From f80188145a63aa7971f306fd47c7244fcf02ff02 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Wed, 6 Aug 2014 12:08:53 +0000 Subject: [PATCH] Create 2062 release branch for CEF3. git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/2062@1783 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- AUTHORS.txt | 28 + CHROMIUM_BUILD_COMPATIBILITY.txt | 12 + DEPS | 7 + LICENSE.txt | 29 + VERSION | 1 + cef.gyp | 1682 ++++++++++ cef.gypi | 30 + cef_create_projects.bat | 2 + cef_create_projects.sh | 2 + cef_paths.gypi | 463 +++ cef_paths2.gypi | 297 ++ include/base/cef_atomic_ref_count.h | 126 + include/base/cef_atomicops.h | 198 ++ include/base/cef_basictypes.h | 86 + include/base/cef_bind.h | 548 +++ include/base/cef_bind_helpers.h | 586 ++++ include/base/cef_build.h | 172 + include/base/cef_callback.h | 807 +++++ include/base/cef_callback_forward.h | 59 + include/base/cef_callback_helpers.h | 93 + include/base/cef_callback_list.h | 444 +++ include/base/cef_cancelable_callback.h | 314 ++ include/base/cef_lock.h | 167 + include/base/cef_logging.h | 746 +++++ include/base/cef_macros.h | 217 ++ include/base/cef_move.h | 259 ++ include/base/cef_platform_thread.h | 113 + include/base/cef_ref_counted.h | 386 +++ include/base/cef_scoped_ptr.h | 623 ++++ include/base/cef_string16.h | 225 ++ include/base/cef_template_util.h | 192 ++ include/base/cef_thread_checker.h | 125 + include/base/cef_thread_collision_warner.h | 287 ++ include/base/cef_trace_event.h | 427 +++ include/base/cef_tuple.h | 1333 ++++++++ include/base/cef_weak_ptr.h | 382 +++ .../cef_atomicops_atomicword_compat.h | 126 + include/base/internal/cef_atomicops_mac.h | 223 ++ include/base/internal/cef_atomicops_x86_gcc.h | 265 ++ .../base/internal/cef_atomicops_x86_msvc.h | 224 ++ include/base/internal/cef_bind_internal.h | 2811 ++++++++++++++++ include/base/internal/cef_bind_internal_win.h | 390 +++ include/base/internal/cef_callback_internal.h | 205 ++ include/base/internal/cef_lock_impl.h | 87 + .../cef_raw_scoped_refptr_mismatch_checker.h | 154 + .../base/internal/cef_thread_checker_impl.h | 70 + include/capi/cef_app_capi.h | 182 + include/capi/cef_auth_callback_capi.h | 75 + include/capi/cef_base_capi.h | 89 + include/capi/cef_browser_capi.h | 557 ++++ .../capi/cef_browser_process_handler_capi.h | 104 + include/capi/cef_callback_capi.h | 89 + include/capi/cef_client_capi.h | 169 + include/capi/cef_command_line_capi.h | 213 ++ include/capi/cef_context_menu_handler_capi.h | 219 ++ include/capi/cef_cookie_capi.h | 176 + include/capi/cef_dialog_handler_capi.h | 106 + include/capi/cef_display_handler_capi.h | 105 + include/capi/cef_dom_capi.h | 447 +++ include/capi/cef_download_handler_capi.h | 127 + include/capi/cef_download_item_capi.h | 155 + include/capi/cef_drag_data_capi.h | 211 ++ include/capi/cef_drag_handler_capi.h | 76 + include/capi/cef_focus_handler_capi.h | 90 + include/capi/cef_frame_capi.h | 220 ++ include/capi/cef_geolocation_capi.h | 79 + include/capi/cef_geolocation_handler_capi.h | 106 + include/capi/cef_jsdialog_handler_capi.h | 133 + include/capi/cef_keyboard_handler_capi.h | 84 + include/capi/cef_life_span_handler_capi.h | 171 + include/capi/cef_load_handler_capi.h | 112 + include/capi/cef_menu_model_capi.h | 388 +++ include/capi/cef_origin_whitelist_capi.h | 106 + include/capi/cef_path_util_capi.h | 58 + include/capi/cef_print_handler_capi.h | 134 + include/capi/cef_print_settings_capi.h | 207 ++ include/capi/cef_process_message_capi.h | 102 + include/capi/cef_process_util_capi.h | 64 + include/capi/cef_render_handler_capi.h | 163 + .../capi/cef_render_process_handler_capi.h | 177 + include/capi/cef_request_capi.h | 293 ++ include/capi/cef_request_context_capi.h | 105 + .../capi/cef_request_context_handler_capi.h | 71 + include/capi/cef_request_handler_capi.h | 226 ++ .../capi/cef_resource_bundle_handler_capi.h | 86 + include/capi/cef_resource_handler_capi.h | 124 + include/capi/cef_response_capi.h | 130 + include/capi/cef_scheme_capi.h | 168 + include/capi/cef_stream_capi.h | 252 ++ include/capi/cef_string_visitor_capi.h | 69 + include/capi/cef_task_capi.h | 159 + include/capi/cef_trace_capi.h | 118 + include/capi/cef_url_capi.h | 82 + include/capi/cef_urlrequest_capi.h | 189 ++ include/capi/cef_v8_capi.h | 851 +++++ include/capi/cef_values_capi.h | 463 +++ include/capi/cef_web_plugin_capi.h | 195 ++ include/capi/cef_xml_reader_capi.h | 278 ++ include/capi/cef_zip_reader_capi.h | 149 + include/cef_app.h | 192 ++ include/cef_application_mac.h | 200 ++ include/cef_auth_callback.h | 64 + include/cef_base.h | 180 + include/cef_browser.h | 582 ++++ include/cef_browser_process_handler.h | 92 + include/cef_callback.h | 75 + include/cef_client.h | 185 ++ include/cef_command_line.h | 208 ++ include/cef_context_menu_handler.h | 210 ++ include/cef_cookie.h | 166 + include/cef_dialog_handler.h | 98 + include/cef_display_handler.h | 98 + include/cef_dom.h | 435 +++ include/cef_download_handler.h | 112 + include/cef_download_item.h | 148 + include/cef_drag_data.h | 198 ++ include/cef_drag_handler.h | 66 + include/cef_focus_handler.h | 81 + include/cef_frame.h | 224 ++ include/cef_geolocation.h | 66 + include/cef_geolocation_handler.h | 97 + include/cef_jsdialog_handler.h | 128 + include/cef_keyboard_handler.h | 74 + include/cef_life_span_handler.h | 164 + include/cef_load_handler.h | 107 + include/cef_menu_model.h | 402 +++ include/cef_origin_whitelist.h | 103 + include/cef_path_util.h | 52 + include/cef_print_handler.h | 120 + include/cef_print_settings.h | 208 ++ include/cef_process_message.h | 91 + include/cef_process_util.h | 57 + include/cef_render_handler.h | 170 + include/cef_render_process_handler.h | 168 + include/cef_request.h | 297 ++ include/cef_request_context.h | 94 + include/cef_request_context_handler.h | 58 + include/cef_request_handler.h | 245 ++ include/cef_resource_bundle_handler.h | 73 + include/cef_resource_handler.h | 116 + include/cef_response.h | 120 + include/cef_runnable.h | 342 ++ include/cef_sandbox_win.h | 92 + include/cef_scheme.h | 161 + include/cef_stream.h | 242 ++ include/cef_string_visitor.h | 55 + include/cef_task.h | 148 + include/cef_trace.h | 111 + include/cef_url.h | 77 + include/cef_urlrequest.h | 183 + include/cef_v8.h | 879 +++++ include/cef_values.h | 471 +++ include/cef_web_plugin.h | 178 + include/cef_xml_reader.h | 268 ++ include/cef_zip_reader.h | 141 + include/internal/cef_export.h | 55 + include/internal/cef_linux.h | 130 + include/internal/cef_logging_internal.h | 66 + include/internal/cef_mac.h | 137 + include/internal/cef_ptr.h | 161 + include/internal/cef_string.h | 113 + include/internal/cef_string_list.h | 88 + include/internal/cef_string_map.h | 97 + include/internal/cef_string_multimap.h | 105 + include/internal/cef_string_types.h | 205 ++ include/internal/cef_string_wrappers.h | 715 ++++ include/internal/cef_thread_internal.h | 74 + include/internal/cef_time.h | 88 + include/internal/cef_trace_event_internal.h | 124 + include/internal/cef_types.h | 1805 ++++++++++ include/internal/cef_types_linux.h | 119 + include/internal/cef_types_mac.h | 132 + include/internal/cef_types_win.h | 109 + include/internal/cef_types_wrappers.h | 718 ++++ include/internal/cef_win.h | 156 + include/wrapper/cef_byte_read_handler.h | 79 + include/wrapper/cef_closure_task.h | 101 + include/wrapper/cef_helpers.h | 81 + include/wrapper/cef_message_router.h | 428 +++ include/wrapper/cef_stream_resource_handler.h | 104 + include/wrapper/cef_xml_object.h | 196 ++ include/wrapper/cef_zip_archive.h | 143 + libcef/browser/browser_context.h | 24 + libcef/browser/browser_context_impl.cc | 155 + libcef/browser/browser_context_impl.h | 69 + libcef/browser/browser_context_proxy.cc | 152 + libcef/browser/browser_context_proxy.h | 82 + libcef/browser/browser_host_impl.cc | 2955 +++++++++++++++++ libcef/browser/browser_host_impl.h | 679 ++++ libcef/browser/browser_host_impl_linux.cc | 431 +++ libcef/browser/browser_host_impl_mac.mm | 696 ++++ libcef/browser/browser_host_impl_win.cc | 942 ++++++ libcef/browser/browser_info.cc | 112 + libcef/browser/browser_info.h | 86 + libcef/browser/browser_main.cc | 205 ++ libcef/browser/browser_main.h | 86 + libcef/browser/browser_main_linux.cc | 11 + libcef/browser/browser_main_mac.mm | 24 + libcef/browser/browser_main_win.cc | 32 + libcef/browser/browser_message_filter.cc | 110 + libcef/browser/browser_message_filter.h | 52 + libcef/browser/browser_message_loop.cc | 28 + libcef/browser/browser_message_loop.h | 33 + libcef/browser/browser_pref_store.cc | 39 + libcef/browser/browser_pref_store.h | 25 + libcef/browser/browser_settings.cc | 127 + libcef/browser/browser_settings.h | 15 + libcef/browser/browser_urlrequest_impl.cc | 540 +++ libcef/browser/browser_urlrequest_impl.h | 37 + libcef/browser/chrome_browser_process_stub.cc | 269 ++ libcef/browser/chrome_browser_process_stub.h | 104 + libcef/browser/chrome_scheme_handler.cc | 403 +++ libcef/browser/chrome_scheme_handler.h | 51 + libcef/browser/content_browser_client.cc | 1049 ++++++ libcef/browser/content_browser_client.h | 199 ++ libcef/browser/context.cc | 423 +++ libcef/browser/context.h | 115 + libcef/browser/context_menu_params_impl.cc | 107 + libcef/browser/context_menu_params_impl.h | 40 + libcef/browser/cookie_manager_impl.cc | 449 +++ libcef/browser/cookie_manager_impl.h | 53 + libcef/browser/devtools_delegate.cc | 172 + libcef/browser/devtools_delegate.h | 52 + libcef/browser/devtools_frontend.cc | 107 + libcef/browser/devtools_frontend.h | 64 + libcef/browser/devtools_scheme_handler.cc | 54 + libcef/browser/devtools_scheme_handler.h | 18 + libcef/browser/download_item_impl.cc | 102 + libcef/browser/download_item_impl.h | 44 + libcef/browser/download_manager_delegate.cc | 349 ++ libcef/browser/download_manager_delegate.h | 48 + libcef/browser/frame_host_impl.cc | 279 ++ libcef/browser/frame_host_impl.h | 96 + libcef/browser/geolocation_impl.cc | 101 + libcef/browser/internal_scheme_handler.cc | 178 + libcef/browser/internal_scheme_handler.h | 53 + libcef/browser/javascript_dialog.h | 67 + libcef/browser/javascript_dialog_linux.cc | 28 + libcef/browser/javascript_dialog_mac.mm | 155 + libcef/browser/javascript_dialog_manager.cc | 226 ++ libcef/browser/javascript_dialog_manager.h | 64 + libcef/browser/javascript_dialog_win.cc | 228 ++ .../media_capture_devices_dispatcher.cc | 141 + .../media_capture_devices_dispatcher.h | 76 + libcef/browser/menu_creator.cc | 310 ++ libcef/browser/menu_creator.h | 72 + libcef/browser/menu_creator_runner_linux.cc | 77 + libcef/browser/menu_creator_runner_linux.h | 28 + libcef/browser/menu_creator_runner_mac.h | 29 + libcef/browser/menu_creator_runner_mac.mm | 94 + libcef/browser/menu_creator_runner_win.cc | 55 + libcef/browser/menu_creator_runner_win.h | 25 + libcef/browser/menu_model_impl.cc | 706 ++++ libcef/browser/menu_model_impl.h | 144 + libcef/browser/navigate_params.cc | 20 + libcef/browser/navigate_params.h | 85 + libcef/browser/origin_whitelist_impl.cc | 288 ++ libcef/browser/origin_whitelist_impl.h | 28 + libcef/browser/path_util_impl.cc | 44 + libcef/browser/print_settings_impl.cc | 165 + libcef/browser/print_settings_impl.h | 56 + libcef/browser/printing/print_dialog_linux.cc | 275 ++ libcef/browser/printing/print_dialog_linux.h | 85 + libcef/browser/printing/print_view_manager.cc | 64 + libcef/browser/printing/print_view_manager.h | 51 + .../printing/print_view_manager_base.cc | 578 ++++ .../printing/print_view_manager_base.h | 179 + .../printing/printing_message_filter.cc | 446 +++ .../printing/printing_message_filter.h | 131 + libcef/browser/process_util_impl.cc | 31 + libcef/browser/proxy_stubs.cc | 18 + libcef/browser/render_widget_host_view_osr.cc | 1081 ++++++ libcef/browser/render_widget_host_view_osr.h | 335 ++ .../render_widget_host_view_osr_linux.cc | 25 + .../render_widget_host_view_osr_mac.mm | 281 ++ .../render_widget_host_view_osr_win.cc | 59 + libcef/browser/request_context_impl.cc | 112 + libcef/browser/request_context_impl.h | 37 + .../resource_dispatcher_host_delegate.cc | 122 + .../resource_dispatcher_host_delegate.h | 41 + libcef/browser/resource_request_job.cc | 559 ++++ libcef/browser/resource_request_job.h | 85 + libcef/browser/scheme_handler.cc | 86 + libcef/browser/scheme_handler.h | 36 + libcef/browser/scheme_impl.cc | 362 ++ libcef/browser/scheme_impl.h | 24 + .../speech_recognition_manager_delegate.cc | 228 ++ .../speech_recognition_manager_delegate.h | 63 + libcef/browser/stream_impl.cc | 318 ++ libcef/browser/stream_impl.h | 171 + libcef/browser/text_input_client_osr_mac.h | 89 + libcef/browser/text_input_client_osr_mac.mm | 359 ++ libcef/browser/thread_util.h | 49 + libcef/browser/trace_impl.cc | 52 + libcef/browser/trace_subscriber.cc | 76 + libcef/browser/trace_subscriber.h | 35 + libcef/browser/url_network_delegate.cc | 184 + libcef/browser/url_network_delegate.h | 34 + libcef/browser/url_request_context_getter.cc | 394 +++ libcef/browser/url_request_context_getter.h | 133 + .../url_request_context_getter_proxy.cc | 42 + .../url_request_context_getter_proxy.h | 46 + libcef/browser/url_request_context_proxy.cc | 167 + libcef/browser/url_request_context_proxy.h | 43 + libcef/browser/url_request_interceptor.cc | 94 + libcef/browser/url_request_interceptor.h | 33 + libcef/browser/url_request_user_data.cc | 18 + libcef/browser/url_request_user_data.h | 27 + libcef/browser/web_contents_view_osr.cc | 167 + libcef/browser/web_contents_view_osr.h | 76 + libcef/browser/web_plugin_impl.cc | 224 ++ libcef/browser/web_plugin_impl.h | 27 + libcef/browser/window_delegate_view.cc | 63 + libcef/browser/window_delegate_view.h | 50 + libcef/browser/window_x11.cc | 374 +++ libcef/browser/window_x11.h | 72 + libcef/browser/xml_reader_impl.cc | 446 +++ libcef/browser/xml_reader_impl.h | 73 + libcef/browser/zip_reader_impl.cc | 280 ++ libcef/browser/zip_reader_impl.h | 55 + libcef/common/base_impl.cc | 345 ++ libcef/common/breakpad_client.cc | 58 + libcef/common/breakpad_client.h | 43 + libcef/common/cef_message_generator.cc | 33 + libcef/common/cef_message_generator.h | 7 + libcef/common/cef_messages.cc | 116 + libcef/common/cef_messages.h | 251 ++ libcef/common/cef_switches.cc | 88 + libcef/common/cef_switches.h | 44 + libcef/common/command_line_impl.cc | 159 + libcef/common/command_line_impl.h | 50 + libcef/common/content_client.cc | 256 ++ libcef/common/content_client.h | 92 + libcef/common/drag_data_impl.cc | 194 ++ libcef/common/drag_data_impl.h | 66 + libcef/common/http_header_utils.cc | 43 + libcef/common/http_header_utils.h | 22 + libcef/common/main_delegate.cc | 594 ++++ libcef/common/main_delegate.h | 69 + libcef/common/net_resource_provider.cc | 10 + libcef/common/net_resource_provider.h | 14 + libcef/common/process_message_impl.cc | 76 + libcef/common/process_message_impl.h | 35 + libcef/common/request_impl.cc | 815 +++++ libcef/common/request_impl.h | 173 + libcef/common/response_impl.cc | 205 ++ libcef/common/response_impl.h | 58 + libcef/common/response_manager.cc | 58 + libcef/common/response_manager.h | 62 + libcef/common/scheme_registrar_impl.cc | 67 + libcef/common/scheme_registrar_impl.h | 46 + libcef/common/scheme_registration.cc | 68 + libcef/common/scheme_registration.h | 29 + libcef/common/string_list_impl.cc | 57 + libcef/common/string_map_impl.cc | 92 + libcef/common/string_multimap_impl.cc | 116 + libcef/common/string_types_impl.cc | 270 ++ libcef/common/task_impl.cc | 38 + libcef/common/task_runner_impl.cc | 147 + libcef/common/task_runner_impl.h | 38 + libcef/common/time_impl.cc | 93 + libcef/common/time_util.h | 16 + libcef/common/tracker.cc | 83 + libcef/common/tracker.h | 77 + libcef/common/upload_data.cc | 37 + libcef/common/upload_data.h | 83 + libcef/common/url_impl.cc | 87 + libcef/common/urlrequest_impl.cc | 46 + libcef/common/value_base.cc | 201 ++ libcef/common/value_base.h | 415 +++ libcef/common/values_impl.cc | 839 +++++ libcef/common/values_impl.h | 209 ++ libcef/renderer/browser_impl.cc | 833 +++++ libcef/renderer/browser_impl.h | 163 + libcef/renderer/content_renderer_client.cc | 788 +++++ libcef/renderer/content_renderer_client.h | 140 + libcef/renderer/dom_document_impl.cc | 262 ++ libcef/renderer/dom_document_impl.h | 66 + libcef/renderer/dom_event_impl.cc | 154 + libcef/renderer/dom_event_impl.h | 43 + libcef/renderer/dom_node_impl.cc | 479 +++ libcef/renderer/dom_node_impl.h | 64 + libcef/renderer/frame_impl.cc | 272 ++ libcef/renderer/frame_impl.h | 70 + libcef/renderer/render_frame_observer.cc | 24 + libcef/renderer/render_frame_observer.h | 26 + libcef/renderer/render_message_filter.cc | 75 + libcef/renderer/render_message_filter.h | 39 + libcef/renderer/render_process_observer.cc | 65 + libcef/renderer/render_process_observer.h | 35 + libcef/renderer/render_urlrequest_impl.cc | 378 +++ libcef/renderer/render_urlrequest_impl.h | 37 + libcef/renderer/thread_util.h | 59 + libcef/renderer/v8_impl.cc | 2124 ++++++++++++ libcef/renderer/v8_impl.h | 391 +++ libcef/renderer/webkit_glue.cc | 97 + libcef/renderer/webkit_glue.h | 43 + libcef/resources/about_version.html | 123 + libcef/resources/cef_resources.grd | 20 + libcef/resources/cef_strings.grd | 282 ++ libcef/resources/devtools_discovery_page.html | 54 + libcef/resources/framework-Info.plist | 18 + .../grit_stub/grit/browser_resources.h | 2 + .../grit_stub/grit/generated_resources.h | 2 + libcef/resources/print_preview_page_stub.html | 1 + libcef/utility/content_utility_client.cc | 60 + libcef/utility/content_utility_client.h | 33 + libcef/utility/printing_handler.cc | 418 +++ libcef/utility/printing_handler.h | 64 + libcef_dll/base/cef_atomicops_x86_gcc.cc | 100 + libcef_dll/base/cef_bind_helpers.cc | 14 + libcef_dll/base/cef_callback_helpers.cc | 42 + libcef_dll/base/cef_callback_internal.cc | 38 + libcef_dll/base/cef_lock.cc | 44 + libcef_dll/base/cef_lock_impl.cc | 92 + libcef_dll/base/cef_logging.cc | 259 ++ libcef_dll/base/cef_ref_counted.cc | 53 + libcef_dll/base/cef_string16.cc | 89 + libcef_dll/base/cef_thread_checker_impl.cc | 34 + .../base/cef_thread_collision_warner.cc | 65 + libcef_dll/base/cef_weak_ptr.cc | 77 + ...allow_certificate_error_callback_cpptoc.cc | 47 + .../allow_certificate_error_callback_cpptoc.h | 39 + libcef_dll/cpptoc/app_cpptoc.cc | 125 + libcef_dll/cpptoc/app_cpptoc.h | 36 + libcef_dll/cpptoc/auth_callback_cpptoc.cc | 65 + libcef_dll/cpptoc/auth_callback_cpptoc.h | 37 + libcef_dll/cpptoc/base_cpptoc.h | 148 + .../cpptoc/before_download_callback_cpptoc.cc | 49 + .../cpptoc/before_download_callback_cpptoc.h | 37 + libcef_dll/cpptoc/binary_value_cpptoc.cc | 134 + libcef_dll/cpptoc/binary_value_cpptoc.h | 37 + libcef_dll/cpptoc/browser_cpptoc.cc | 390 +++ libcef_dll/cpptoc/browser_cpptoc.h | 38 + libcef_dll/cpptoc/browser_host_cpptoc.cc | 818 +++++ libcef_dll/cpptoc/browser_host_cpptoc.h | 39 + .../cpptoc/browser_process_handler_cpptoc.cc | 105 + .../cpptoc/browser_process_handler_cpptoc.h | 37 + libcef_dll/cpptoc/callback_cpptoc.cc | 53 + libcef_dll/cpptoc/callback_cpptoc.h | 36 + libcef_dll/cpptoc/client_cpptoc.cc | 294 ++ libcef_dll/cpptoc/client_cpptoc.h | 36 + libcef_dll/cpptoc/command_line_cpptoc.cc | 428 +++ libcef_dll/cpptoc/command_line_cpptoc.h | 37 + .../cpptoc/completion_callback_cpptoc.cc | 44 + .../cpptoc/completion_callback_cpptoc.h | 37 + .../cpptoc/context_menu_handler_cpptoc.cc | 132 + .../cpptoc/context_menu_handler_cpptoc.h | 37 + .../cpptoc/context_menu_params_cpptoc.cc | 279 ++ .../cpptoc/context_menu_params_cpptoc.h | 37 + libcef_dll/cpptoc/cookie_manager_cpptoc.cc | 225 ++ libcef_dll/cpptoc/cookie_manager_cpptoc.h | 37 + libcef_dll/cpptoc/cookie_visitor_cpptoc.cc | 70 + libcef_dll/cpptoc/cookie_visitor_cpptoc.h | 37 + libcef_dll/cpptoc/cpptoc.h | 165 + libcef_dll/cpptoc/dialog_handler_cpptoc.cc | 71 + libcef_dll/cpptoc/dialog_handler_cpptoc.h | 37 + libcef_dll/cpptoc/dictionary_value_cpptoc.cc | 577 ++++ libcef_dll/cpptoc/dictionary_value_cpptoc.h | 37 + libcef_dll/cpptoc/display_handler_cpptoc.cc | 155 + libcef_dll/cpptoc/display_handler_cpptoc.h | 37 + libcef_dll/cpptoc/domdocument_cpptoc.cc | 303 ++ libcef_dll/cpptoc/domdocument_cpptoc.h | 37 + libcef_dll/cpptoc/domevent_cpptoc.cc | 159 + libcef_dll/cpptoc/domevent_cpptoc.h | 36 + libcef_dll/cpptoc/domevent_listener_cpptoc.cc | 49 + libcef_dll/cpptoc/domevent_listener_cpptoc.h | 37 + libcef_dll/cpptoc/domnode_cpptoc.cc | 493 +++ libcef_dll/cpptoc/domnode_cpptoc.h | 36 + libcef_dll/cpptoc/domvisitor_cpptoc.cc | 48 + libcef_dll/cpptoc/domvisitor_cpptoc.h | 36 + libcef_dll/cpptoc/download_handler_cpptoc.cc | 100 + libcef_dll/cpptoc/download_handler_cpptoc.h | 37 + .../cpptoc/download_item_callback_cpptoc.cc | 44 + .../cpptoc/download_item_callback_cpptoc.h | 37 + libcef_dll/cpptoc/download_item_cpptoc.cc | 284 ++ libcef_dll/cpptoc/download_item_cpptoc.h | 37 + libcef_dll/cpptoc/drag_data_cpptoc.cc | 401 +++ libcef_dll/cpptoc/drag_data_cpptoc.h | 36 + libcef_dll/cpptoc/drag_handler_cpptoc.cc | 59 + libcef_dll/cpptoc/drag_handler_cpptoc.h | 37 + .../cpptoc/end_tracing_callback_cpptoc.cc | 51 + .../cpptoc/end_tracing_callback_cpptoc.h | 37 + .../cpptoc/file_dialog_callback_cpptoc.cc | 67 + .../cpptoc/file_dialog_callback_cpptoc.h | 37 + libcef_dll/cpptoc/focus_handler_cpptoc.cc | 90 + libcef_dll/cpptoc/focus_handler_cpptoc.h | 37 + libcef_dll/cpptoc/frame_cpptoc.cc | 401 +++ libcef_dll/cpptoc/frame_cpptoc.h | 40 + .../cpptoc/geolocation_callback_cpptoc.cc | 45 + .../cpptoc/geolocation_callback_cpptoc.h | 37 + .../cpptoc/geolocation_handler_cpptoc.cc | 95 + .../cpptoc/geolocation_handler_cpptoc.h | 37 + .../cpptoc/get_geolocation_callback_cpptoc.cc | 57 + .../cpptoc/get_geolocation_callback_cpptoc.h | 37 + libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc | 46 + libcef_dll/cpptoc/jsdialog_callback_cpptoc.h | 37 + libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc | 151 + libcef_dll/cpptoc/jsdialog_handler_cpptoc.h | 37 + libcef_dll/cpptoc/keyboard_handler_cpptoc.cc | 110 + libcef_dll/cpptoc/keyboard_handler_cpptoc.h | 37 + libcef_dll/cpptoc/life_span_handler_cpptoc.cc | 211 ++ libcef_dll/cpptoc/life_span_handler_cpptoc.h | 39 + libcef_dll/cpptoc/list_value_cpptoc.cc | 528 +++ libcef_dll/cpptoc/list_value_cpptoc.h | 36 + libcef_dll/cpptoc/load_handler_cpptoc.cc | 133 + libcef_dll/cpptoc/load_handler_cpptoc.h | 37 + libcef_dll/cpptoc/menu_model_cpptoc.cc | 1020 ++++++ libcef_dll/cpptoc/menu_model_cpptoc.h | 36 + .../cpptoc/permission_handler_cpptoc.cc | 67 + libcef_dll/cpptoc/permission_handler_cpptoc.h | 41 + libcef_dll/cpptoc/post_data_cpptoc.cc | 164 + libcef_dll/cpptoc/post_data_cpptoc.h | 36 + libcef_dll/cpptoc/post_data_element_cpptoc.cc | 180 + libcef_dll/cpptoc/post_data_element_cpptoc.h | 37 + .../cpptoc/print_dialog_callback_cpptoc.cc | 64 + .../cpptoc/print_dialog_callback_cpptoc.h | 37 + libcef_dll/cpptoc/print_handler_cpptoc.cc | 121 + libcef_dll/cpptoc/print_handler_cpptoc.h | 37 + .../cpptoc/print_job_callback_cpptoc.cc | 43 + libcef_dll/cpptoc/print_job_callback_cpptoc.h | 37 + libcef_dll/cpptoc/print_settings_cpptoc.cc | 447 +++ libcef_dll/cpptoc/print_settings_cpptoc.h | 37 + libcef_dll/cpptoc/process_message_cpptoc.cc | 132 + libcef_dll/cpptoc/process_message_cpptoc.h | 37 + libcef_dll/cpptoc/quota_callback_cpptoc.cc | 56 + libcef_dll/cpptoc/quota_callback_cpptoc.h | 37 + libcef_dll/cpptoc/read_handler_cpptoc.cc | 115 + libcef_dll/cpptoc/read_handler_cpptoc.h | 37 + libcef_dll/cpptoc/render_handler_cpptoc.cc | 359 ++ libcef_dll/cpptoc/render_handler_cpptoc.h | 37 + .../cpptoc/render_process_handler_cpptoc.cc | 321 ++ .../cpptoc/render_process_handler_cpptoc.h | 37 + libcef_dll/cpptoc/request_context_cpptoc.cc | 112 + libcef_dll/cpptoc/request_context_cpptoc.h | 37 + .../cpptoc/request_context_handler_cpptoc.cc | 50 + .../cpptoc/request_context_handler_cpptoc.h | 37 + libcef_dll/cpptoc/request_cpptoc.cc | 341 ++ libcef_dll/cpptoc/request_cpptoc.h | 36 + libcef_dll/cpptoc/request_handler_cpptoc.cc | 398 +++ libcef_dll/cpptoc/request_handler_cpptoc.h | 37 + .../cpptoc/resource_bundle_handler_cpptoc.cc | 98 + .../cpptoc/resource_bundle_handler_cpptoc.h | 37 + libcef_dll/cpptoc/resource_handler_cpptoc.cc | 203 ++ libcef_dll/cpptoc/resource_handler_cpptoc.h | 37 + libcef_dll/cpptoc/response_cpptoc.cc | 224 ++ libcef_dll/cpptoc/response_cpptoc.h | 36 + .../cpptoc/run_file_dialog_callback_cpptoc.cc | 61 + .../cpptoc/run_file_dialog_callback_cpptoc.h | 39 + .../cpptoc/scheme_handler_factory_cpptoc.cc | 67 + .../cpptoc/scheme_handler_factory_cpptoc.h | 37 + libcef_dll/cpptoc/scheme_registrar_cpptoc.cc | 55 + libcef_dll/cpptoc/scheme_registrar_cpptoc.h | 37 + libcef_dll/cpptoc/stream_reader_cpptoc.cc | 172 + libcef_dll/cpptoc/stream_reader_cpptoc.h | 37 + libcef_dll/cpptoc/stream_writer_cpptoc.cc | 154 + libcef_dll/cpptoc/stream_writer_cpptoc.h | 37 + libcef_dll/cpptoc/string_visitor_cpptoc.cc | 45 + libcef_dll/cpptoc/string_visitor_cpptoc.h | 37 + libcef_dll/cpptoc/task_cpptoc.cc | 41 + libcef_dll/cpptoc/task_cpptoc.h | 36 + libcef_dll/cpptoc/task_runner_cpptoc.cc | 153 + libcef_dll/cpptoc/task_runner_cpptoc.h | 36 + libcef_dll/cpptoc/urlrequest_client_cpptoc.cc | 154 + libcef_dll/cpptoc/urlrequest_client_cpptoc.h | 37 + libcef_dll/cpptoc/urlrequest_cpptoc.cc | 152 + libcef_dll/cpptoc/urlrequest_cpptoc.h | 36 + libcef_dll/cpptoc/v8accessor_cpptoc.cc | 126 + libcef_dll/cpptoc/v8accessor_cpptoc.h | 36 + libcef_dll/cpptoc/v8context_cpptoc.cc | 261 ++ libcef_dll/cpptoc/v8context_cpptoc.h | 36 + libcef_dll/cpptoc/v8exception_cpptoc.cc | 154 + libcef_dll/cpptoc/v8exception_cpptoc.h | 37 + libcef_dll/cpptoc/v8handler_cpptoc.cc | 99 + libcef_dll/cpptoc/v8handler_cpptoc.h | 36 + libcef_dll/cpptoc/v8stack_frame_cpptoc.cc | 157 + libcef_dll/cpptoc/v8stack_frame_cpptoc.h | 37 + libcef_dll/cpptoc/v8stack_trace_cpptoc.cc | 94 + libcef_dll/cpptoc/v8stack_trace_cpptoc.h | 37 + libcef_dll/cpptoc/v8value_cpptoc.cc | 973 ++++++ libcef_dll/cpptoc/v8value_cpptoc.h | 36 + libcef_dll/cpptoc/web_plugin_info_cpptoc.cc | 94 + libcef_dll/cpptoc/web_plugin_info_cpptoc.h | 37 + .../cpptoc/web_plugin_info_visitor_cpptoc.cc | 56 + .../cpptoc/web_plugin_info_visitor_cpptoc.h | 37 + .../web_plugin_unstable_callback_cpptoc.cc | 53 + .../web_plugin_unstable_callback_cpptoc.h | 38 + libcef_dll/cpptoc/write_handler_cpptoc.cc | 116 + libcef_dll/cpptoc/write_handler_cpptoc.h | 37 + libcef_dll/cpptoc/xml_reader_cpptoc.cc | 558 ++++ libcef_dll/cpptoc/xml_reader_cpptoc.h | 36 + libcef_dll/cpptoc/zip_reader_cpptoc.cc | 249 ++ libcef_dll/cpptoc/zip_reader_cpptoc.h | 36 + ...allow_certificate_error_callback_ctocpp.cc | 35 + .../allow_certificate_error_callback_ctocpp.h | 45 + libcef_dll/ctocpp/app_ctocpp.cc | 106 + libcef_dll/ctocpp/app_ctocpp.h | 48 + libcef_dll/ctocpp/auth_callback_ctocpp.cc | 55 + libcef_dll/ctocpp/auth_callback_ctocpp.h | 44 + libcef_dll/ctocpp/base_ctocpp.h | 101 + .../ctocpp/before_download_callback_ctocpp.cc | 39 + .../ctocpp/before_download_callback_ctocpp.h | 43 + libcef_dll/ctocpp/binary_value_ctocpp.cc | 118 + libcef_dll/ctocpp/binary_value_ctocpp.h | 47 + libcef_dll/ctocpp/browser_ctocpp.cc | 343 ++ libcef_dll/ctocpp/browser_ctocpp.h | 64 + libcef_dll/ctocpp/browser_host_ctocpp.cc | 582 ++++ libcef_dll/ctocpp/browser_host_ctocpp.h | 96 + .../ctocpp/browser_process_handler_ctocpp.cc | 83 + .../ctocpp/browser_process_handler_ctocpp.h | 47 + libcef_dll/ctocpp/callback_ctocpp.cc | 43 + libcef_dll/ctocpp/callback_ctocpp.h | 41 + libcef_dll/ctocpp/client_ctocpp.cc | 235 ++ libcef_dll/ctocpp/client_ctocpp.h | 55 + libcef_dll/ctocpp/command_line_ctocpp.cc | 398 +++ libcef_dll/ctocpp/command_line_ctocpp.h | 63 + .../ctocpp/completion_callback_ctocpp.cc | 33 + .../ctocpp/completion_callback_ctocpp.h | 42 + .../ctocpp/context_menu_handler_ctocpp.cc | 116 + .../ctocpp/context_menu_handler_ctocpp.h | 49 + .../ctocpp/context_menu_params_ctocpp.cc | 236 ++ .../ctocpp/context_menu_params_ctocpp.h | 56 + libcef_dll/ctocpp/cookie_manager_ctocpp.cc | 199 ++ libcef_dll/ctocpp/cookie_manager_ctocpp.h | 54 + libcef_dll/ctocpp/cookie_visitor_ctocpp.cc | 47 + libcef_dll/ctocpp/cookie_visitor_ctocpp.h | 43 + libcef_dll/ctocpp/ctocpp.h | 117 + libcef_dll/ctocpp/dialog_handler_ctocpp.cc | 69 + libcef_dll/ctocpp/dialog_handler_ctocpp.h | 46 + libcef_dll/ctocpp/dictionary_value_ctocpp.cc | 517 +++ libcef_dll/ctocpp/dictionary_value_ctocpp.h | 71 + libcef_dll/ctocpp/display_handler_ctocpp.cc | 136 + libcef_dll/ctocpp/display_handler_ctocpp.h | 51 + libcef_dll/ctocpp/domdocument_ctocpp.cc | 255 ++ libcef_dll/ctocpp/domdocument_ctocpp.h | 57 + libcef_dll/ctocpp/domevent_ctocpp.cc | 131 + libcef_dll/ctocpp/domevent_ctocpp.h | 47 + libcef_dll/ctocpp/domevent_listener_ctocpp.cc | 40 + libcef_dll/ctocpp/domevent_listener_ctocpp.h | 42 + libcef_dll/ctocpp/domnode_ctocpp.cc | 436 +++ libcef_dll/ctocpp/domnode_ctocpp.h | 67 + libcef_dll/ctocpp/domvisitor_ctocpp.cc | 40 + libcef_dll/ctocpp/domvisitor_ctocpp.h | 40 + libcef_dll/ctocpp/download_handler_ctocpp.cc | 88 + libcef_dll/ctocpp/download_handler_ctocpp.h | 48 + .../ctocpp/download_item_callback_ctocpp.cc | 33 + .../ctocpp/download_item_callback_ctocpp.h | 42 + libcef_dll/ctocpp/download_item_ctocpp.cc | 241 ++ libcef_dll/ctocpp/download_item_ctocpp.h | 57 + libcef_dll/ctocpp/drag_data_ctocpp.cc | 358 ++ libcef_dll/ctocpp/drag_data_ctocpp.h | 63 + libcef_dll/ctocpp/drag_handler_ctocpp.cc | 51 + libcef_dll/ctocpp/drag_handler_ctocpp.h | 43 + .../ctocpp/end_tracing_callback_ctocpp.cc | 40 + .../ctocpp/end_tracing_callback_ctocpp.h | 42 + .../ctocpp/file_dialog_callback_ctocpp.cc | 56 + .../ctocpp/file_dialog_callback_ctocpp.h | 44 + libcef_dll/ctocpp/focus_handler_ctocpp.cc | 79 + libcef_dll/ctocpp/focus_handler_ctocpp.h | 45 + libcef_dll/ctocpp/frame_ctocpp.cc | 351 ++ libcef_dll/ctocpp/frame_ctocpp.h | 69 + .../ctocpp/geolocation_callback_ctocpp.cc | 34 + .../ctocpp/geolocation_callback_ctocpp.h | 42 + .../ctocpp/geolocation_handler_ctocpp.cc | 81 + .../ctocpp/geolocation_handler_ctocpp.h | 46 + .../ctocpp/get_geolocation_callback_ctocpp.cc | 36 + .../ctocpp/get_geolocation_callback_ctocpp.h | 42 + libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc | 38 + libcef_dll/ctocpp/jsdialog_callback_ctocpp.h | 42 + libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc | 129 + libcef_dll/ctocpp/jsdialog_handler_ctocpp.h | 52 + libcef_dll/ctocpp/keyboard_handler_ctocpp.cc | 81 + libcef_dll/ctocpp/keyboard_handler_ctocpp.h | 46 + libcef_dll/ctocpp/life_span_handler_ctocpp.cc | 156 + libcef_dll/ctocpp/life_span_handler_ctocpp.h | 53 + libcef_dll/ctocpp/list_value_ctocpp.cc | 476 +++ libcef_dll/ctocpp/list_value_ctocpp.h | 64 + libcef_dll/ctocpp/load_handler_ctocpp.cc | 121 + libcef_dll/ctocpp/load_handler_ctocpp.h | 50 + libcef_dll/ctocpp/menu_model_ctocpp.cc | 839 +++++ libcef_dll/ctocpp/menu_model_ctocpp.h | 98 + .../ctocpp/permission_handler_ctocpp.cc | 56 + libcef_dll/ctocpp/permission_handler_ctocpp.h | 47 + libcef_dll/ctocpp/post_data_ctocpp.cc | 150 + libcef_dll/ctocpp/post_data_ctocpp.h | 45 + libcef_dll/ctocpp/post_data_element_ctocpp.cc | 153 + libcef_dll/ctocpp/post_data_element_ctocpp.h | 49 + .../ctocpp/print_dialog_callback_ctocpp.cc | 51 + .../ctocpp/print_dialog_callback_ctocpp.h | 43 + libcef_dll/ctocpp/print_handler_ctocpp.cc | 105 + libcef_dll/ctocpp/print_handler_ctocpp.h | 49 + .../ctocpp/print_job_callback_ctocpp.cc | 33 + libcef_dll/ctocpp/print_job_callback_ctocpp.h | 42 + libcef_dll/ctocpp/print_settings_ctocpp.cc | 367 ++ libcef_dll/ctocpp/print_settings_ctocpp.h | 67 + libcef_dll/ctocpp/process_message_ctocpp.cc | 110 + libcef_dll/ctocpp/process_message_ctocpp.h | 46 + libcef_dll/ctocpp/quota_callback_ctocpp.cc | 44 + libcef_dll/ctocpp/quota_callback_ctocpp.h | 43 + libcef_dll/ctocpp/read_handler_ctocpp.cc | 98 + libcef_dll/ctocpp/read_handler_ctocpp.h | 46 + libcef_dll/ctocpp/render_handler_ctocpp.cc | 275 ++ libcef_dll/ctocpp/render_handler_ctocpp.h | 63 + .../ctocpp/render_process_handler_ctocpp.cc | 284 ++ .../ctocpp/render_process_handler_ctocpp.h | 63 + libcef_dll/ctocpp/request_context_ctocpp.cc | 96 + libcef_dll/ctocpp/request_context_ctocpp.h | 44 + .../ctocpp/request_context_handler_ctocpp.cc | 37 + .../ctocpp/request_context_handler_ctocpp.h | 42 + libcef_dll/ctocpp/request_ctocpp.cc | 303 ++ libcef_dll/ctocpp/request_ctocpp.h | 56 + libcef_dll/ctocpp/request_handler_ctocpp.cc | 356 ++ libcef_dll/ctocpp/request_handler_ctocpp.h | 71 + .../ctocpp/resource_bundle_handler_ctocpp.cc | 56 + .../ctocpp/resource_bundle_handler_ctocpp.h | 44 + libcef_dll/ctocpp/resource_handler_ctocpp.cc | 136 + libcef_dll/ctocpp/resource_handler_ctocpp.h | 50 + libcef_dll/ctocpp/response_ctocpp.cc | 202 ++ libcef_dll/ctocpp/response_ctocpp.h | 49 + .../ctocpp/run_file_dialog_callback_ctocpp.cc | 54 + .../ctocpp/run_file_dialog_callback_ctocpp.h | 46 + .../ctocpp/scheme_handler_factory_ctocpp.cc | 56 + .../ctocpp/scheme_handler_factory_ctocpp.h | 44 + libcef_dll/ctocpp/scheme_registrar_ctocpp.cc | 46 + libcef_dll/ctocpp/scheme_registrar_ctocpp.h | 43 + libcef_dll/ctocpp/stream_reader_ctocpp.cc | 154 + libcef_dll/ctocpp/stream_reader_ctocpp.h | 46 + libcef_dll/ctocpp/stream_writer_ctocpp.cc | 136 + libcef_dll/ctocpp/stream_writer_ctocpp.h | 46 + libcef_dll/ctocpp/string_visitor_ctocpp.cc | 36 + libcef_dll/ctocpp/string_visitor_ctocpp.h | 42 + libcef_dll/ctocpp/task_ctocpp.cc | 33 + libcef_dll/ctocpp/task_ctocpp.h | 40 + libcef_dll/ctocpp/task_runner_ctocpp.cc | 134 + libcef_dll/ctocpp/task_runner_ctocpp.h | 45 + libcef_dll/ctocpp/urlrequest_client_ctocpp.cc | 138 + libcef_dll/ctocpp/urlrequest_client_ctocpp.h | 51 + libcef_dll/ctocpp/urlrequest_ctocpp.cc | 126 + libcef_dll/ctocpp/urlrequest_ctocpp.h | 45 + libcef_dll/ctocpp/v8accessor_ctocpp.cc | 99 + libcef_dll/ctocpp/v8accessor_ctocpp.h | 43 + libcef_dll/ctocpp/v8context_ctocpp.cc | 221 ++ libcef_dll/ctocpp/v8context_ctocpp.h | 49 + libcef_dll/ctocpp/v8exception_ctocpp.cc | 133 + libcef_dll/ctocpp/v8exception_ctocpp.h | 49 + libcef_dll/ctocpp/v8handler_ctocpp.cc | 84 + libcef_dll/ctocpp/v8handler_ctocpp.h | 42 + libcef_dll/ctocpp/v8stack_frame_ctocpp.cc | 134 + libcef_dll/ctocpp/v8stack_frame_ctocpp.h | 49 + libcef_dll/ctocpp/v8stack_trace_ctocpp.cc | 78 + libcef_dll/ctocpp/v8stack_trace_ctocpp.h | 44 + libcef_dll/ctocpp/v8value_ctocpp.cc | 874 +++++ libcef_dll/ctocpp/v8value_ctocpp.h | 89 + libcef_dll/ctocpp/web_plugin_info_ctocpp.cc | 83 + libcef_dll/ctocpp/web_plugin_info_ctocpp.h | 45 + .../ctocpp/web_plugin_info_visitor_ctocpp.cc | 46 + .../ctocpp/web_plugin_info_visitor_ctocpp.h | 43 + .../web_plugin_unstable_callback_ctocpp.cc | 42 + .../web_plugin_unstable_callback_ctocpp.h | 44 + libcef_dll/ctocpp/write_handler_ctocpp.cc | 98 + libcef_dll/ctocpp/write_handler_ctocpp.h | 46 + libcef_dll/ctocpp/xml_reader_ctocpp.cc | 501 +++ libcef_dll/ctocpp/xml_reader_ctocpp.h | 70 + libcef_dll/ctocpp/zip_reader_ctocpp.cc | 220 ++ libcef_dll/ctocpp/zip_reader_ctocpp.h | 52 + libcef_dll/libcef.dll.manifest | 8 + libcef_dll/libcef_dll.cc | 780 +++++ libcef_dll/libcef_dll.rc | 143 + libcef_dll/libcef_dll2.cc | 31 + libcef_dll/resource.h | 26 + libcef_dll/sandbox/sandbox_win.cc | 39 + libcef_dll/transfer_util.cpp | 72 + libcef_dll/transfer_util.h | 37 + libcef_dll/wrapper/cef_browser_info_map.h | 265 ++ libcef_dll/wrapper/cef_byte_read_handler.cc | 66 + libcef_dll/wrapper/cef_closure_task.cc | 42 + libcef_dll/wrapper/cef_message_router.cc | 1149 +++++++ .../wrapper/cef_stream_resource_handler.cc | 203 ++ libcef_dll/wrapper/cef_xml_object.cc | 453 +++ libcef_dll/wrapper/cef_zip_archive.cc | 174 + libcef_dll/wrapper/libcef_dll_wrapper.cc | 734 ++++ libcef_dll/wrapper/libcef_dll_wrapper2.cc | 4 + patch/README.txt | 20 + patch/patch.cfg | 121 + patch/patches/browser_web_contents_1257.patch | 78 + patch/patches/build.patch | 54 + patch/patches/content_nav_1129.patch | 60 + patch/patches/gritsettings.patch | 17 + patch/patches/gyp_331.patch | 22 + patch/patches/message_loop_443.patch | 13 + patch/patches/prefs_content_1161.patch | 25 + patch/patches/prefs_webkit_1161.patch | 24 + patch/patches/public_browser_1161_1257.patch | 132 + patch/patches/renderer_host_1161.patch | 128 + patch/patches/spi_webcore_364.patch | 34 + patch/patches/ui_dragdrop_355390.patch | 14 + patch/patches/underlay_1051.patch | 13 + patch/patches/views_widget_180.patch | 223 ++ patch/patches/webkit_933.patch | 13 + patch/patches/webkit_popups.patch | 76 + patch/patches/zlib.patch | 13 + tests/cefclient/binding_test.cpp | 55 + tests/cefclient/binding_test.h | 18 + tests/cefclient/bytes_write_handler.cpp | 94 + tests/cefclient/bytes_write_handler.h | 39 + tests/cefclient/cefclient.cpp | 195 ++ tests/cefclient/cefclient.exe.manifest | 20 + tests/cefclient/cefclient.h | 56 + tests/cefclient/cefclient.rc | 172 + tests/cefclient/cefclient_gtk.cpp | 477 +++ tests/cefclient/cefclient_mac.mm | 631 ++++ .../cefclient/cefclient_osr_dragdrop_win.cpp | 648 ++++ tests/cefclient/cefclient_osr_dragdrop_win.h | 178 + tests/cefclient/cefclient_osr_widget_gtk.cpp | 1356 ++++++++ tests/cefclient/cefclient_osr_widget_gtk.h | 92 + tests/cefclient/cefclient_osr_widget_mac.h | 147 + tests/cefclient/cefclient_osr_widget_mac.mm | 1213 +++++++ tests/cefclient/cefclient_osr_widget_win.cpp | 709 ++++ tests/cefclient/cefclient_osr_widget_win.h | 126 + tests/cefclient/cefclient_win.cpp | 741 +++++ tests/cefclient/client_app.cpp | 160 + tests/cefclient/client_app.h | 187 ++ tests/cefclient/client_app_delegates.cpp | 41 + tests/cefclient/client_handler.cpp | 938 ++++++ tests/cefclient/client_handler.h | 402 +++ tests/cefclient/client_handler_gtk.cpp | 435 +++ tests/cefclient/client_handler_mac.mm | 70 + tests/cefclient/client_handler_win.cpp | 83 + tests/cefclient/client_renderer.cpp | 85 + tests/cefclient/client_renderer.h | 22 + tests/cefclient/client_switches.cpp | 29 + tests/cefclient/client_switches.h | 23 + tests/cefclient/dialog_test.cpp | 98 + tests/cefclient/dialog_test.h | 18 + tests/cefclient/dom_test.cpp | 134 + tests/cefclient/dom_test.h | 25 + tests/cefclient/dragdrop_events.h | 24 + .../mac/English.lproj/InfoPlist.strings | 3 + .../cefclient/mac/English.lproj/MainMenu.xib | 2880 ++++++++++++++++ tests/cefclient/mac/Info.plist | 28 + tests/cefclient/mac/cefclient.icns | Bin 0 -> 55080 bytes tests/cefclient/mac/helper-Info.plist | 30 + tests/cefclient/osrenderer.cpp | 277 ++ tests/cefclient/osrenderer.h | 65 + tests/cefclient/performance_test.cpp | 163 + tests/cefclient/performance_test.h | 18 + tests/cefclient/performance_test_setup.h | 102 + tests/cefclient/performance_test_tests.cpp | 328 ++ tests/cefclient/print_handler_gtk.cpp | 524 +++ tests/cefclient/print_handler_gtk.h | 62 + tests/cefclient/process_helper_mac.cpp | 32 + tests/cefclient/res/binding.html | 28 + tests/cefclient/res/cefclient.ico | Bin 0 -> 23558 bytes tests/cefclient/res/dialogs.html | 64 + tests/cefclient/res/domaccess.html | 13 + tests/cefclient/res/localstorage.html | 24 + tests/cefclient/res/logo.png | Bin 0 -> 24025 bytes tests/cefclient/res/osr_test.html | 109 + tests/cefclient/res/other_tests.html | 33 + tests/cefclient/res/performance.html | 293 ++ tests/cefclient/res/performance2.html | 442 +++ tests/cefclient/res/small.ico | Bin 0 -> 23558 bytes tests/cefclient/res/transparency.html | 63 + tests/cefclient/res/window.html | 48 + tests/cefclient/res/xmlhttprequest.html | 19 + tests/cefclient/resource.h | 70 + tests/cefclient/resource_util.h | 23 + tests/cefclient/resource_util_linux.cpp | 30 + tests/cefclient/resource_util_mac.mm | 61 + tests/cefclient/resource_util_posix.cpp | 59 + tests/cefclient/resource_util_win.cpp | 92 + tests/cefclient/scheme_test.cpp | 163 + tests/cefclient/scheme_test.h | 26 + tests/cefclient/string_util.cpp | 74 + tests/cefclient/string_util.h | 21 + tests/cefclient/window_test.cpp | 102 + tests/cefclient/window_test.h | 28 + tests/cefclient/window_test_gtk.cpp | 72 + tests/cefclient/window_test_mac.mm | 69 + tests/cefclient/window_test_win.cpp | 78 + tests/cefsimple/cefsimple.exe.manifest | 20 + tests/cefsimple/cefsimple.rc | 79 + tests/cefsimple/cefsimple_linux.cpp | 39 + tests/cefsimple/cefsimple_mac.mm | 150 + tests/cefsimple/cefsimple_win.cpp | 72 + .../mac/English.lproj/InfoPlist.strings | 3 + .../cefsimple/mac/English.lproj/MainMenu.xib | 2880 ++++++++++++++++ tests/cefsimple/mac/Info.plist | 28 + tests/cefsimple/mac/cefsimple.icns | Bin 0 -> 55080 bytes tests/cefsimple/mac/helper-Info.plist | 30 + tests/cefsimple/process_helper_mac.cpp | 14 + tests/cefsimple/res/cefsimple.ico | Bin 0 -> 23558 bytes tests/cefsimple/res/small.ico | Bin 0 -> 23558 bytes tests/cefsimple/resource.h | 26 + tests/cefsimple/simple_app.cpp | 48 + tests/cefsimple/simple_app.h | 27 + tests/cefsimple/simple_handler.cpp | 111 + tests/cefsimple/simple_handler.h | 66 + tests/cefsimple/simple_handler_linux.cpp | 54 + tests/cefsimple/simple_handler_mac.mm | 21 + tests/cefsimple/simple_handler_win.cpp | 19 + tests/unittests/browser_info_map_unittest.cc | 722 ++++ tests/unittests/chromium_includes.h | 14 + tests/unittests/client_app_delegates.cc | 91 + tests/unittests/command_line_unittest.cc | 121 + tests/unittests/cookie_unittest.cc | 1123 +++++++ tests/unittests/dialog_unittest.cc | 270 ++ tests/unittests/display_unittest.cc | 112 + tests/unittests/dom_unittest.cc | 335 ++ tests/unittests/download_unittest.cc | 266 ++ tests/unittests/geolocation_unittest.cc | 210 ++ tests/unittests/jsdialog_unittest.cc | 417 +++ tests/unittests/life_span_unittest.cc | 310 ++ .../mac/English.lproj/InfoPlist.strings | 3 + .../unittests/mac/English.lproj/MainMenu.xib | 2880 ++++++++++++++++ tests/unittests/mac/Info.plist | 28 + tests/unittests/mac/unittests.icns | Bin 0 -> 55080 bytes tests/unittests/message_router_unittest.cc | 2815 ++++++++++++++++ tests/unittests/navigation_unittest.cc | 2090 ++++++++++++ tests/unittests/os_rendering_unittest.cc | 1020 ++++++ tests/unittests/os_rendering_unittest_mac.h | 18 + tests/unittests/os_rendering_unittest_mac.mm | 42 + tests/unittests/print_unittest.cc | 104 + tests/unittests/process_message_unittest.cc | 156 + tests/unittests/request_context_unittest.cc | 476 +++ tests/unittests/request_handler_unittest.cc | 509 +++ tests/unittests/request_unittest.cc | 541 +++ tests/unittests/routing_test_handler.cc | 107 + tests/unittests/routing_test_handler.h | 44 + tests/unittests/run_all_unittests.cc | 147 + tests/unittests/run_all_unittests_mac.mm | 48 + tests/unittests/scheme_handler_unittest.cc | 1530 +++++++++ .../stream_resource_handler_unittest.cc | 191 ++ tests/unittests/stream_unittest.cc | 381 +++ tests/unittests/string_unittest.cc | 368 ++ tests/unittests/task_unittest.cc | 205 ++ tests/unittests/test_handler.cc | 299 ++ tests/unittests/test_handler.h | 254 ++ tests/unittests/test_suite.cc | 125 + tests/unittests/test_suite.h | 39 + tests/unittests/test_util.cc | 237 ++ tests/unittests/test_util.h | 63 + tests/unittests/tracing_unittest.cc | 423 +++ tests/unittests/url_unittest.cc | 233 ++ tests/unittests/urlrequest_unittest.cc | 1178 +++++++ tests/unittests/v8_unittest.cc | 2169 ++++++++++++ tests/unittests/values_unittest.cc | 736 ++++ tests/unittests/version_unittest.cc | 27 + tests/unittests/xml_reader_unittest.cc | 645 ++++ tests/unittests/zip_reader_unittest.cc | 256 ++ tools/automate/automate-git.py | 941 ++++++ tools/automate/automate.README.txt | 99 + tools/automate/automate.py | 643 ++++ tools/automate/gitsvnmirror.py | 241 ++ tools/build_projects.bat | 48 + tools/build_projects.sh | 18 + tools/cef_api_hash.py | 245 ++ tools/cef_parser.py | 1869 +++++++++++ tools/check_revision.py | 92 + tools/check_style.bat | 2 + tools/check_style.py | 129 + tools/check_style.sh | 2 + tools/combine_libs.py | 118 + tools/date_util.py | 13 + tools/distrib/README-TRANSFER.txt | 5 + tools/distrib/README.client.txt | 12 + tools/distrib/README.footer.txt | 8 + tools/distrib/README.header.txt | 14 + tools/distrib/cefclient.gyp | 677 ++++ tools/distrib/linux/README.minimal.txt | 17 + tools/distrib/linux/README.redistrib.txt | 43 + tools/distrib/linux/README.standard.txt | 39 + tools/distrib/linux/build.sh | 12 + tools/distrib/mac/README.minimal.txt | 14 + tools/distrib/mac/README.redistrib.txt | 108 + tools/distrib/mac/README.standard.txt | 35 + tools/distrib/mac/transfer.cfg | 33 + tools/distrib/transfer.cfg | 13 + tools/distrib/win/README.minimal.txt | 19 + tools/distrib/win/README.redistrib.txt | 51 + tools/distrib/win/README.standard.txt | 51 + tools/distrib/win/d3dcompiler_43.dll | Bin 0 -> 2106216 bytes tools/distrib/win/transfer.cfg | 21 + tools/exec_util.py | 27 + tools/file_util.py | 131 + tools/gclient_hook.py | 39 + tools/gclient_util.py | 45 + tools/git_util.py | 44 + tools/make_capi_header.py | 202 ++ tools/make_cppdocs.bat | 18 + tools/make_cpptoc_header.py | 106 + tools/make_cpptoc_impl.py | 571 ++++ tools/make_ctocpp_header.py | 122 + tools/make_ctocpp_impl.py | 584 ++++ tools/make_distrib.bat | 2 + tools/make_distrib.py | 813 +++++ tools/make_distrib.sh | 2 + tools/make_gypi_file.py | 108 + tools/make_pack_header.py | 121 + tools/make_version_header.bat | 2 + tools/make_version_header.py | 176 + tools/make_version_header.sh | 2 + tools/msvs_env.bat | 60 + tools/patch.bat | 2 + tools/patch.sh | 2 + tools/patch_updater.py | 130 + tools/patch_util.py | 593 ++++ tools/patcher.README.txt | 32 + tools/patcher.py | 103 + tools/repack_locales.py | 190 ++ tools/revision.py | 22 + tools/svn_util.py | 60 + tools/translator.README.txt | 1697 ++++++++++ tools/translator.bat | 3 + tools/translator.py | 164 + tools/translator.sh | 2 + 1016 files changed, 183417 insertions(+) create mode 100644 AUTHORS.txt create mode 100644 CHROMIUM_BUILD_COMPATIBILITY.txt create mode 100644 DEPS create mode 100644 LICENSE.txt create mode 100644 VERSION create mode 100644 cef.gyp create mode 100644 cef.gypi create mode 100644 cef_create_projects.bat create mode 100755 cef_create_projects.sh create mode 100644 cef_paths.gypi create mode 100644 cef_paths2.gypi create mode 100644 include/base/cef_atomic_ref_count.h create mode 100644 include/base/cef_atomicops.h create mode 100644 include/base/cef_basictypes.h create mode 100644 include/base/cef_bind.h create mode 100644 include/base/cef_bind_helpers.h create mode 100644 include/base/cef_build.h create mode 100644 include/base/cef_callback.h create mode 100644 include/base/cef_callback_forward.h create mode 100644 include/base/cef_callback_helpers.h create mode 100644 include/base/cef_callback_list.h create mode 100644 include/base/cef_cancelable_callback.h create mode 100644 include/base/cef_lock.h create mode 100644 include/base/cef_logging.h create mode 100644 include/base/cef_macros.h create mode 100644 include/base/cef_move.h create mode 100644 include/base/cef_platform_thread.h create mode 100644 include/base/cef_ref_counted.h create mode 100644 include/base/cef_scoped_ptr.h create mode 100644 include/base/cef_string16.h create mode 100644 include/base/cef_template_util.h create mode 100644 include/base/cef_thread_checker.h create mode 100644 include/base/cef_thread_collision_warner.h create mode 100644 include/base/cef_trace_event.h create mode 100644 include/base/cef_tuple.h create mode 100644 include/base/cef_weak_ptr.h create mode 100644 include/base/internal/cef_atomicops_atomicword_compat.h create mode 100644 include/base/internal/cef_atomicops_mac.h create mode 100644 include/base/internal/cef_atomicops_x86_gcc.h create mode 100644 include/base/internal/cef_atomicops_x86_msvc.h create mode 100644 include/base/internal/cef_bind_internal.h create mode 100644 include/base/internal/cef_bind_internal_win.h create mode 100644 include/base/internal/cef_callback_internal.h create mode 100644 include/base/internal/cef_lock_impl.h create mode 100644 include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h create mode 100644 include/base/internal/cef_thread_checker_impl.h create mode 100644 include/capi/cef_app_capi.h create mode 100644 include/capi/cef_auth_callback_capi.h create mode 100644 include/capi/cef_base_capi.h create mode 100644 include/capi/cef_browser_capi.h create mode 100644 include/capi/cef_browser_process_handler_capi.h create mode 100644 include/capi/cef_callback_capi.h create mode 100644 include/capi/cef_client_capi.h create mode 100644 include/capi/cef_command_line_capi.h create mode 100644 include/capi/cef_context_menu_handler_capi.h create mode 100644 include/capi/cef_cookie_capi.h create mode 100644 include/capi/cef_dialog_handler_capi.h create mode 100644 include/capi/cef_display_handler_capi.h create mode 100644 include/capi/cef_dom_capi.h create mode 100644 include/capi/cef_download_handler_capi.h create mode 100644 include/capi/cef_download_item_capi.h create mode 100644 include/capi/cef_drag_data_capi.h create mode 100644 include/capi/cef_drag_handler_capi.h create mode 100644 include/capi/cef_focus_handler_capi.h create mode 100644 include/capi/cef_frame_capi.h create mode 100644 include/capi/cef_geolocation_capi.h create mode 100644 include/capi/cef_geolocation_handler_capi.h create mode 100644 include/capi/cef_jsdialog_handler_capi.h create mode 100644 include/capi/cef_keyboard_handler_capi.h create mode 100644 include/capi/cef_life_span_handler_capi.h create mode 100644 include/capi/cef_load_handler_capi.h create mode 100644 include/capi/cef_menu_model_capi.h create mode 100644 include/capi/cef_origin_whitelist_capi.h create mode 100644 include/capi/cef_path_util_capi.h create mode 100644 include/capi/cef_print_handler_capi.h create mode 100644 include/capi/cef_print_settings_capi.h create mode 100644 include/capi/cef_process_message_capi.h create mode 100644 include/capi/cef_process_util_capi.h create mode 100644 include/capi/cef_render_handler_capi.h create mode 100644 include/capi/cef_render_process_handler_capi.h create mode 100644 include/capi/cef_request_capi.h create mode 100644 include/capi/cef_request_context_capi.h create mode 100644 include/capi/cef_request_context_handler_capi.h create mode 100644 include/capi/cef_request_handler_capi.h create mode 100644 include/capi/cef_resource_bundle_handler_capi.h create mode 100644 include/capi/cef_resource_handler_capi.h create mode 100644 include/capi/cef_response_capi.h create mode 100644 include/capi/cef_scheme_capi.h create mode 100644 include/capi/cef_stream_capi.h create mode 100644 include/capi/cef_string_visitor_capi.h create mode 100644 include/capi/cef_task_capi.h create mode 100644 include/capi/cef_trace_capi.h create mode 100644 include/capi/cef_url_capi.h create mode 100644 include/capi/cef_urlrequest_capi.h create mode 100644 include/capi/cef_v8_capi.h create mode 100644 include/capi/cef_values_capi.h create mode 100644 include/capi/cef_web_plugin_capi.h create mode 100644 include/capi/cef_xml_reader_capi.h create mode 100644 include/capi/cef_zip_reader_capi.h create mode 100644 include/cef_app.h create mode 100644 include/cef_application_mac.h create mode 100644 include/cef_auth_callback.h create mode 100644 include/cef_base.h create mode 100644 include/cef_browser.h create mode 100644 include/cef_browser_process_handler.h create mode 100644 include/cef_callback.h create mode 100644 include/cef_client.h create mode 100644 include/cef_command_line.h create mode 100644 include/cef_context_menu_handler.h create mode 100644 include/cef_cookie.h create mode 100644 include/cef_dialog_handler.h create mode 100644 include/cef_display_handler.h create mode 100644 include/cef_dom.h create mode 100644 include/cef_download_handler.h create mode 100644 include/cef_download_item.h create mode 100644 include/cef_drag_data.h create mode 100644 include/cef_drag_handler.h create mode 100644 include/cef_focus_handler.h create mode 100644 include/cef_frame.h create mode 100644 include/cef_geolocation.h create mode 100644 include/cef_geolocation_handler.h create mode 100644 include/cef_jsdialog_handler.h create mode 100644 include/cef_keyboard_handler.h create mode 100644 include/cef_life_span_handler.h create mode 100644 include/cef_load_handler.h create mode 100644 include/cef_menu_model.h create mode 100644 include/cef_origin_whitelist.h create mode 100644 include/cef_path_util.h create mode 100644 include/cef_print_handler.h create mode 100644 include/cef_print_settings.h create mode 100644 include/cef_process_message.h create mode 100644 include/cef_process_util.h create mode 100644 include/cef_render_handler.h create mode 100644 include/cef_render_process_handler.h create mode 100644 include/cef_request.h create mode 100644 include/cef_request_context.h create mode 100644 include/cef_request_context_handler.h create mode 100644 include/cef_request_handler.h create mode 100644 include/cef_resource_bundle_handler.h create mode 100644 include/cef_resource_handler.h create mode 100644 include/cef_response.h create mode 100644 include/cef_runnable.h create mode 100644 include/cef_sandbox_win.h create mode 100644 include/cef_scheme.h create mode 100644 include/cef_stream.h create mode 100644 include/cef_string_visitor.h create mode 100644 include/cef_task.h create mode 100644 include/cef_trace.h create mode 100644 include/cef_url.h create mode 100644 include/cef_urlrequest.h create mode 100644 include/cef_v8.h create mode 100644 include/cef_values.h create mode 100644 include/cef_web_plugin.h create mode 100644 include/cef_xml_reader.h create mode 100644 include/cef_zip_reader.h create mode 100644 include/internal/cef_export.h create mode 100644 include/internal/cef_linux.h create mode 100644 include/internal/cef_logging_internal.h create mode 100644 include/internal/cef_mac.h create mode 100644 include/internal/cef_ptr.h create mode 100644 include/internal/cef_string.h create mode 100644 include/internal/cef_string_list.h create mode 100644 include/internal/cef_string_map.h create mode 100644 include/internal/cef_string_multimap.h create mode 100644 include/internal/cef_string_types.h create mode 100644 include/internal/cef_string_wrappers.h create mode 100644 include/internal/cef_thread_internal.h create mode 100644 include/internal/cef_time.h create mode 100644 include/internal/cef_trace_event_internal.h create mode 100644 include/internal/cef_types.h create mode 100644 include/internal/cef_types_linux.h create mode 100644 include/internal/cef_types_mac.h create mode 100644 include/internal/cef_types_win.h create mode 100644 include/internal/cef_types_wrappers.h create mode 100644 include/internal/cef_win.h create mode 100644 include/wrapper/cef_byte_read_handler.h create mode 100644 include/wrapper/cef_closure_task.h create mode 100644 include/wrapper/cef_helpers.h create mode 100644 include/wrapper/cef_message_router.h create mode 100644 include/wrapper/cef_stream_resource_handler.h create mode 100644 include/wrapper/cef_xml_object.h create mode 100644 include/wrapper/cef_zip_archive.h create mode 100644 libcef/browser/browser_context.h create mode 100644 libcef/browser/browser_context_impl.cc create mode 100644 libcef/browser/browser_context_impl.h create mode 100644 libcef/browser/browser_context_proxy.cc create mode 100644 libcef/browser/browser_context_proxy.h create mode 100644 libcef/browser/browser_host_impl.cc create mode 100644 libcef/browser/browser_host_impl.h create mode 100644 libcef/browser/browser_host_impl_linux.cc create mode 100644 libcef/browser/browser_host_impl_mac.mm create mode 100644 libcef/browser/browser_host_impl_win.cc create mode 100644 libcef/browser/browser_info.cc create mode 100644 libcef/browser/browser_info.h create mode 100644 libcef/browser/browser_main.cc create mode 100644 libcef/browser/browser_main.h create mode 100644 libcef/browser/browser_main_linux.cc create mode 100644 libcef/browser/browser_main_mac.mm create mode 100644 libcef/browser/browser_main_win.cc create mode 100644 libcef/browser/browser_message_filter.cc create mode 100644 libcef/browser/browser_message_filter.h create mode 100644 libcef/browser/browser_message_loop.cc create mode 100644 libcef/browser/browser_message_loop.h create mode 100644 libcef/browser/browser_pref_store.cc create mode 100644 libcef/browser/browser_pref_store.h create mode 100644 libcef/browser/browser_settings.cc create mode 100644 libcef/browser/browser_settings.h create mode 100644 libcef/browser/browser_urlrequest_impl.cc create mode 100644 libcef/browser/browser_urlrequest_impl.h create mode 100644 libcef/browser/chrome_browser_process_stub.cc create mode 100644 libcef/browser/chrome_browser_process_stub.h create mode 100644 libcef/browser/chrome_scheme_handler.cc create mode 100644 libcef/browser/chrome_scheme_handler.h create mode 100644 libcef/browser/content_browser_client.cc create mode 100644 libcef/browser/content_browser_client.h create mode 100644 libcef/browser/context.cc create mode 100644 libcef/browser/context.h create mode 100644 libcef/browser/context_menu_params_impl.cc create mode 100644 libcef/browser/context_menu_params_impl.h create mode 100644 libcef/browser/cookie_manager_impl.cc create mode 100644 libcef/browser/cookie_manager_impl.h create mode 100644 libcef/browser/devtools_delegate.cc create mode 100644 libcef/browser/devtools_delegate.h create mode 100644 libcef/browser/devtools_frontend.cc create mode 100644 libcef/browser/devtools_frontend.h create mode 100644 libcef/browser/devtools_scheme_handler.cc create mode 100644 libcef/browser/devtools_scheme_handler.h create mode 100644 libcef/browser/download_item_impl.cc create mode 100644 libcef/browser/download_item_impl.h create mode 100644 libcef/browser/download_manager_delegate.cc create mode 100644 libcef/browser/download_manager_delegate.h create mode 100644 libcef/browser/frame_host_impl.cc create mode 100644 libcef/browser/frame_host_impl.h create mode 100644 libcef/browser/geolocation_impl.cc create mode 100644 libcef/browser/internal_scheme_handler.cc create mode 100644 libcef/browser/internal_scheme_handler.h create mode 100644 libcef/browser/javascript_dialog.h create mode 100644 libcef/browser/javascript_dialog_linux.cc create mode 100644 libcef/browser/javascript_dialog_mac.mm create mode 100644 libcef/browser/javascript_dialog_manager.cc create mode 100644 libcef/browser/javascript_dialog_manager.h create mode 100644 libcef/browser/javascript_dialog_win.cc create mode 100644 libcef/browser/media_capture_devices_dispatcher.cc create mode 100644 libcef/browser/media_capture_devices_dispatcher.h create mode 100644 libcef/browser/menu_creator.cc create mode 100644 libcef/browser/menu_creator.h create mode 100644 libcef/browser/menu_creator_runner_linux.cc create mode 100644 libcef/browser/menu_creator_runner_linux.h create mode 100644 libcef/browser/menu_creator_runner_mac.h create mode 100644 libcef/browser/menu_creator_runner_mac.mm create mode 100644 libcef/browser/menu_creator_runner_win.cc create mode 100644 libcef/browser/menu_creator_runner_win.h create mode 100644 libcef/browser/menu_model_impl.cc create mode 100644 libcef/browser/menu_model_impl.h create mode 100644 libcef/browser/navigate_params.cc create mode 100644 libcef/browser/navigate_params.h create mode 100644 libcef/browser/origin_whitelist_impl.cc create mode 100644 libcef/browser/origin_whitelist_impl.h create mode 100644 libcef/browser/path_util_impl.cc create mode 100644 libcef/browser/print_settings_impl.cc create mode 100644 libcef/browser/print_settings_impl.h create mode 100644 libcef/browser/printing/print_dialog_linux.cc create mode 100644 libcef/browser/printing/print_dialog_linux.h create mode 100644 libcef/browser/printing/print_view_manager.cc create mode 100644 libcef/browser/printing/print_view_manager.h create mode 100644 libcef/browser/printing/print_view_manager_base.cc create mode 100644 libcef/browser/printing/print_view_manager_base.h create mode 100644 libcef/browser/printing/printing_message_filter.cc create mode 100644 libcef/browser/printing/printing_message_filter.h create mode 100644 libcef/browser/process_util_impl.cc create mode 100644 libcef/browser/proxy_stubs.cc create mode 100644 libcef/browser/render_widget_host_view_osr.cc create mode 100644 libcef/browser/render_widget_host_view_osr.h create mode 100644 libcef/browser/render_widget_host_view_osr_linux.cc create mode 100644 libcef/browser/render_widget_host_view_osr_mac.mm create mode 100644 libcef/browser/render_widget_host_view_osr_win.cc create mode 100644 libcef/browser/request_context_impl.cc create mode 100644 libcef/browser/request_context_impl.h create mode 100644 libcef/browser/resource_dispatcher_host_delegate.cc create mode 100644 libcef/browser/resource_dispatcher_host_delegate.h create mode 100644 libcef/browser/resource_request_job.cc create mode 100644 libcef/browser/resource_request_job.h create mode 100644 libcef/browser/scheme_handler.cc create mode 100644 libcef/browser/scheme_handler.h create mode 100644 libcef/browser/scheme_impl.cc create mode 100644 libcef/browser/scheme_impl.h create mode 100644 libcef/browser/speech_recognition_manager_delegate.cc create mode 100644 libcef/browser/speech_recognition_manager_delegate.h create mode 100644 libcef/browser/stream_impl.cc create mode 100644 libcef/browser/stream_impl.h create mode 100644 libcef/browser/text_input_client_osr_mac.h create mode 100644 libcef/browser/text_input_client_osr_mac.mm create mode 100644 libcef/browser/thread_util.h create mode 100644 libcef/browser/trace_impl.cc create mode 100644 libcef/browser/trace_subscriber.cc create mode 100644 libcef/browser/trace_subscriber.h create mode 100644 libcef/browser/url_network_delegate.cc create mode 100644 libcef/browser/url_network_delegate.h create mode 100644 libcef/browser/url_request_context_getter.cc create mode 100644 libcef/browser/url_request_context_getter.h create mode 100644 libcef/browser/url_request_context_getter_proxy.cc create mode 100644 libcef/browser/url_request_context_getter_proxy.h create mode 100644 libcef/browser/url_request_context_proxy.cc create mode 100644 libcef/browser/url_request_context_proxy.h create mode 100644 libcef/browser/url_request_interceptor.cc create mode 100644 libcef/browser/url_request_interceptor.h create mode 100644 libcef/browser/url_request_user_data.cc create mode 100644 libcef/browser/url_request_user_data.h create mode 100644 libcef/browser/web_contents_view_osr.cc create mode 100644 libcef/browser/web_contents_view_osr.h create mode 100644 libcef/browser/web_plugin_impl.cc create mode 100644 libcef/browser/web_plugin_impl.h create mode 100644 libcef/browser/window_delegate_view.cc create mode 100644 libcef/browser/window_delegate_view.h create mode 100644 libcef/browser/window_x11.cc create mode 100644 libcef/browser/window_x11.h create mode 100644 libcef/browser/xml_reader_impl.cc create mode 100644 libcef/browser/xml_reader_impl.h create mode 100644 libcef/browser/zip_reader_impl.cc create mode 100644 libcef/browser/zip_reader_impl.h create mode 100644 libcef/common/base_impl.cc create mode 100644 libcef/common/breakpad_client.cc create mode 100644 libcef/common/breakpad_client.h create mode 100644 libcef/common/cef_message_generator.cc create mode 100644 libcef/common/cef_message_generator.h create mode 100644 libcef/common/cef_messages.cc create mode 100644 libcef/common/cef_messages.h create mode 100644 libcef/common/cef_switches.cc create mode 100644 libcef/common/cef_switches.h create mode 100644 libcef/common/command_line_impl.cc create mode 100644 libcef/common/command_line_impl.h create mode 100644 libcef/common/content_client.cc create mode 100644 libcef/common/content_client.h create mode 100644 libcef/common/drag_data_impl.cc create mode 100644 libcef/common/drag_data_impl.h create mode 100644 libcef/common/http_header_utils.cc create mode 100644 libcef/common/http_header_utils.h create mode 100644 libcef/common/main_delegate.cc create mode 100644 libcef/common/main_delegate.h create mode 100644 libcef/common/net_resource_provider.cc create mode 100644 libcef/common/net_resource_provider.h create mode 100644 libcef/common/process_message_impl.cc create mode 100644 libcef/common/process_message_impl.h create mode 100644 libcef/common/request_impl.cc create mode 100644 libcef/common/request_impl.h create mode 100644 libcef/common/response_impl.cc create mode 100644 libcef/common/response_impl.h create mode 100644 libcef/common/response_manager.cc create mode 100644 libcef/common/response_manager.h create mode 100644 libcef/common/scheme_registrar_impl.cc create mode 100644 libcef/common/scheme_registrar_impl.h create mode 100644 libcef/common/scheme_registration.cc create mode 100644 libcef/common/scheme_registration.h create mode 100644 libcef/common/string_list_impl.cc create mode 100644 libcef/common/string_map_impl.cc create mode 100644 libcef/common/string_multimap_impl.cc create mode 100644 libcef/common/string_types_impl.cc create mode 100644 libcef/common/task_impl.cc create mode 100644 libcef/common/task_runner_impl.cc create mode 100644 libcef/common/task_runner_impl.h create mode 100644 libcef/common/time_impl.cc create mode 100644 libcef/common/time_util.h create mode 100644 libcef/common/tracker.cc create mode 100644 libcef/common/tracker.h create mode 100644 libcef/common/upload_data.cc create mode 100644 libcef/common/upload_data.h create mode 100644 libcef/common/url_impl.cc create mode 100644 libcef/common/urlrequest_impl.cc create mode 100644 libcef/common/value_base.cc create mode 100644 libcef/common/value_base.h create mode 100644 libcef/common/values_impl.cc create mode 100644 libcef/common/values_impl.h create mode 100644 libcef/renderer/browser_impl.cc create mode 100644 libcef/renderer/browser_impl.h create mode 100644 libcef/renderer/content_renderer_client.cc create mode 100644 libcef/renderer/content_renderer_client.h create mode 100644 libcef/renderer/dom_document_impl.cc create mode 100644 libcef/renderer/dom_document_impl.h create mode 100644 libcef/renderer/dom_event_impl.cc create mode 100644 libcef/renderer/dom_event_impl.h create mode 100644 libcef/renderer/dom_node_impl.cc create mode 100644 libcef/renderer/dom_node_impl.h create mode 100644 libcef/renderer/frame_impl.cc create mode 100644 libcef/renderer/frame_impl.h create mode 100644 libcef/renderer/render_frame_observer.cc create mode 100644 libcef/renderer/render_frame_observer.h create mode 100644 libcef/renderer/render_message_filter.cc create mode 100644 libcef/renderer/render_message_filter.h create mode 100644 libcef/renderer/render_process_observer.cc create mode 100644 libcef/renderer/render_process_observer.h create mode 100644 libcef/renderer/render_urlrequest_impl.cc create mode 100644 libcef/renderer/render_urlrequest_impl.h create mode 100644 libcef/renderer/thread_util.h create mode 100644 libcef/renderer/v8_impl.cc create mode 100644 libcef/renderer/v8_impl.h create mode 100644 libcef/renderer/webkit_glue.cc create mode 100644 libcef/renderer/webkit_glue.h create mode 100644 libcef/resources/about_version.html create mode 100644 libcef/resources/cef_resources.grd create mode 100644 libcef/resources/cef_strings.grd create mode 100644 libcef/resources/devtools_discovery_page.html create mode 100644 libcef/resources/framework-Info.plist create mode 100644 libcef/resources/grit_stub/grit/browser_resources.h create mode 100644 libcef/resources/grit_stub/grit/generated_resources.h create mode 100644 libcef/resources/print_preview_page_stub.html create mode 100644 libcef/utility/content_utility_client.cc create mode 100644 libcef/utility/content_utility_client.h create mode 100644 libcef/utility/printing_handler.cc create mode 100644 libcef/utility/printing_handler.h create mode 100644 libcef_dll/base/cef_atomicops_x86_gcc.cc create mode 100644 libcef_dll/base/cef_bind_helpers.cc create mode 100644 libcef_dll/base/cef_callback_helpers.cc create mode 100644 libcef_dll/base/cef_callback_internal.cc create mode 100644 libcef_dll/base/cef_lock.cc create mode 100644 libcef_dll/base/cef_lock_impl.cc create mode 100644 libcef_dll/base/cef_logging.cc create mode 100644 libcef_dll/base/cef_ref_counted.cc create mode 100644 libcef_dll/base/cef_string16.cc create mode 100644 libcef_dll/base/cef_thread_checker_impl.cc create mode 100644 libcef_dll/base/cef_thread_collision_warner.cc create mode 100644 libcef_dll/base/cef_weak_ptr.cc create mode 100644 libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/app_cpptoc.cc create mode 100644 libcef_dll/cpptoc/app_cpptoc.h create mode 100644 libcef_dll/cpptoc/auth_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/auth_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/base_cpptoc.h create mode 100644 libcef_dll/cpptoc/before_download_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/before_download_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/binary_value_cpptoc.cc create mode 100644 libcef_dll/cpptoc/binary_value_cpptoc.h create mode 100644 libcef_dll/cpptoc/browser_cpptoc.cc create mode 100644 libcef_dll/cpptoc/browser_cpptoc.h create mode 100644 libcef_dll/cpptoc/browser_host_cpptoc.cc create mode 100644 libcef_dll/cpptoc/browser_host_cpptoc.h create mode 100644 libcef_dll/cpptoc/browser_process_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/browser_process_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/client_cpptoc.cc create mode 100644 libcef_dll/cpptoc/client_cpptoc.h create mode 100644 libcef_dll/cpptoc/command_line_cpptoc.cc create mode 100644 libcef_dll/cpptoc/command_line_cpptoc.h create mode 100644 libcef_dll/cpptoc/completion_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/completion_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/context_menu_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/context_menu_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/context_menu_params_cpptoc.cc create mode 100644 libcef_dll/cpptoc/context_menu_params_cpptoc.h create mode 100644 libcef_dll/cpptoc/cookie_manager_cpptoc.cc create mode 100644 libcef_dll/cpptoc/cookie_manager_cpptoc.h create mode 100644 libcef_dll/cpptoc/cookie_visitor_cpptoc.cc create mode 100644 libcef_dll/cpptoc/cookie_visitor_cpptoc.h create mode 100644 libcef_dll/cpptoc/cpptoc.h create mode 100644 libcef_dll/cpptoc/dialog_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/dialog_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/dictionary_value_cpptoc.cc create mode 100644 libcef_dll/cpptoc/dictionary_value_cpptoc.h create mode 100644 libcef_dll/cpptoc/display_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/display_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/domdocument_cpptoc.cc create mode 100644 libcef_dll/cpptoc/domdocument_cpptoc.h create mode 100644 libcef_dll/cpptoc/domevent_cpptoc.cc create mode 100644 libcef_dll/cpptoc/domevent_cpptoc.h create mode 100644 libcef_dll/cpptoc/domevent_listener_cpptoc.cc create mode 100644 libcef_dll/cpptoc/domevent_listener_cpptoc.h create mode 100644 libcef_dll/cpptoc/domnode_cpptoc.cc create mode 100644 libcef_dll/cpptoc/domnode_cpptoc.h create mode 100644 libcef_dll/cpptoc/domvisitor_cpptoc.cc create mode 100644 libcef_dll/cpptoc/domvisitor_cpptoc.h create mode 100644 libcef_dll/cpptoc/download_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/download_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/download_item_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/download_item_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/download_item_cpptoc.cc create mode 100644 libcef_dll/cpptoc/download_item_cpptoc.h create mode 100644 libcef_dll/cpptoc/drag_data_cpptoc.cc create mode 100644 libcef_dll/cpptoc/drag_data_cpptoc.h create mode 100644 libcef_dll/cpptoc/drag_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/drag_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/end_tracing_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/file_dialog_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/focus_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/focus_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/frame_cpptoc.cc create mode 100644 libcef_dll/cpptoc/frame_cpptoc.h create mode 100644 libcef_dll/cpptoc/geolocation_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/geolocation_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/geolocation_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/geolocation_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/get_geolocation_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/jsdialog_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/jsdialog_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/keyboard_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/keyboard_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/life_span_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/life_span_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/list_value_cpptoc.cc create mode 100644 libcef_dll/cpptoc/list_value_cpptoc.h create mode 100644 libcef_dll/cpptoc/load_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/load_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/menu_model_cpptoc.cc create mode 100644 libcef_dll/cpptoc/menu_model_cpptoc.h create mode 100644 libcef_dll/cpptoc/permission_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/permission_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/post_data_cpptoc.cc create mode 100644 libcef_dll/cpptoc/post_data_cpptoc.h create mode 100644 libcef_dll/cpptoc/post_data_element_cpptoc.cc create mode 100644 libcef_dll/cpptoc/post_data_element_cpptoc.h create mode 100644 libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/print_dialog_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/print_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/print_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/print_job_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/print_job_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/print_settings_cpptoc.cc create mode 100644 libcef_dll/cpptoc/print_settings_cpptoc.h create mode 100644 libcef_dll/cpptoc/process_message_cpptoc.cc create mode 100644 libcef_dll/cpptoc/process_message_cpptoc.h create mode 100644 libcef_dll/cpptoc/quota_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/quota_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/read_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/read_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/render_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/render_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/render_process_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/render_process_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/request_context_cpptoc.cc create mode 100644 libcef_dll/cpptoc/request_context_cpptoc.h create mode 100644 libcef_dll/cpptoc/request_context_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/request_context_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/request_cpptoc.cc create mode 100644 libcef_dll/cpptoc/request_cpptoc.h create mode 100644 libcef_dll/cpptoc/request_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/request_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/resource_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/resource_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/response_cpptoc.cc create mode 100644 libcef_dll/cpptoc/response_cpptoc.h create mode 100644 libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc create mode 100644 libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h create mode 100644 libcef_dll/cpptoc/scheme_registrar_cpptoc.cc create mode 100644 libcef_dll/cpptoc/scheme_registrar_cpptoc.h create mode 100644 libcef_dll/cpptoc/stream_reader_cpptoc.cc create mode 100644 libcef_dll/cpptoc/stream_reader_cpptoc.h create mode 100644 libcef_dll/cpptoc/stream_writer_cpptoc.cc create mode 100644 libcef_dll/cpptoc/stream_writer_cpptoc.h create mode 100644 libcef_dll/cpptoc/string_visitor_cpptoc.cc create mode 100644 libcef_dll/cpptoc/string_visitor_cpptoc.h create mode 100644 libcef_dll/cpptoc/task_cpptoc.cc create mode 100644 libcef_dll/cpptoc/task_cpptoc.h create mode 100644 libcef_dll/cpptoc/task_runner_cpptoc.cc create mode 100644 libcef_dll/cpptoc/task_runner_cpptoc.h create mode 100644 libcef_dll/cpptoc/urlrequest_client_cpptoc.cc create mode 100644 libcef_dll/cpptoc/urlrequest_client_cpptoc.h create mode 100644 libcef_dll/cpptoc/urlrequest_cpptoc.cc create mode 100644 libcef_dll/cpptoc/urlrequest_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8accessor_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8accessor_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8context_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8context_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8exception_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8exception_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8stack_frame_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8stack_frame_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8stack_trace_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8stack_trace_cpptoc.h create mode 100644 libcef_dll/cpptoc/v8value_cpptoc.cc create mode 100644 libcef_dll/cpptoc/v8value_cpptoc.h create mode 100644 libcef_dll/cpptoc/web_plugin_info_cpptoc.cc create mode 100644 libcef_dll/cpptoc/web_plugin_info_cpptoc.h create mode 100644 libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc create mode 100644 libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h create mode 100644 libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc create mode 100644 libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h create mode 100644 libcef_dll/cpptoc/write_handler_cpptoc.cc create mode 100644 libcef_dll/cpptoc/write_handler_cpptoc.h create mode 100644 libcef_dll/cpptoc/xml_reader_cpptoc.cc create mode 100644 libcef_dll/cpptoc/xml_reader_cpptoc.h create mode 100644 libcef_dll/cpptoc/zip_reader_cpptoc.cc create mode 100644 libcef_dll/cpptoc/zip_reader_cpptoc.h create mode 100644 libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/app_ctocpp.cc create mode 100644 libcef_dll/ctocpp/app_ctocpp.h create mode 100644 libcef_dll/ctocpp/auth_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/auth_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/base_ctocpp.h create mode 100644 libcef_dll/ctocpp/before_download_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/before_download_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/binary_value_ctocpp.cc create mode 100644 libcef_dll/ctocpp/binary_value_ctocpp.h create mode 100644 libcef_dll/ctocpp/browser_ctocpp.cc create mode 100644 libcef_dll/ctocpp/browser_ctocpp.h create mode 100644 libcef_dll/ctocpp/browser_host_ctocpp.cc create mode 100644 libcef_dll/ctocpp/browser_host_ctocpp.h create mode 100644 libcef_dll/ctocpp/browser_process_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/browser_process_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/client_ctocpp.cc create mode 100644 libcef_dll/ctocpp/client_ctocpp.h create mode 100644 libcef_dll/ctocpp/command_line_ctocpp.cc create mode 100644 libcef_dll/ctocpp/command_line_ctocpp.h create mode 100644 libcef_dll/ctocpp/completion_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/completion_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/context_menu_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/context_menu_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/context_menu_params_ctocpp.cc create mode 100644 libcef_dll/ctocpp/context_menu_params_ctocpp.h create mode 100644 libcef_dll/ctocpp/cookie_manager_ctocpp.cc create mode 100644 libcef_dll/ctocpp/cookie_manager_ctocpp.h create mode 100644 libcef_dll/ctocpp/cookie_visitor_ctocpp.cc create mode 100644 libcef_dll/ctocpp/cookie_visitor_ctocpp.h create mode 100644 libcef_dll/ctocpp/ctocpp.h create mode 100644 libcef_dll/ctocpp/dialog_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/dialog_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/dictionary_value_ctocpp.cc create mode 100644 libcef_dll/ctocpp/dictionary_value_ctocpp.h create mode 100644 libcef_dll/ctocpp/display_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/display_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/domdocument_ctocpp.cc create mode 100644 libcef_dll/ctocpp/domdocument_ctocpp.h create mode 100644 libcef_dll/ctocpp/domevent_ctocpp.cc create mode 100644 libcef_dll/ctocpp/domevent_ctocpp.h create mode 100644 libcef_dll/ctocpp/domevent_listener_ctocpp.cc create mode 100644 libcef_dll/ctocpp/domevent_listener_ctocpp.h create mode 100644 libcef_dll/ctocpp/domnode_ctocpp.cc create mode 100644 libcef_dll/ctocpp/domnode_ctocpp.h create mode 100644 libcef_dll/ctocpp/domvisitor_ctocpp.cc create mode 100644 libcef_dll/ctocpp/domvisitor_ctocpp.h create mode 100644 libcef_dll/ctocpp/download_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/download_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/download_item_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/download_item_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/download_item_ctocpp.cc create mode 100644 libcef_dll/ctocpp/download_item_ctocpp.h create mode 100644 libcef_dll/ctocpp/drag_data_ctocpp.cc create mode 100644 libcef_dll/ctocpp/drag_data_ctocpp.h create mode 100644 libcef_dll/ctocpp/drag_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/drag_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/end_tracing_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/file_dialog_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/focus_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/focus_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/frame_ctocpp.cc create mode 100644 libcef_dll/ctocpp/frame_ctocpp.h create mode 100644 libcef_dll/ctocpp/geolocation_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/geolocation_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/geolocation_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/geolocation_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/jsdialog_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/jsdialog_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/keyboard_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/keyboard_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/life_span_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/life_span_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/list_value_ctocpp.cc create mode 100644 libcef_dll/ctocpp/list_value_ctocpp.h create mode 100644 libcef_dll/ctocpp/load_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/load_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/menu_model_ctocpp.cc create mode 100644 libcef_dll/ctocpp/menu_model_ctocpp.h create mode 100644 libcef_dll/ctocpp/permission_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/permission_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/post_data_ctocpp.cc create mode 100644 libcef_dll/ctocpp/post_data_ctocpp.h create mode 100644 libcef_dll/ctocpp/post_data_element_ctocpp.cc create mode 100644 libcef_dll/ctocpp/post_data_element_ctocpp.h create mode 100644 libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/print_dialog_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/print_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/print_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/print_job_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/print_job_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/print_settings_ctocpp.cc create mode 100644 libcef_dll/ctocpp/print_settings_ctocpp.h create mode 100644 libcef_dll/ctocpp/process_message_ctocpp.cc create mode 100644 libcef_dll/ctocpp/process_message_ctocpp.h create mode 100644 libcef_dll/ctocpp/quota_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/quota_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/read_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/read_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/render_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/render_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/render_process_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/render_process_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/request_context_ctocpp.cc create mode 100644 libcef_dll/ctocpp/request_context_ctocpp.h create mode 100644 libcef_dll/ctocpp/request_context_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/request_context_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/request_ctocpp.cc create mode 100644 libcef_dll/ctocpp/request_ctocpp.h create mode 100644 libcef_dll/ctocpp/request_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/request_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/resource_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/resource_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/response_ctocpp.cc create mode 100644 libcef_dll/ctocpp/response_ctocpp.h create mode 100644 libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc create mode 100644 libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h create mode 100644 libcef_dll/ctocpp/scheme_registrar_ctocpp.cc create mode 100644 libcef_dll/ctocpp/scheme_registrar_ctocpp.h create mode 100644 libcef_dll/ctocpp/stream_reader_ctocpp.cc create mode 100644 libcef_dll/ctocpp/stream_reader_ctocpp.h create mode 100644 libcef_dll/ctocpp/stream_writer_ctocpp.cc create mode 100644 libcef_dll/ctocpp/stream_writer_ctocpp.h create mode 100644 libcef_dll/ctocpp/string_visitor_ctocpp.cc create mode 100644 libcef_dll/ctocpp/string_visitor_ctocpp.h create mode 100644 libcef_dll/ctocpp/task_ctocpp.cc create mode 100644 libcef_dll/ctocpp/task_ctocpp.h create mode 100644 libcef_dll/ctocpp/task_runner_ctocpp.cc create mode 100644 libcef_dll/ctocpp/task_runner_ctocpp.h create mode 100644 libcef_dll/ctocpp/urlrequest_client_ctocpp.cc create mode 100644 libcef_dll/ctocpp/urlrequest_client_ctocpp.h create mode 100644 libcef_dll/ctocpp/urlrequest_ctocpp.cc create mode 100644 libcef_dll/ctocpp/urlrequest_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8accessor_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8accessor_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8context_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8context_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8exception_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8exception_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8stack_frame_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8stack_frame_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8stack_trace_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8stack_trace_ctocpp.h create mode 100644 libcef_dll/ctocpp/v8value_ctocpp.cc create mode 100644 libcef_dll/ctocpp/v8value_ctocpp.h create mode 100644 libcef_dll/ctocpp/web_plugin_info_ctocpp.cc create mode 100644 libcef_dll/ctocpp/web_plugin_info_ctocpp.h create mode 100644 libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc create mode 100644 libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h create mode 100644 libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc create mode 100644 libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h create mode 100644 libcef_dll/ctocpp/write_handler_ctocpp.cc create mode 100644 libcef_dll/ctocpp/write_handler_ctocpp.h create mode 100644 libcef_dll/ctocpp/xml_reader_ctocpp.cc create mode 100644 libcef_dll/ctocpp/xml_reader_ctocpp.h create mode 100644 libcef_dll/ctocpp/zip_reader_ctocpp.cc create mode 100644 libcef_dll/ctocpp/zip_reader_ctocpp.h create mode 100644 libcef_dll/libcef.dll.manifest create mode 100644 libcef_dll/libcef_dll.cc create mode 100644 libcef_dll/libcef_dll.rc create mode 100644 libcef_dll/libcef_dll2.cc create mode 100644 libcef_dll/resource.h create mode 100644 libcef_dll/sandbox/sandbox_win.cc create mode 100644 libcef_dll/transfer_util.cpp create mode 100644 libcef_dll/transfer_util.h create mode 100644 libcef_dll/wrapper/cef_browser_info_map.h create mode 100644 libcef_dll/wrapper/cef_byte_read_handler.cc create mode 100644 libcef_dll/wrapper/cef_closure_task.cc create mode 100644 libcef_dll/wrapper/cef_message_router.cc create mode 100644 libcef_dll/wrapper/cef_stream_resource_handler.cc create mode 100644 libcef_dll/wrapper/cef_xml_object.cc create mode 100644 libcef_dll/wrapper/cef_zip_archive.cc create mode 100644 libcef_dll/wrapper/libcef_dll_wrapper.cc create mode 100644 libcef_dll/wrapper/libcef_dll_wrapper2.cc create mode 100644 patch/README.txt create mode 100644 patch/patch.cfg create mode 100644 patch/patches/browser_web_contents_1257.patch create mode 100644 patch/patches/build.patch create mode 100644 patch/patches/content_nav_1129.patch create mode 100644 patch/patches/gritsettings.patch create mode 100644 patch/patches/gyp_331.patch create mode 100644 patch/patches/message_loop_443.patch create mode 100644 patch/patches/prefs_content_1161.patch create mode 100644 patch/patches/prefs_webkit_1161.patch create mode 100644 patch/patches/public_browser_1161_1257.patch create mode 100644 patch/patches/renderer_host_1161.patch create mode 100644 patch/patches/spi_webcore_364.patch create mode 100644 patch/patches/ui_dragdrop_355390.patch create mode 100644 patch/patches/underlay_1051.patch create mode 100644 patch/patches/views_widget_180.patch create mode 100644 patch/patches/webkit_933.patch create mode 100644 patch/patches/webkit_popups.patch create mode 100644 patch/patches/zlib.patch create mode 100644 tests/cefclient/binding_test.cpp create mode 100644 tests/cefclient/binding_test.h create mode 100644 tests/cefclient/bytes_write_handler.cpp create mode 100644 tests/cefclient/bytes_write_handler.h create mode 100644 tests/cefclient/cefclient.cpp create mode 100644 tests/cefclient/cefclient.exe.manifest create mode 100644 tests/cefclient/cefclient.h create mode 100644 tests/cefclient/cefclient.rc create mode 100644 tests/cefclient/cefclient_gtk.cpp create mode 100644 tests/cefclient/cefclient_mac.mm create mode 100644 tests/cefclient/cefclient_osr_dragdrop_win.cpp create mode 100644 tests/cefclient/cefclient_osr_dragdrop_win.h create mode 100644 tests/cefclient/cefclient_osr_widget_gtk.cpp create mode 100644 tests/cefclient/cefclient_osr_widget_gtk.h create mode 100644 tests/cefclient/cefclient_osr_widget_mac.h create mode 100644 tests/cefclient/cefclient_osr_widget_mac.mm create mode 100644 tests/cefclient/cefclient_osr_widget_win.cpp create mode 100644 tests/cefclient/cefclient_osr_widget_win.h create mode 100644 tests/cefclient/cefclient_win.cpp create mode 100644 tests/cefclient/client_app.cpp create mode 100644 tests/cefclient/client_app.h create mode 100644 tests/cefclient/client_app_delegates.cpp create mode 100644 tests/cefclient/client_handler.cpp create mode 100644 tests/cefclient/client_handler.h create mode 100644 tests/cefclient/client_handler_gtk.cpp create mode 100644 tests/cefclient/client_handler_mac.mm create mode 100644 tests/cefclient/client_handler_win.cpp create mode 100644 tests/cefclient/client_renderer.cpp create mode 100644 tests/cefclient/client_renderer.h create mode 100644 tests/cefclient/client_switches.cpp create mode 100644 tests/cefclient/client_switches.h create mode 100644 tests/cefclient/dialog_test.cpp create mode 100644 tests/cefclient/dialog_test.h create mode 100644 tests/cefclient/dom_test.cpp create mode 100644 tests/cefclient/dom_test.h create mode 100644 tests/cefclient/dragdrop_events.h create mode 100644 tests/cefclient/mac/English.lproj/InfoPlist.strings create mode 100644 tests/cefclient/mac/English.lproj/MainMenu.xib create mode 100644 tests/cefclient/mac/Info.plist create mode 100644 tests/cefclient/mac/cefclient.icns create mode 100644 tests/cefclient/mac/helper-Info.plist create mode 100644 tests/cefclient/osrenderer.cpp create mode 100644 tests/cefclient/osrenderer.h create mode 100644 tests/cefclient/performance_test.cpp create mode 100644 tests/cefclient/performance_test.h create mode 100644 tests/cefclient/performance_test_setup.h create mode 100644 tests/cefclient/performance_test_tests.cpp create mode 100644 tests/cefclient/print_handler_gtk.cpp create mode 100644 tests/cefclient/print_handler_gtk.h create mode 100644 tests/cefclient/process_helper_mac.cpp create mode 100644 tests/cefclient/res/binding.html create mode 100644 tests/cefclient/res/cefclient.ico create mode 100644 tests/cefclient/res/dialogs.html create mode 100644 tests/cefclient/res/domaccess.html create mode 100644 tests/cefclient/res/localstorage.html create mode 100644 tests/cefclient/res/logo.png create mode 100644 tests/cefclient/res/osr_test.html create mode 100644 tests/cefclient/res/other_tests.html create mode 100644 tests/cefclient/res/performance.html create mode 100644 tests/cefclient/res/performance2.html create mode 100644 tests/cefclient/res/small.ico create mode 100644 tests/cefclient/res/transparency.html create mode 100644 tests/cefclient/res/window.html create mode 100644 tests/cefclient/res/xmlhttprequest.html create mode 100644 tests/cefclient/resource.h create mode 100644 tests/cefclient/resource_util.h create mode 100644 tests/cefclient/resource_util_linux.cpp create mode 100644 tests/cefclient/resource_util_mac.mm create mode 100644 tests/cefclient/resource_util_posix.cpp create mode 100644 tests/cefclient/resource_util_win.cpp create mode 100644 tests/cefclient/scheme_test.cpp create mode 100644 tests/cefclient/scheme_test.h create mode 100644 tests/cefclient/string_util.cpp create mode 100644 tests/cefclient/string_util.h create mode 100644 tests/cefclient/window_test.cpp create mode 100644 tests/cefclient/window_test.h create mode 100644 tests/cefclient/window_test_gtk.cpp create mode 100644 tests/cefclient/window_test_mac.mm create mode 100644 tests/cefclient/window_test_win.cpp create mode 100644 tests/cefsimple/cefsimple.exe.manifest create mode 100644 tests/cefsimple/cefsimple.rc create mode 100644 tests/cefsimple/cefsimple_linux.cpp create mode 100644 tests/cefsimple/cefsimple_mac.mm create mode 100644 tests/cefsimple/cefsimple_win.cpp create mode 100644 tests/cefsimple/mac/English.lproj/InfoPlist.strings create mode 100644 tests/cefsimple/mac/English.lproj/MainMenu.xib create mode 100644 tests/cefsimple/mac/Info.plist create mode 100644 tests/cefsimple/mac/cefsimple.icns create mode 100644 tests/cefsimple/mac/helper-Info.plist create mode 100644 tests/cefsimple/process_helper_mac.cpp create mode 100644 tests/cefsimple/res/cefsimple.ico create mode 100644 tests/cefsimple/res/small.ico create mode 100644 tests/cefsimple/resource.h create mode 100644 tests/cefsimple/simple_app.cpp create mode 100644 tests/cefsimple/simple_app.h create mode 100644 tests/cefsimple/simple_handler.cpp create mode 100644 tests/cefsimple/simple_handler.h create mode 100644 tests/cefsimple/simple_handler_linux.cpp create mode 100644 tests/cefsimple/simple_handler_mac.mm create mode 100644 tests/cefsimple/simple_handler_win.cpp create mode 100644 tests/unittests/browser_info_map_unittest.cc create mode 100644 tests/unittests/chromium_includes.h create mode 100644 tests/unittests/client_app_delegates.cc create mode 100644 tests/unittests/command_line_unittest.cc create mode 100644 tests/unittests/cookie_unittest.cc create mode 100644 tests/unittests/dialog_unittest.cc create mode 100644 tests/unittests/display_unittest.cc create mode 100644 tests/unittests/dom_unittest.cc create mode 100644 tests/unittests/download_unittest.cc create mode 100644 tests/unittests/geolocation_unittest.cc create mode 100644 tests/unittests/jsdialog_unittest.cc create mode 100644 tests/unittests/life_span_unittest.cc create mode 100644 tests/unittests/mac/English.lproj/InfoPlist.strings create mode 100644 tests/unittests/mac/English.lproj/MainMenu.xib create mode 100644 tests/unittests/mac/Info.plist create mode 100644 tests/unittests/mac/unittests.icns create mode 100644 tests/unittests/message_router_unittest.cc create mode 100644 tests/unittests/navigation_unittest.cc create mode 100644 tests/unittests/os_rendering_unittest.cc create mode 100644 tests/unittests/os_rendering_unittest_mac.h create mode 100644 tests/unittests/os_rendering_unittest_mac.mm create mode 100644 tests/unittests/print_unittest.cc create mode 100644 tests/unittests/process_message_unittest.cc create mode 100644 tests/unittests/request_context_unittest.cc create mode 100644 tests/unittests/request_handler_unittest.cc create mode 100644 tests/unittests/request_unittest.cc create mode 100644 tests/unittests/routing_test_handler.cc create mode 100644 tests/unittests/routing_test_handler.h create mode 100644 tests/unittests/run_all_unittests.cc create mode 100644 tests/unittests/run_all_unittests_mac.mm create mode 100644 tests/unittests/scheme_handler_unittest.cc create mode 100644 tests/unittests/stream_resource_handler_unittest.cc create mode 100644 tests/unittests/stream_unittest.cc create mode 100644 tests/unittests/string_unittest.cc create mode 100644 tests/unittests/task_unittest.cc create mode 100644 tests/unittests/test_handler.cc create mode 100644 tests/unittests/test_handler.h create mode 100644 tests/unittests/test_suite.cc create mode 100644 tests/unittests/test_suite.h create mode 100644 tests/unittests/test_util.cc create mode 100644 tests/unittests/test_util.h create mode 100644 tests/unittests/tracing_unittest.cc create mode 100644 tests/unittests/url_unittest.cc create mode 100644 tests/unittests/urlrequest_unittest.cc create mode 100644 tests/unittests/v8_unittest.cc create mode 100644 tests/unittests/values_unittest.cc create mode 100644 tests/unittests/version_unittest.cc create mode 100644 tests/unittests/xml_reader_unittest.cc create mode 100644 tests/unittests/zip_reader_unittest.cc create mode 100644 tools/automate/automate-git.py create mode 100644 tools/automate/automate.README.txt create mode 100644 tools/automate/automate.py create mode 100644 tools/automate/gitsvnmirror.py create mode 100644 tools/build_projects.bat create mode 100755 tools/build_projects.sh create mode 100644 tools/cef_api_hash.py create mode 100644 tools/cef_parser.py create mode 100644 tools/check_revision.py create mode 100644 tools/check_style.bat create mode 100644 tools/check_style.py create mode 100755 tools/check_style.sh create mode 100644 tools/combine_libs.py create mode 100644 tools/date_util.py create mode 100644 tools/distrib/README-TRANSFER.txt create mode 100644 tools/distrib/README.client.txt create mode 100644 tools/distrib/README.footer.txt create mode 100644 tools/distrib/README.header.txt create mode 100644 tools/distrib/cefclient.gyp create mode 100644 tools/distrib/linux/README.minimal.txt create mode 100644 tools/distrib/linux/README.redistrib.txt create mode 100644 tools/distrib/linux/README.standard.txt create mode 100755 tools/distrib/linux/build.sh create mode 100644 tools/distrib/mac/README.minimal.txt create mode 100644 tools/distrib/mac/README.redistrib.txt create mode 100644 tools/distrib/mac/README.standard.txt create mode 100644 tools/distrib/mac/transfer.cfg create mode 100644 tools/distrib/transfer.cfg create mode 100644 tools/distrib/win/README.minimal.txt create mode 100644 tools/distrib/win/README.redistrib.txt create mode 100644 tools/distrib/win/README.standard.txt create mode 100644 tools/distrib/win/d3dcompiler_43.dll create mode 100644 tools/distrib/win/transfer.cfg create mode 100644 tools/exec_util.py create mode 100644 tools/file_util.py create mode 100644 tools/gclient_hook.py create mode 100644 tools/gclient_util.py create mode 100644 tools/git_util.py create mode 100644 tools/make_capi_header.py create mode 100644 tools/make_cppdocs.bat create mode 100644 tools/make_cpptoc_header.py create mode 100644 tools/make_cpptoc_impl.py create mode 100644 tools/make_ctocpp_header.py create mode 100644 tools/make_ctocpp_impl.py create mode 100644 tools/make_distrib.bat create mode 100644 tools/make_distrib.py create mode 100755 tools/make_distrib.sh create mode 100644 tools/make_gypi_file.py create mode 100644 tools/make_pack_header.py create mode 100644 tools/make_version_header.bat create mode 100644 tools/make_version_header.py create mode 100755 tools/make_version_header.sh create mode 100644 tools/msvs_env.bat create mode 100644 tools/patch.bat create mode 100755 tools/patch.sh create mode 100644 tools/patch_updater.py create mode 100644 tools/patch_util.py create mode 100644 tools/patcher.README.txt create mode 100644 tools/patcher.py create mode 100644 tools/repack_locales.py create mode 100644 tools/revision.py create mode 100644 tools/svn_util.py create mode 100644 tools/translator.README.txt create mode 100644 tools/translator.bat create mode 100644 tools/translator.py create mode 100755 tools/translator.sh diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 000000000..1b5b1032b --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,28 @@ +# This file is an addendum to the Chromium AUTHORS file. +# Names should be added to this file like so: +# Name or Organization + +Marshall Greenblatt +Jamie Kirkpatrick +Johan Lindström +Igor Pavlov +Yanko Yankov +Emerick Rogul +Valve Corporation +Anthony Taranto +Joe Andrieu +Keith Poole +Aviv Rind +Michael Kaminski +ADInstruments Ltd. +Gus Verdun +Joinerysoft Ltd. +Johan Björk +Dmitry Azaraev +David Xue +Russell (Rusty) Richards +Brian Power +Corey Lucier +Mihai Tica +Czarek Tomczak +Felix Bruns diff --git a/CHROMIUM_BUILD_COMPATIBILITY.txt b/CHROMIUM_BUILD_COMPATIBILITY.txt new file mode 100644 index 000000000..0d169a07c --- /dev/null +++ b/CHROMIUM_BUILD_COMPATIBILITY.txt @@ -0,0 +1,12 @@ +# The Chromium Embedded Framework (CEF) project is built on top of the Chromium +# project source tree. Chromium should be updated to the URL and revision listed +# below before building CEF. Chromium compatibility information for older CEF +# revisions is available by viewing this file's change history. +# +# Instructions for building CEF are available at: +# https://code.google.com/p/chromiumembedded/wiki/BranchesAndBuilding + +{ + 'release_url': 'http://src.chromium.org/svn/releases/37.0.2062.58', + 'chromium_checkout': 'refs/tags/37.0.2062.58', +} diff --git a/DEPS b/DEPS new file mode 100644 index 000000000..0a7dc22e3 --- /dev/null +++ b/DEPS @@ -0,0 +1,7 @@ +hooks = [ + { + # A change to a .gyp, .gypi, or to GYP itself should run the generator. + "pattern": ".", + "action": ["python", "src/cef/tools/gclient_hook.py"], + }, +] diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..a5d84adab --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,29 @@ +// Copyright (c) 2008-2013 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-2009 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. diff --git a/VERSION b/VERSION new file mode 100644 index 000000000..2ecb9806b --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +CEF_MAJOR=3 diff --git a/cef.gyp b/cef.gyp new file mode 100644 index 000000000..fe7c21702 --- /dev/null +++ b/cef.gyp @@ -0,0 +1,1682 @@ +# 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. + +{ + 'variables': { + 'pkg-config': 'pkg-config', + 'chromium_code': 1, + 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/cef', + 'about_credits_file': '<(SHARED_INTERMEDIATE_DIR)/about_credits.html', + 'framework_name': 'Chromium Embedded Framework', + 'revision': '=46', { + 'target_defaults': { + # Disable warnings about c++0x compatibility, as some names (such + # as nullptr) conflict with upcoming c++0x types. + 'cflags_cc': ['-Wno-c++0x-compat'], + }, + }], + ['OS=="mac"', { + 'targets': [ + { + 'target_name': 'cef_framework', + 'type': 'shared_library', + 'product_name': '<(framework_name)', + 'mac_bundle': 1, + 'mac_bundle_resources': [ + '<(PRODUCT_DIR)/cef.pak', + '<(PRODUCT_DIR)/cef_100_percent.pak', + '<(PRODUCT_DIR)/cef_200_percent.pak', + '<(PRODUCT_DIR)/devtools_resources.pak', + '<(PRODUCT_DIR)/icudtl.dat', + 'libcef/resources/framework-Info.plist', + ], + 'mac_bundle_resources!': [ + 'libcef/resources/framework-Info.plist', + ], + 'xcode_settings': { + # Default path that will be changed by install_name_tool in dependent targets. + 'INSTALL_PATH': '@executable_path', + 'DYLIB_INSTALL_NAME_BASE': '@executable_path', + 'LD_DYLIB_INSTALL_NAME': '@executable_path/<(framework_name)', + + # The libcef_static target contains ObjC categories. Passing the -ObjC flag + # is necessary to properly load them and avoid a "selector not recognized" + # runtime error. See http://developer.apple.com/library/mac/#qa/qa1490/_index.html + # for more information. + 'OTHER_LDFLAGS': ['-Wl,-ObjC'], + + 'DYLIB_COMPATIBILITY_VERSION': '<(version_mac_dylib)', + 'DYLIB_CURRENT_VERSION': '<(version_mac_dylib)', + 'INFOPLIST_FILE': 'libcef/resources/framework-Info.plist', + }, + 'dependencies': [ + 'cef_pak', + 'libcef_static', + ], + 'defines': [ + 'BUILDING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + '<@(includes_common)', + '<@(includes_capi)', + '<@(libcef_sources_common)', + ], + 'postbuilds': [ + { + # Modify the Info.plist as needed. The script explains why + # this is needed. This is also done in the chrome target. + # The framework needs the Breakpad keys if this feature is + # enabled. It does not need the Keystone keys; these always + # come from the outer application bundle. The framework + # doesn't currently use the SCM keys for anything, + # but this seems like a really good place to store them. + 'postbuild_name': 'Tweak Info.plist', + 'action': ['../build/mac/tweak_info_plist.py', + '--breakpad=1', + '--keystone=0', + '--scm=1', + '--version=<(chrome_version)', + '--branding=<(framework_name)'], + }, + ], + 'copies': [ + { + # Copy binaries for HTML5 audio/video and PDF support. + 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries', + 'files': [ + '<(PRODUCT_DIR)/ffmpegsumo.so', + '<(PRODUCT_DIR)/PDF.plugin', + ], + }, + { + # Copy binaries for breakpad support. + 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Resources', + 'files': [ + '<(PRODUCT_DIR)/crash_inspector', + '<(PRODUCT_DIR)/crash_report_sender.app', + ], + }, + ], + }, # target cef_framework + { + 'target_name': 'cefclient_helper_app', + 'type': 'executable', + 'variables': { 'enable_wexit_time_destructors': 1, }, + 'product_name': 'cefclient Helper', + 'mac_bundle': 1, + 'dependencies': [ + 'cef_framework', + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + # cefclient includes are relative to the tests directory to make + # creation of binary releases easier. + 'tests' + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + ], + }, + 'sources': [ + '<@(cefclient_sources_mac_helper)', + ], + # TODO(mark): Come up with a fancier way to do this. It should only + # be necessary to list helper-Info.plist once, not the three times it + # is listed here. + 'mac_bundle_resources!': [ + 'tests/cefclient/mac/helper-Info.plist', + ], + # TODO(mark): For now, don't put any resources into this app. Its + # resources directory will be a symbolic link to the browser app's + # resources directory. + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'tests/cefclient/mac/helper-Info.plist', + # Necessary to avoid an "install_name_tool: changing install names or + # rpaths can't be redone" error. + 'OTHER_LDFLAGS': ['-Wl,-headerpad_max_install_names'], + }, + 'postbuilds': [ + { + # The framework defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # cefclient_helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + { + # Modify the Info.plist as needed. The script explains why this + # is needed. This is also done in the chrome and chrome_dll + # targets. In this case, --breakpad=0, --keystone=0, and --scm=0 + # are used because Breakpad, Keystone, and SCM keys are + # never placed into the helper. + 'postbuild_name': 'Tweak Info.plist', + 'action': ['../build/mac/tweak_info_plist.py', + '--breakpad=0', + '--keystone=0', + '--scm=0'], + }, + ], + }, # target cefclient_helper_app + { + 'target_name': 'cefsimple_helper_app', + 'type': 'executable', + 'variables': { 'enable_wexit_time_destructors': 1, }, + 'product_name': 'cefsimple Helper', + 'mac_bundle': 1, + 'dependencies': [ + 'cef_framework', + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + # cefsimple includes are relative to the tests directory to make + # creation of binary releases easier. + 'tests' + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + ], + }, + 'sources': [ + '<@(cefsimple_sources_mac_helper)', + ], + # TODO(mark): Come up with a fancier way to do this. It should only + # be necessary to list helper-Info.plist once, not the three times it + # is listed here. + 'mac_bundle_resources!': [ + 'tests/cefsimple/mac/helper-Info.plist', + ], + # TODO(mark): For now, don't put any resources into this app. Its + # resources directory will be a symbolic link to the browser app's + # resources directory. + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'tests/cefsimple/mac/helper-Info.plist', + # Necessary to avoid an "install_name_tool: changing install names or + # rpaths can't be redone" error. + 'OTHER_LDFLAGS': ['-Wl,-headerpad_max_install_names'], + }, + 'postbuilds': [ + { + # The framework defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # cefsimple_helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + { + # Modify the Info.plist as needed. The script explains why this + # is needed. This is also done in the chrome and chrome_dll + # targets. In this case, --breakpad=0, --keystone=0, and --scm=0 + # are used because Breakpad, Keystone, and SCM keys are + # never placed into the helper. + 'postbuild_name': 'Tweak Info.plist', + 'action': ['../build/mac/tweak_info_plist.py', + '--breakpad=0', + '--keystone=0', + '--scm=0'], + }, + ], + }, # target cefsimple_helper_app + { + 'target_name': 'cef_unittests_helper_app', + 'type': 'executable', + 'product_name': 'cef_unittests Helper', + 'mac_bundle': 1, + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/base/base.gyp:base_i18n', + '<(DEPTH)/base/base.gyp:test_support_base', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/icu/icu.gyp:icui18n', + '<(DEPTH)/third_party/icu/icu.gyp:icuuc', + 'cef_framework', + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + 'tests/cefclient/client_app.cpp', + 'tests/cefclient/client_app.h', + 'tests/cefclient/client_switches.cpp', + 'tests/cefclient/client_switches.h', + 'tests/cefclient/process_helper_mac.cpp', + 'tests/unittests/client_app_delegates.cc', + 'tests/unittests/cookie_unittest.cc', + 'tests/unittests/dom_unittest.cc', + 'tests/unittests/message_router_unittest.cc', + 'tests/unittests/navigation_unittest.cc', + 'tests/unittests/process_message_unittest.cc', + 'tests/unittests/request_handler_unittest.cc', + 'tests/unittests/request_unittest.cc', + 'tests/unittests/routing_test_handler.cc', + 'tests/unittests/routing_test_handler.h', + 'tests/unittests/scheme_handler_unittest.cc', + 'tests/unittests/urlrequest_unittest.cc', + 'tests/unittests/test_handler.cc', + 'tests/unittests/test_handler.h', + 'tests/unittests/test_suite.cc', + 'tests/unittests/test_suite.h', + 'tests/unittests/test_util.cc', + 'tests/unittests/test_util.h', + 'tests/unittests/tracing_unittest.cc', + 'tests/unittests/v8_unittest.cc', + ], + # TODO(mark): Come up with a fancier way to do this. It should only + # be necessary to list helper-Info.plist once, not the three times it + # is listed here. + 'mac_bundle_resources!': [ + 'tests/cefclient/mac/helper-Info.plist', + ], + # TODO(mark): For now, don't put any resources into this app. Its + # resources directory will be a symbolic link to the browser app's + # resources directory. + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'tests/cefclient/mac/helper-Info.plist', + # Necessary to avoid an "install_name_tool: changing install names or + # rpaths can't be redone" error. + 'OTHER_LDFLAGS': ['-Wl,-headerpad_max_install_names'], + }, + 'postbuilds': [ + { + # The framework defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # cefclient_helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + { + # Modify the Info.plist as needed. The script explains why this + # is needed. This is also done in the chrome and chrome_dll + # targets. In this case, --breakpad=0, --keystone=0, and --scm=0 + # are used because Breakpad, Keystone, and SCM keys are + # never placed into the helper. + 'postbuild_name': 'Tweak Info.plist', + 'action': ['../build/mac/tweak_info_plist.py', + '--breakpad=0', + '--keystone=0', + '--scm=0'], + }, + ], + }, # target cef_unittests_helper_app + ], + }, { # OS!="mac" + 'targets': [ + { + 'target_name': 'libcef', + 'type': 'shared_library', + 'msvs_guid': 'C13650D5-CF1A-4259-BE45-B1EBA6280E47', + 'dependencies': [ + 'libcef_static', + ], + 'defines': [ + 'BUILDING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + '<@(includes_common)', + '<@(includes_capi)', + '<@(libcef_sources_common)', + ], + 'conditions': [ + ['OS=="win" and win_use_allocator_shim==1', { + 'dependencies': [ + '<(DEPTH)/base/allocator/allocator.gyp:allocator', + ], + }], + ['OS=="win"', { + 'configurations': { + 'Debug_Base': { + 'msvs_settings': { + 'VCLinkerTool': { + 'LinkIncremental': '<(msvs_large_module_debug_link_mode)', + }, + }, + }, + }, + 'sources': [ + '<@(includes_win)', + # TODO(cef): Remove ui_unscaled_resources.rc once custom cursor + # resources can be loaded via ResourceBundle. See crbug.com/147663. + '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.rc', + '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_unscaled_resources.rc', + 'libcef_dll/libcef_dll.rc', + ], + 'link_settings': { + 'libraries': [ + '-lcomctl32.lib', + ], + }, + 'msvs_settings': { + 'VCLinkerTool': { + # Generate a PDB symbol file for both Debug and Release builds. + 'GenerateDebugInformation': 'true', + }, + 'VCManifestTool': { + 'AdditionalManifestFiles': [ + 'libcef_dll/libcef.dll.manifest', + ], + }, + }, + }], + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'dependencies':[ + '<(DEPTH)/base/allocator/allocator.gyp:allocator', + ], + }], + ], + }], + }], # OS!="mac" + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'targets': [ + { + 'target_name': 'gtk', + 'type': 'none', + 'variables': { + # gtk requires gmodule, but it does not list it as a dependency + # in some misconfigured systems. + 'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0', + }, + 'direct_dependent_settings': { + 'cflags': [ + ' + +#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_ diff --git a/include/base/cef_basictypes.h b/include/base/cef_basictypes.h new file mode 100644 index 000000000..af3431127 --- /dev/null +++ b/include/base/cef_basictypes.h @@ -0,0 +1,86 @@ +// 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 // For UINT_MAX +#include // 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 +// 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 + +// UTF-16 character type +#ifndef char16 +#if defined(WIN32) +typedef wchar_t char16; +#else +typedef unsigned short char16; +#endif +#endif + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_BASICTYPES_H_ diff --git a/include/base/cef_bind.h b/include/base/cef_bind.h new file mode 100644 index 000000000..c3f56f337 --- /dev/null +++ b/include/base/cef_bind.h @@ -0,0 +1,548 @@ +// 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. + +#ifndef CEF_INCLUDE_BASE_CEF_BIND_H_ +#define CEF_INCLUDE_BASE_CEF_BIND_H_ +#pragma once + +#if defined(BASE_BIND_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/bind.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/internal/cef_bind_internal.h" +#include "include/base/internal/cef_callback_internal.h" + +// ----------------------------------------------------------------------------- +// Usage documentation +// ----------------------------------------------------------------------------- +// +// See base/cef_callback.h for documentation. +// +// +// ----------------------------------------------------------------------------- +// Implementation notes +// ----------------------------------------------------------------------------- +// +// If you're reading the implementation, before proceeding further, you should +// read the top comment of base/bind_internal.h for a definition of common +// terms and concepts. +// +// RETURN TYPES +// +// Though Bind()'s result is meant to be stored in a Callback<> type, it +// cannot actually return the exact type without requiring a large amount +// of extra template specializations. The problem is that in order to +// discern the correct specialization of Callback<>, Bind would need to +// unwrap the function signature to determine the signature's arity, and +// whether or not it is a method. +// +// Each unique combination of (arity, function_type, num_prebound) where +// function_type is one of {function, method, const_method} would require +// one specialization. We eventually have to do a similar number of +// specializations anyways in the implementation (see the Invoker<>, +// classes). However, it is avoidable in Bind if we return the result +// via an indirection like we do below. +// +// TODO(ajwong): We might be able to avoid this now, but need to test. +// +// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, +// but it feels a little nicer to have the asserts here so people do not +// need to crack open bind_internal.h. On the other hand, it makes Bind() +// harder to read. + +namespace base { + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void()> + ::UnboundRunType> +Bind(Functor functor) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + typedef internal::BindState BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor))); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + typedef internal::BindState::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5, const P6& p6) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p6_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); +} + +template +base::Callback< + typename internal::BindState< + typename internal::FunctorTraits::RunnableType, + typename internal::FunctorTraits::RunType, + void(typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> + ::UnboundRunType> +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5, const P6& p6, const P7& p7) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits::RunnableType RunnableType; + typedef typename internal::FunctorTraits::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value || + is_non_const_reference::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag::value || + !internal::NeedsScopedRefptrButGetsRawPtr::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag::value || + !is_array::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p6_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr::value, + p7_is_refcounted_type_and_needs_scoped_refptr); + typedef internal::BindState::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType, + typename internal::CallbackParamTraits::StorageType)> BindState; + + + return Callback( + new BindState(internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, + p7)); +} + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_BIND_H_ diff --git a/include/base/cef_bind_helpers.h b/include/base/cef_bind_helpers.h new file mode 100644 index 000000000..8edac5c03 --- /dev/null +++ b/include/base/cef_bind_helpers.h @@ -0,0 +1,586 @@ +// 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 defines a set of argument wrappers and related factory methods that +// can be used specify the refcounting and reference semantics of arguments +// that are bound by the Bind() function in base/bind.h. +// +// It also defines a set of simple functions and utilities that people want +// when using Callback<> and Bind(). +// +// +// ARGUMENT BINDING WRAPPERS +// +// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(), +// base::ConstRef(), and base::IgnoreResult(). +// +// Unretained() allows Bind() to bind a non-refcounted class, and to disable +// refcounting on arguments that are refcounted objects. +// +// Owned() transfers ownership of an object to the Callback resulting from +// bind; the object will be deleted when the Callback is deleted. +// +// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) +// through a Callback. Logically, this signifies a destructive transfer of +// the state of the argument into the target function. Invoking +// Callback::Run() twice on a Callback that was created with a Passed() +// argument will CHECK() because the first invocation would have already +// transferred ownership to the target function. +// +// ConstRef() allows binding a constant reference to an argument rather +// than a copy. +// +// IgnoreResult() is used to adapt a function or Callback with a return type to +// one with a void return. This is most useful if you have a function with, +// say, a pesky ignorable bool return that you want to use with PostTask or +// something else that expect a Callback with a void return. +// +// EXAMPLE OF Unretained(): +// +// class Foo { +// public: +// void func() { cout << "Foo:f" << endl; } +// }; +// +// // In some function somewhere. +// Foo foo; +// Closure foo_callback = +// Bind(&Foo::func, Unretained(&foo)); +// foo_callback.Run(); // Prints "Foo:f". +// +// Without the Unretained() wrapper on |&foo|, the above call would fail +// to compile because Foo does not support the AddRef() and Release() methods. +// +// +// EXAMPLE OF Owned(): +// +// void foo(int* arg) { cout << *arg << endl } +// +// int* pn = new int(1); +// Closure foo_callback = Bind(&foo, Owned(pn)); +// +// foo_callback.Run(); // Prints "1" +// foo_callback.Run(); // Prints "1" +// *n = 2; +// foo_callback.Run(); // Prints "2" +// +// foo_callback.Reset(); // |pn| is deleted. Also will happen when +// // |foo_callback| goes out of scope. +// +// Without Owned(), someone would have to know to delete |pn| when the last +// reference to the Callback is deleted. +// +// +// EXAMPLE OF ConstRef(): +// +// void foo(int arg) { cout << arg << endl } +// +// int n = 1; +// Closure no_ref = Bind(&foo, n); +// Closure has_ref = Bind(&foo, ConstRef(n)); +// +// no_ref.Run(); // Prints "1" +// has_ref.Run(); // Prints "1" +// +// n = 2; +// no_ref.Run(); // Prints "1" +// has_ref.Run(); // Prints "2" +// +// Note that because ConstRef() takes a reference on |n|, |n| must outlive all +// its bound callbacks. +// +// +// EXAMPLE OF IgnoreResult(): +// +// int DoSomething(int arg) { cout << arg << endl; } +// +// // Assign to a Callback with a void return type. +// Callback cb = Bind(IgnoreResult(&DoSomething)); +// cb->Run(1); // Prints "1". +// +// // Prints "1" on |ml|. +// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); +// +// +// EXAMPLE OF Passed(): +// +// void TakesOwnership(scoped_ptr arg) { } +// scoped_ptr CreateFoo() { return scoped_ptr(new Foo()); } +// +// scoped_ptr f(new Foo()); +// +// // |cb| is given ownership of Foo(). |f| is now NULL. +// // You can use f.Pass() in place of &f, but it's more verbose. +// Closure cb = Bind(&TakesOwnership, Passed(&f)); +// +// // Run was never called so |cb| still owns Foo() and deletes +// // it on Reset(). +// cb.Reset(); +// +// // |cb| is given a new Foo created by CreateFoo(). +// cb = Bind(&TakesOwnership, Passed(CreateFoo())); +// +// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| +// // no longer owns Foo() and, if reset, would not delete Foo(). +// cb.Run(); // Foo() is now transferred to |arg| and deleted. +// cb.Run(); // This CHECK()s since Foo() already been used once. +// +// Passed() is particularly useful with PostTask() when you are transferring +// ownership of an argument into a task, but don't necessarily know if the +// task will always be executed. This can happen if the task is cancellable +// or if it is posted to a MessageLoopProxy. +// +// +// SIMPLE FUNCTIONS AND UTILITIES. +// +// DoNothing() - Useful for creating a Closure that does nothing when called. +// DeletePointer() - Useful for creating a Closure that will delete a +// pointer when invoked. Only use this when necessary. +// In most cases MessageLoop::DeleteSoon() is a better +// fit. + +#ifndef CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ +#define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ +#pragma once + +#if defined(BASE_BIND_HELPERS_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/bind_helpers.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_basictypes.h" +#include "include/base/cef_callback.h" +#include "include/base/cef_template_util.h" +#include "include/base/cef_weak_ptr.h" + +namespace base { +namespace internal { + +// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T +// for the existence of AddRef() and Release() functions of the correct +// signature. +// +// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error +// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence +// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison +// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions +// +// The last link in particular show the method used below. +// +// For SFINAE to work with inherited methods, we need to pull some extra tricks +// with multiple inheritance. In the more standard formulation, the overloads +// of Check would be: +// +// template +// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); +// +// template +// No NotTheCheckWeWant(...); +// +// static const bool value = sizeof(NotTheCheckWeWant(0)) == sizeof(Yes); +// +// The problem here is that template resolution will not match +// C::TargetFunc if TargetFunc does not exist directly in C. That is, if +// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, +// |value| will be false. This formulation only checks for whether or +// not TargetFunc exist directly in the class being introspected. +// +// To get around this, we play a dirty trick with multiple inheritance. +// First, We create a class BaseMixin that declares each function that we +// want to probe for. Then we create a class Base that inherits from both T +// (the class we wish to probe) and BaseMixin. Note that the function +// signature in BaseMixin does not need to match the signature of the function +// we are probing for; thus it's easiest to just use void(void). +// +// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an +// ambiguous resolution between BaseMixin and T. This lets us write the +// following: +// +// template +// No GoodCheck(Helper<&C::TargetFunc>*); +// +// template +// Yes GoodCheck(...); +// +// static const bool value = sizeof(GoodCheck(0)) == sizeof(Yes); +// +// Notice here that the variadic version of GoodCheck() returns Yes here +// instead of No like the previous one. Also notice that we calculate |value| +// by specializing GoodCheck() on Base instead of T. +// +// We've reversed the roles of the variadic, and Helper overloads. +// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid +// substitution if T::TargetFunc exists. Thus GoodCheck(0) will resolve +// to the variadic version if T has TargetFunc. If T::TargetFunc does not +// exist, then &C::TargetFunc is not ambiguous, and the overload resolution +// will prefer GoodCheck(Helper<&C::TargetFunc>*). +// +// This method of SFINAE will correctly probe for inherited names, but it cannot +// typecheck those names. It's still a good enough sanity check though. +// +// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. +// +// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted +// this works well. +// +// TODO(ajwong): Make this check for Release() as well. +// See http://crbug.com/82038. +template +class SupportsAddRefAndRelease { + typedef char Yes[1]; + typedef char No[2]; + + struct BaseMixin { + void AddRef(); + }; + +// MSVC warns when you try to use Base if T has a private destructor, the +// common pattern for refcounted types. It does this even though no attempt to +// instantiate Base is made. We disable the warning for this definition. +#if defined(OS_WIN) +#pragma warning(push) +#pragma warning(disable:4624) +#endif + struct Base : public T, public BaseMixin { + }; +#if defined(OS_WIN) +#pragma warning(pop) +#endif + + template struct Helper {}; + + template + static No& Check(Helper<&C::AddRef>*); + + template + static Yes& Check(...); + + public: + static const bool value = sizeof(Check(0)) == sizeof(Yes); +}; + +// Helpers to assert that arguments of a recounted type are bound with a +// scoped_refptr. +template +struct UnsafeBindtoRefCountedArgHelper : false_type { +}; + +template +struct UnsafeBindtoRefCountedArgHelper + : integral_constant::value> { +}; + +template +struct UnsafeBindtoRefCountedArg : false_type { +}; + +template +struct UnsafeBindtoRefCountedArg + : UnsafeBindtoRefCountedArgHelper::value, T> { +}; + +template +class HasIsMethodTag { + typedef char Yes[1]; + typedef char No[2]; + + template + static Yes& Check(typename U::IsMethod*); + + template + static No& Check(...); + + public: + static const bool value = sizeof(Check(0)) == sizeof(Yes); +}; + +template +class UnretainedWrapper { + public: + explicit UnretainedWrapper(T* o) : ptr_(o) {} + T* get() const { return ptr_; } + private: + T* ptr_; +}; + +template +class ConstRefWrapper { + public: + explicit ConstRefWrapper(const T& o) : ptr_(&o) {} + const T& get() const { return *ptr_; } + private: + const T* ptr_; +}; + +template +struct IgnoreResultHelper { + explicit IgnoreResultHelper(T functor) : functor_(functor) {} + + T functor_; +}; + +template +struct IgnoreResultHelper > { + explicit IgnoreResultHelper(const Callback& functor) : functor_(functor) {} + + const Callback& functor_; +}; + +// An alternate implementation is to avoid the destructive copy, and instead +// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to +// a class that is essentially a scoped_ptr<>. +// +// The current implementation has the benefit though of leaving ParamTraits<> +// fully in callback_internal.h as well as avoiding type conversions during +// storage. +template +class OwnedWrapper { + public: + explicit OwnedWrapper(T* o) : ptr_(o) {} + ~OwnedWrapper() { delete ptr_; } + T* get() const { return ptr_; } + OwnedWrapper(const OwnedWrapper& other) { + ptr_ = other.ptr_; + other.ptr_ = NULL; + } + + private: + mutable T* ptr_; +}; + +// PassedWrapper is a copyable adapter for a scoper that ignores const. +// +// It is needed to get around the fact that Bind() takes a const reference to +// all its arguments. Because Bind() takes a const reference to avoid +// unnecessary copies, it is incompatible with movable-but-not-copyable +// types; doing a destructive "move" of the type into Bind() would violate +// the const correctness. +// +// This conundrum cannot be solved without either C++11 rvalue references or +// a O(2^n) blowup of Bind() templates to handle each combination of regular +// types and movable-but-not-copyable types. Thus we introduce a wrapper type +// that is copyable to transmit the correct type information down into +// BindState<>. Ignoring const in this type makes sense because it is only +// created when we are explicitly trying to do a destructive move. +// +// Two notes: +// 1) PassedWrapper supports any type that has a "Pass()" function. +// This is intentional. The whitelisting of which specific types we +// support is maintained by CallbackParamTraits<>. +// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" +// scoper to a Callback and allow the Callback to execute once. +template +class PassedWrapper { + public: + explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} + PassedWrapper(const PassedWrapper& other) + : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { + } + T Pass() const { + CHECK(is_valid_); + is_valid_ = false; + return scoper_.Pass(); + } + + private: + mutable bool is_valid_; + mutable T scoper_; +}; + +// Unwrap the stored parameters for the wrappers above. +template +struct UnwrapTraits { + typedef const T& ForwardType; + static ForwardType Unwrap(const T& o) { return o; } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(UnretainedWrapper unretained) { + return unretained.get(); + } +}; + +template +struct UnwrapTraits > { + typedef const T& ForwardType; + static ForwardType Unwrap(ConstRefWrapper const_ref) { + return const_ref.get(); + } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(const scoped_refptr& o) { return o.get(); } +}; + +template +struct UnwrapTraits > { + typedef const WeakPtr& ForwardType; + static ForwardType Unwrap(const WeakPtr& o) { return o; } +}; + +template +struct UnwrapTraits > { + typedef T* ForwardType; + static ForwardType Unwrap(const OwnedWrapper& o) { + return o.get(); + } +}; + +template +struct UnwrapTraits > { + typedef T ForwardType; + static T Unwrap(PassedWrapper& o) { + return o.Pass(); + } +}; + +// Utility for handling different refcounting semantics in the Bind() +// function. +template +struct MaybeRefcount; + +template +struct MaybeRefcount { + static void AddRef(const T&) {} + static void Release(const T&) {} +}; + +template +struct MaybeRefcount { + static void AddRef(const T*) {} + static void Release(const T*) {} +}; + +template +struct MaybeRefcount { + static void AddRef(const T&) {} + static void Release(const T&) {} +}; + +template +struct MaybeRefcount { + static void AddRef(T* o) { o->AddRef(); } + static void Release(T* o) { o->Release(); } +}; + +// No need to additionally AddRef() and Release() since we are storing a +// scoped_refptr<> inside the storage object already. +template +struct MaybeRefcount > { + static void AddRef(const scoped_refptr& o) {} + static void Release(const scoped_refptr& o) {} +}; + +template +struct MaybeRefcount { + static void AddRef(const T* o) { o->AddRef(); } + static void Release(const T* o) { o->Release(); } +}; + +// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a +// method. It is used internally by Bind() to select the correct +// InvokeHelper that will no-op itself in the event the WeakPtr<> for +// the target object is invalidated. +// +// P1 should be the type of the object that will be received of the method. +template +struct IsWeakMethod : public false_type {}; + +template +struct IsWeakMethod > : public true_type {}; + +template +struct IsWeakMethod > > : public true_type {}; + +} // namespace internal + +template +static inline internal::UnretainedWrapper Unretained(T* o) { + return internal::UnretainedWrapper(o); +} + +template +static inline internal::ConstRefWrapper ConstRef(const T& o) { + return internal::ConstRefWrapper(o); +} + +template +static inline internal::OwnedWrapper Owned(T* o) { + return internal::OwnedWrapper(o); +} + +// We offer 2 syntaxes for calling Passed(). The first takes a temporary and +// is best suited for use with the return value of a function. The second +// takes a pointer to the scoper and is just syntactic sugar to avoid having +// to write Passed(scoper.Pass()). +template +static inline internal::PassedWrapper Passed(T scoper) { + return internal::PassedWrapper(scoper.Pass()); +} +template +static inline internal::PassedWrapper Passed(T* scoper) { + return internal::PassedWrapper(scoper->Pass()); +} + +template +static inline internal::IgnoreResultHelper IgnoreResult(T data) { + return internal::IgnoreResultHelper(data); +} + +template +static inline internal::IgnoreResultHelper > +IgnoreResult(const Callback& data) { + return internal::IgnoreResultHelper >(data); +} + +void DoNothing(); + +template +void DeletePointer(T* obj) { + delete obj; +} + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ diff --git a/include/base/cef_build.h b/include/base/cef_build.h new file mode 100644 index 000000000..bf35d6a66 --- /dev/null +++ b/include/base/cef_build.h @@ -0,0 +1,172 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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_BUILD_H_ +#define CEF_INCLUDE_BASE_CEF_BUILD_H_ +#pragma once + +#if defined(BUILDING_CEF_SHARED) +// When building CEF include the Chromium header directly. +#include "base/compiler_specific.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. + +#if defined(_WIN32) +#ifndef OS_WIN +#define OS_WIN 1 +#endif +#elif defined(__APPLE__) +#ifndef OS_MACOSX +#define OS_MACOSX 1 +#endif +#elif defined(__linux__) +#ifndef OS_LINUX +#define OS_LINUX 1 +#endif +#else +#error Please add support for your platform in cef_build.h +#endif + +// For access to standard POSIXish features, use OS_POSIX instead of a +// more specific macro. +#if defined(OS_MACOSX) || defined(OS_LINUX) +#ifndef OS_POSIX +#define OS_POSIX 1 +#endif +#endif + +// Compiler detection. +#if defined(__GNUC__) +#ifndef COMPILER_GCC +#define COMPILER_GCC 1 +#endif +#elif defined(_MSC_VER) +#ifndef COMPILER_MSVC +#define COMPILER_MSVC 1 +#endif +#else +#error Please add support for your compiler in cef_build.h +#endif + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86_64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(_M_IX86) || defined(__i386__) +#define ARCH_CPU_X86_FAMILY 1 +#define ARCH_CPU_X86 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__ARMEL__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARMEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__aarch64__) +#define ARCH_CPU_ARM_FAMILY 1 +#define ARCH_CPU_ARM64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__pnacl__) +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__MIPSEL__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPSEL 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#else +#error Please add support for your architecture in cef_build.h +#endif + +// Type detection for wchar_t. +#if defined(OS_WIN) +#define WCHAR_T_IS_UTF16 +#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ + defined(__WCHAR_MAX__) && \ + (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) +#define WCHAR_T_IS_UTF32 +#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ + defined(__WCHAR_MAX__) && \ + (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) +// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to +// compile in this mode (in particular, Chrome doesn't). This is intended for +// other projects using base who manage their own dependencies and make sure +// short wchar works for them. +#define WCHAR_T_IS_UTF16 +#else +#error Please add support for your compiler in cef_build.h +#endif + +// Annotate a virtual method indicating it must be overriding a virtual +// method in the parent class. +// Use like: +// virtual void foo() OVERRIDE; +#if defined(__clang__) || defined(COMPILER_MSVC) +#define OVERRIDE override +#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 +// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. +#define OVERRIDE override +#else +#define OVERRIDE +#endif + +// Annotate a function indicating the caller must examine the return value. +// Use like: +// int foo() WARN_UNUSED_RESULT; +// To explicitly ignore a result, see |ignore_result()| in . +#if defined(COMPILER_GCC) +#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define WARN_UNUSED_RESULT +#endif + +// Annotate a variable indicating it's ok if the variable is not used. +// (Typically used to silence a compiler warning when the assignment +// is important for some other reason.) +// Use like: +// int x ALLOW_UNUSED = ...; +#if defined(COMPILER_GCC) +#define ALLOW_UNUSED __attribute__((unused)) +#else +#define ALLOW_UNUSED +#endif + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_BUILD_H_ diff --git a/include/base/cef_callback.h b/include/base/cef_callback.h new file mode 100644 index 000000000..002f78fbf --- /dev/null +++ b/include/base/cef_callback.h @@ -0,0 +1,807 @@ +// 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_CALLBACK_H_ +#define CEF_INCLUDE_BASE_CEF_CALLBACK_H_ +#pragma once + +#if defined(BASE_CALLBACK_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/callback.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/internal/cef_callback_internal.h" +#include "include/base/cef_callback_forward.h" +#include "include/base/cef_template_util.h" + +// NOTE: Header files that do not require the full definition of Callback or +// Closure should #include "base/cef_callback_forward.h" instead of this file. + +// ----------------------------------------------------------------------------- +// Introduction +// ----------------------------------------------------------------------------- +// +// The templated Callback class is a generalized function object. Together +// with the Bind() function in bind.h, they provide a type-safe method for +// performing partial application of functions. +// +// Partial application (or "currying") is the process of binding a subset of +// a function's arguments to produce another function that takes fewer +// arguments. This can be used to pass around a unit of delayed execution, +// much like lexical closures are used in other languages. For example, it +// is used in Chromium code to schedule tasks on different MessageLoops. +// +// A callback with no unbound input parameters (base::Callback) +// is called a base::Closure. Note that this is NOT the same as what other +// languages refer to as a closure -- it does not retain a reference to its +// enclosing environment. +// +// MEMORY MANAGEMENT AND PASSING +// +// The Callback objects themselves should be passed by const-reference, and +// stored by copy. They internally store their state via a refcounted class +// and thus do not need to be deleted. +// +// The reason to pass via a const-reference is to avoid unnecessary +// AddRef/Release pairs to the internal state. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for basic stuff +// ----------------------------------------------------------------------------- +// +// BINDING A BARE FUNCTION +// +// int Return5() { return 5; } +// base::Callback func_cb = base::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. +// +// BINDING A CLASS METHOD +// +// The first argument to bind is the member function to call, the second is +// the object on which to call it. +// +// class Ref : public base::RefCountedThreadSafe { +// public: +// int Foo() { return 3; } +// void PrintBye() { LOG(INFO) << "bye."; } +// }; +// scoped_refptr ref = new Ref(); +// base::Callback ref_cb = base::Bind(&Ref::Foo, ref); +// LOG(INFO) << ref_cb.Run(); // Prints out 3. +// +// By default the object must support RefCounted or you will get a compiler +// error. If you're passing between threads, be sure it's +// RefCountedThreadSafe! See "Advanced binding of member functions" below if +// you don't want to use reference counting. +// +// RUNNING A CALLBACK +// +// Callbacks can be run with their "Run" method, which has the same +// signature as the template argument to the callback. +// +// void DoSomething(const base::Callback& callback) { +// callback.Run(5, "hello"); +// } +// +// Callbacks can be run more than once (they don't get deleted or marked when +// run). However, this precludes using base::Passed (see below). +// +// void DoSomething(const base::Callback& callback) { +// double myresult = callback.Run(3.14159); +// myresult += callback.Run(2.71828); +// } +// +// PASSING UNBOUND INPUT PARAMETERS +// +// Unbound parameters are specified at the time a callback is Run(). They are +// specified in the Callback template type: +// +// void MyFunc(int i, const std::string& str) {} +// base::Callback cb = base::Bind(&MyFunc); +// cb.Run(23, "hello, world"); +// +// PASSING BOUND INPUT PARAMETERS +// +// Bound parameters are specified when you create thee callback as arguments +// to Bind(). They will be passed to the function and the Run()ner of the +// callback doesn't see those values or even know that the function it's +// calling. +// +// void MyFunc(int i, const std::string& str) {} +// base::Callback cb = base::Bind(&MyFunc, 23, "hello world"); +// cb.Run(); +// +// A callback with no unbound input parameters (base::Callback) +// is called a base::Closure. So we could have also written: +// +// base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); +// +// When calling member functions, bound parameters just go after the object +// pointer. +// +// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); +// +// PARTIAL BINDING OF PARAMETERS +// +// You can specify some parameters when you create the callback, and specify +// the rest when you execute the callback. +// +// void MyFunc(int i, const std::string& str) {} +// base::Callback cb = base::Bind(&MyFunc, 23); +// cb.Run("hello world"); +// +// When calling a function bound parameters are first, followed by unbound +// parameters. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for advanced binding +// ----------------------------------------------------------------------------- +// +// BINDING A CLASS METHOD WITH WEAK POINTERS +// +// base::Bind(&MyClass::Foo, GetWeakPtr()); +// +// The callback will not be run if the object has already been destroyed. +// DANGER: weak pointers are not threadsafe, so don't use this +// when passing between threads! +// +// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT +// +// base::Bind(&MyClass::Foo, base::Unretained(this)); +// +// This disables all lifetime management on the object. You're responsible +// for making sure the object is alive at the time of the call. You break it, +// you own it! +// +// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS +// +// MyClass* myclass = new MyClass; +// base::Bind(&MyClass::Foo, base::Owned(myclass)); +// +// The object will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). Potentially useful for +// "fire and forget" cases. +// +// IGNORING RETURN VALUES +// +// Sometimes you want to call a function that returns a value in a callback +// that doesn't expect a return value. +// +// int DoSomething(int arg) { cout << arg << endl; } +// base::Callback) cb = +// base::Bind(base::IgnoreResult(&DoSomething)); +// +// +// ----------------------------------------------------------------------------- +// Quick reference for binding parameters to Bind() +// ----------------------------------------------------------------------------- +// +// Bound parameters are specified as arguments to Bind() and are passed to the +// function. A callback with no parameters or no unbound parameters is called a +// Closure (base::Callback and base::Closure are the same thing). +// +// PASSING PARAMETERS OWNED BY THE CALLBACK +// +// void Foo(int* arg) { cout << *arg << endl; } +// int* pn = new int(1); +// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); +// +// The parameter will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). +// +// PASSING PARAMETERS AS A scoped_ptr +// +// void TakesOwnership(scoped_ptr arg) {} +// scoped_ptr f(new Foo); +// // f becomes null during the following call. +// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); +// +// Ownership of the parameter will be with the callback until the it is run, +// when ownership is passed to the callback function. This means the callback +// can only be run once. If the callback is never run, it will delete the +// object when it's destroyed. +// +// PASSING PARAMETERS AS A scoped_refptr +// +// void TakesOneRef(scoped_refptr arg) {} +// scoped_refptr f(new Foo) +// base::Closure cb = base::Bind(&TakesOneRef, f); +// +// This should "just work." The closure will take a reference as long as it +// is alive, and another reference will be taken for the called function. +// +// PASSING PARAMETERS BY REFERENCE +// +// Const references are *copied* unless ConstRef is used. Example: +// +// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } +// int n = 1; +// base::Closure has_copy = base::Bind(&foo, n); +// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); +// n = 2; +// foo(n); // Prints "2 0xaaaaaaaaaaaa" +// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" +// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" +// +// Normally parameters are copied in the closure. DANGER: ConstRef stores a +// const reference instead, referencing the original parameter. This means +// that you must ensure the object outlives the callback! +// +// +// ----------------------------------------------------------------------------- +// Implementation notes +// ----------------------------------------------------------------------------- +// +// WHERE IS THIS DESIGN FROM: +// +// The design Callback and Bind is heavily influenced by C++'s +// tr1::function/tr1::bind, and by the "Google Callback" system used inside +// Google. +// +// +// HOW THE IMPLEMENTATION WORKS: +// +// There are three main components to the system: +// 1) The Callback classes. +// 2) The Bind() functions. +// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). +// +// The Callback classes represent a generic function pointer. Internally, +// it stores a refcounted piece of state that represents the target function +// and all its bound parameters. Each Callback specialization has a templated +// constructor that takes an BindState<>*. In the context of the constructor, +// the static type of this BindState<> pointer uniquely identifies the +// function it is representing, all its bound parameters, and a Run() method +// that is capable of invoking the target. +// +// Callback's constructor takes the BindState<>* that has the full static type +// and erases the target function type as well as the types of the bound +// parameters. It does this by storing a pointer to the specific Run() +// function, and upcasting the state of BindState<>* to a +// BindStateBase*. This is safe as long as this BindStateBase pointer +// is only used with the stored Run() pointer. +// +// To BindState<> objects are created inside the Bind() functions. +// These functions, along with a set of internal templates, are responsible for +// +// - Unwrapping the function signature into return type, and parameters +// - Determining the number of parameters that are bound +// - Creating the BindState storing the bound parameters +// - Performing compile-time asserts to avoid error-prone behavior +// - Returning an Callback<> with an arity matching the number of unbound +// parameters and that knows the correct refcounting semantics for the +// target object if we are binding a method. +// +// The Bind functions do the above using type-inference, and template +// specializations. +// +// By default Bind() will store copies of all bound parameters, and attempt +// to refcount a target object if the function being bound is a class method. +// These copies are created even if the function takes parameters as const +// references. (Binding to non-const references is forbidden, see bind.h.) +// +// To change this behavior, we introduce a set of argument wrappers +// (e.g., Unretained(), and ConstRef()). These are simple container templates +// that are passed by value, and wrap a pointer to argument. See the +// file-level comment in base/bind_helpers.h for more info. +// +// These types are passed to the Unwrap() functions, and the MaybeRefcount() +// functions respectively to modify the behavior of Bind(). The Unwrap() +// and MaybeRefcount() functions change behavior by doing partial +// specialization based on whether or not a parameter is a wrapper type. +// +// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. +// +// +// WHY NOT TR1 FUNCTION/BIND? +// +// Direct use of tr1::function and tr1::bind was considered, but ultimately +// rejected because of the number of copy constructors invocations involved +// in the binding of arguments during construction, and the forwarding of +// arguments during invocation. These copies will no longer be an issue in +// C++0x because C++0x will support rvalue reference allowing for the compiler +// to avoid these copies. However, waiting for C++0x is not an option. +// +// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the +// tr1::bind call itself will invoke a non-trivial copy constructor three times +// for each bound parameter. Also, each when passing a tr1::function, each +// bound argument will be copied again. +// +// In addition to the copies taken at binding and invocation, copying a +// tr1::function causes a copy to be made of all the bound parameters and +// state. +// +// Furthermore, in Chromium, it is desirable for the Callback to take a +// reference on a target object when representing a class method call. This +// is not supported by tr1. +// +// Lastly, tr1::function and tr1::bind has a more general and flexible API. +// This includes things like argument reordering by use of +// tr1::bind::placeholder, support for non-const reference parameters, and some +// limited amount of subtyping of the tr1::function object (e.g., +// tr1::function is convertible to tr1::function). +// +// These are not features that are required in Chromium. Some of them, such as +// allowing for reference parameters, and subtyping of functions, may actually +// become a source of errors. Removing support for these features actually +// allows for a simpler implementation, and a terser Currying API. +// +// +// WHY NOT GOOGLE CALLBACKS? +// +// The Google callback system also does not support refcounting. Furthermore, +// its implementation has a number of strange edge cases with respect to type +// conversion of its arguments. In particular, the argument's constness must +// at times match exactly the function signature, or the type-inference might +// break. Given the above, writing a custom solution was easier. +// +// +// MISSING FUNCTIONALITY +// - Invoking the return of Bind. Bind(&foo).Run() does not work; +// - Binding arrays to functions that take a non-const pointer. +// Example: +// void Foo(const char* ptr); +// void Bar(char* ptr); +// Bind(&Foo, "test"); +// Bind(&Bar, "test"); // This fails because ptr is not const. + +namespace base { + +// First, we forward declare the Callback class template. This informs the +// compiler that the template only has 1 type parameter which is the function +// signature that the Callback is representing. +// +// After this, create template specializations for 0-7 parameters. Note that +// even though the template typelist grows, the specialization still +// only has one type: the function signature. +// +// If you are thinking of forward declaring Callback in your own header file, +// please include "base/callback_forward.h" instead. +template +class Callback; + +namespace internal { +template +struct BindState; +} // namespace internal + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run() const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get()); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5, A6); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + +template +class Callback : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template + Callback(internal::BindState* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6, + typename internal::CallbackParamTraits::ForwardType a7) const { + PolymorphicInvoke f = + reinterpret_cast(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6), + internal::CallbackForward(a7)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType, + typename internal::CallbackParamTraits::ForwardType); + +}; + + +// Syntactic sugar to make Callbacks easier to declare since it +// will be used in a lot of APIs with delayed execution. +typedef Callback Closure; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_H_ diff --git a/include/base/cef_callback_forward.h b/include/base/cef_callback_forward.h new file mode 100644 index 000000000..4986b8f76 --- /dev/null +++ b/include/base/cef_callback_forward.h @@ -0,0 +1,59 @@ +// 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. + +#ifndef INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ +#define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ +#pragma once + +#if defined(BASE_CALLBACK_FORWARD_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/callback_forward.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. + +namespace base { + +template +class Callback; + +typedef Callback Closure; + +} // namespace base + +#endif // !!BUILDING_CEF_SHARED + +#endif // INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ diff --git a/include/base/cef_callback_helpers.h b/include/base/cef_callback_helpers.h new file mode 100644 index 000000000..62a0c8752 --- /dev/null +++ b/include/base/cef_callback_helpers.h @@ -0,0 +1,93 @@ +// 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. + +// This defines helpful methods for dealing with Callbacks. Because Callbacks +// are implemented using templates, with a class per callback signature, adding +// methods to Callback<> itself is unattractive (lots of extra code gets +// generated). Instead, consider adding methods here. +// +// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a +// copy) after the original callback is Reset(). This can be handy if Run() +// reads/writes the variable holding the Callback. + +#ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ +#define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ +#pragma once + +#if defined(BASE_CALLBACK_HELPERS_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/callback_helpers.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_basictypes.h" +#include "include/base/cef_build.h" +#include "include/base/cef_callback.h" +#include "include/base/cef_macros.h" + +namespace base { + +template +base::Callback ResetAndReturn(base::Callback* cb) { + base::Callback ret(*cb); + cb->Reset(); + return ret; +} + +// ScopedClosureRunner is akin to scoped_ptr for Closures. It ensures that the +// Closure is executed and deleted no matter how the current scope exits. +class ScopedClosureRunner { + public: + ScopedClosureRunner(); + explicit ScopedClosureRunner(const Closure& closure); + ~ScopedClosureRunner(); + + void Reset(); + void Reset(const Closure& closure); + Closure Release() WARN_UNUSED_RESULT; + + private: + Closure closure_; + + DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner); +}; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ diff --git a/include/base/cef_callback_list.h b/include/base/cef_callback_list.h new file mode 100644 index 000000000..e198fd390 --- /dev/null +++ b/include/base/cef_callback_list.h @@ -0,0 +1,444 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013 +// 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_CALLBACK_LIST_H_ +#define CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_ +#pragma once + +#if defined(BASE_CALLBACK_LIST_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/callback_list.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 "include/base/cef_basictypes.h" +#include "include/base/cef_callback.h" +#include "include/base/internal/cef_callback_internal.h" +#include "include/base/cef_build.h" +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/base/cef_scoped_ptr.h" + +// OVERVIEW: +// +// A container for a list of callbacks. Unlike a normal STL vector or list, +// this container can be modified during iteration without invalidating the +// iterator. It safely handles the case of a callback removing itself +// or another callback from the list while callbacks are being run. +// +// TYPICAL USAGE: +// +// class MyWidget { +// public: +// ... +// +// typedef base::Callback OnFooCallback; +// +// scoped_ptr::Subscription> +// RegisterCallback(const OnFooCallback& cb) { +// return callback_list_.Add(cb); +// } +// +// private: +// void NotifyFoo(const Foo& foo) { +// callback_list_.Notify(foo); +// } +// +// base::CallbackList callback_list_; +// +// DISALLOW_COPY_AND_ASSIGN(MyWidget); +// }; +// +// +// class MyWidgetListener { +// public: +// MyWidgetListener::MyWidgetListener() { +// foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback( +// base::Bind(&MyWidgetListener::OnFoo, this))); +// } +// +// MyWidgetListener::~MyWidgetListener() { +// // Subscription gets deleted automatically and will deregister +// // the callback in the process. +// } +// +// private: +// void OnFoo(const Foo& foo) { +// // Do something. +// } +// +// scoped_ptr::Subscription> +// foo_subscription_; +// +// DISALLOW_COPY_AND_ASSIGN(MyWidgetListener); +// }; + +namespace base { + +namespace internal { + +template +class CallbackListBase { + public: + class Subscription { + public: + Subscription(CallbackListBase* list, + typename std::list::iterator iter) + : list_(list), + iter_(iter) { + } + + ~Subscription() { + if (list_->active_iterator_count_) { + iter_->Reset(); + } else { + list_->callbacks_.erase(iter_); + if (!list_->removal_callback_.is_null()) + list_->removal_callback_.Run(); + } + } + + private: + CallbackListBase* list_; + typename std::list::iterator iter_; + + DISALLOW_COPY_AND_ASSIGN(Subscription); + }; + + // Add a callback to the list. The callback will remain registered until the + // returned Subscription is destroyed, which must occur before the + // CallbackList is destroyed. + scoped_ptr Add(const CallbackType& cb) WARN_UNUSED_RESULT { + DCHECK(!cb.is_null()); + return scoped_ptr( + new Subscription(this, callbacks_.insert(callbacks_.end(), cb))); + } + + // Sets a callback which will be run when a subscription list is changed. + void set_removal_callback(const Closure& callback) { + removal_callback_ = callback; + } + + // Returns true if there are no subscriptions. This is only valid to call when + // not looping through the list. + bool empty() { + DCHECK_EQ(0, active_iterator_count_); + return callbacks_.empty(); + } + + protected: + // An iterator class that can be used to access the list of callbacks. + class Iterator { + public: + explicit Iterator(CallbackListBase* list) + : list_(list), + list_iter_(list_->callbacks_.begin()) { + ++list_->active_iterator_count_; + } + + Iterator(const Iterator& iter) + : list_(iter.list_), + list_iter_(iter.list_iter_) { + ++list_->active_iterator_count_; + } + + ~Iterator() { + if (list_ && --list_->active_iterator_count_ == 0) { + list_->Compact(); + } + } + + CallbackType* GetNext() { + while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null()) + ++list_iter_; + + CallbackType* cb = NULL; + if (list_iter_ != list_->callbacks_.end()) { + cb = &(*list_iter_); + ++list_iter_; + } + return cb; + } + + private: + CallbackListBase* list_; + typename std::list::iterator list_iter_; + }; + + CallbackListBase() : active_iterator_count_(0) {} + + ~CallbackListBase() { + DCHECK_EQ(0, active_iterator_count_); + DCHECK_EQ(0U, callbacks_.size()); + } + + // Returns an instance of a CallbackListBase::Iterator which can be used + // to run callbacks. + Iterator GetIterator() { + return Iterator(this); + } + + // Compact the list: remove any entries which were NULLed out during + // iteration. + void Compact() { + typename std::list::iterator it = callbacks_.begin(); + bool updated = false; + while (it != callbacks_.end()) { + if ((*it).is_null()) { + updated = true; + it = callbacks_.erase(it); + } else { + ++it; + } + + if (updated && !removal_callback_.is_null()) + removal_callback_.Run(); + } + } + + private: + std::list callbacks_; + int active_iterator_count_; + Closure removal_callback_; + + DISALLOW_COPY_AND_ASSIGN(CallbackListBase); +}; + +} // namespace internal + +template class CallbackList; + +template <> +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify() { + internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5, a6); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +template +class CallbackList + : public internal::CallbackListBase > { + public: + typedef Callback CallbackType; + + CallbackList() {} + + void Notify(typename internal::CallbackParamTraits::ForwardType a1, + typename internal::CallbackParamTraits::ForwardType a2, + typename internal::CallbackParamTraits::ForwardType a3, + typename internal::CallbackParamTraits::ForwardType a4, + typename internal::CallbackParamTraits::ForwardType a5, + typename internal::CallbackParamTraits::ForwardType a6, + typename internal::CallbackParamTraits::ForwardType a7) { + typename internal::CallbackListBase::Iterator it = + this->GetIterator(); + CallbackType* cb; + while ((cb = it.GetNext()) != NULL) { + cb->Run(a1, a2, a3, a4, a5, a6, a7); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(CallbackList); +}; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CALLBACK_LIST_H_ diff --git a/include/base/cef_cancelable_callback.h b/include/base/cef_cancelable_callback.h new file mode 100644 index 000000000..8ad3bf3bb --- /dev/null +++ b/include/base/cef_cancelable_callback.h @@ -0,0 +1,314 @@ +// 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. +// +// CancelableCallback is a wrapper around base::Callback that allows +// cancellation of a callback. CancelableCallback takes a reference on the +// wrapped callback until this object is destroyed or Reset()/Cancel() are +// called. +// +// NOTE: +// +// Calling CancelableCallback::Cancel() brings the object back to its natural, +// default-constructed state, i.e., CancelableCallback::callback() will return +// a null callback. +// +// THREAD-SAFETY: +// +// CancelableCallback objects must be created on, posted to, cancelled on, and +// destroyed on the same thread. +// +// +// EXAMPLE USAGE: +// +// In the following example, the test is verifying that RunIntensiveTest() +// Quit()s the message loop within 4 seconds. The cancelable callback is posted +// to the message loop, the intensive test runs, the message loop is run, +// then the callback is cancelled. +// +// void TimeoutCallback(const std::string& timeout_message) { +// FAIL() << timeout_message; +// MessageLoop::current()->QuitWhenIdle(); +// } +// +// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out.")); +// MessageLoop::current()->PostDelayedTask(FROM_HERE, timeout.callback(), +// 4000) // 4 seconds to run. +// RunIntensiveTest(); +// MessageLoop::current()->Run(); +// timeout.Cancel(); // Hopefully this is hit before the timeout callback runs. +// + +#ifndef CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ +#define CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ +#pragma once + +#if defined(BASE_CANCELABLE_CALLBACK_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/cancelable_callback.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_bind.h" +#include "include/base/cef_callback.h" +#include "include/base/cef_build.h" +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/base/cef_weak_ptr.h" +#include "include/base/internal/cef_callback_internal.h" + +namespace base { + +template +class CancelableCallback; + +template <> +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& callback) + : weak_factory_(this), + callback_(callback) { + DCHECK(!callback.is_null()); + InitializeForwarder(); + } + + ~CancelableCallback() {} + + // Cancels and drops the reference to the wrapped callback. + void Cancel() { + weak_factory_.InvalidateWeakPtrs(); + forwarder_.Reset(); + callback_.Reset(); + } + + // Returns true if the wrapped callback has been cancelled. + bool IsCancelled() const { + return callback_.is_null(); + } + + // Sets |callback| as the closure that may be cancelled. |callback| may not + // be null. Outstanding and any previously wrapped callbacks are cancelled. + void Reset(const base::Callback& callback) { + DCHECK(!callback.is_null()); + + // Outstanding tasks (e.g., posted to a message loop) must not be called. + Cancel(); + + // |forwarder_| is no longer valid after Cancel(), so re-bind. + InitializeForwarder(); + + callback_ = callback; + } + + // Returns a callback that can be disabled by calling Cancel(). + const base::Callback& callback() const { + return forwarder_; + } + + private: + void Forward() { + callback_.Run(); + } + + // Helper method to bind |forwarder_| using a weak pointer from + // |weak_factory_|. + void InitializeForwarder() { + forwarder_ = base::Bind(&CancelableCallback::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +template +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& callback) + : weak_factory_(this), + callback_(callback) { + DCHECK(!callback.is_null()); + InitializeForwarder(); + } + + ~CancelableCallback() {} + + // Cancels and drops the reference to the wrapped callback. + void Cancel() { + weak_factory_.InvalidateWeakPtrs(); + forwarder_.Reset(); + callback_.Reset(); + } + + // Returns true if the wrapped callback has been cancelled. + bool IsCancelled() const { + return callback_.is_null(); + } + + // Sets |callback| as the closure that may be cancelled. |callback| may not + // be null. Outstanding and any previously wrapped callbacks are cancelled. + void Reset(const base::Callback& callback) { + DCHECK(!callback.is_null()); + + // Outstanding tasks (e.g., posted to a message loop) must not be called. + Cancel(); + + // |forwarder_| is no longer valid after Cancel(), so re-bind. + InitializeForwarder(); + + callback_ = callback; + } + + // Returns a callback that can be disabled by calling Cancel(). + const base::Callback& callback() const { + return forwarder_; + } + + private: + void Forward(A1 a1) const { + callback_.Run(a1); + } + + // Helper method to bind |forwarder_| using a weak pointer from + // |weak_factory_|. + void InitializeForwarder() { + forwarder_ = base::Bind(&CancelableCallback::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +template +class CancelableCallback { + public: + CancelableCallback() : weak_factory_(this) {} + + // |callback| must not be null. + explicit CancelableCallback(const base::Callback& callback) + : weak_factory_(this), + callback_(callback) { + DCHECK(!callback.is_null()); + InitializeForwarder(); + } + + ~CancelableCallback() {} + + // Cancels and drops the reference to the wrapped callback. + void Cancel() { + weak_factory_.InvalidateWeakPtrs(); + forwarder_.Reset(); + callback_.Reset(); + } + + // Returns true if the wrapped callback has been cancelled. + bool IsCancelled() const { + return callback_.is_null(); + } + + // Sets |callback| as the closure that may be cancelled. |callback| may not + // be null. Outstanding and any previously wrapped callbacks are cancelled. + void Reset(const base::Callback& callback) { + DCHECK(!callback.is_null()); + + // Outstanding tasks (e.g., posted to a message loop) must not be called. + Cancel(); + + // |forwarder_| is no longer valid after Cancel(), so re-bind. + InitializeForwarder(); + + callback_ = callback; + } + + // Returns a callback that can be disabled by calling Cancel(). + const base::Callback& callback() const { + return forwarder_; + } + + private: + void Forward(A1 a1, A2 a2) const { + callback_.Run(a1, a2); + } + + // Helper method to bind |forwarder_| using a weak pointer from + // |weak_factory_|. + void InitializeForwarder() { + forwarder_ = base::Bind(&CancelableCallback::Forward, + weak_factory_.GetWeakPtr()); + } + + // Used to ensure Forward() is not run when this object is destroyed. + base::WeakPtrFactory > weak_factory_; + + // The wrapper closure. + base::Callback forwarder_; + + // The stored closure that may be cancelled. + base::Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); +}; + +typedef CancelableCallback CancelableClosure; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_CANCELABLE_CALLBACK_H_ diff --git a/include/base/cef_lock.h b/include/base/cef_lock.h new file mode 100644 index 000000000..d50d60ba8 --- /dev/null +++ b/include/base/cef_lock.h @@ -0,0 +1,167 @@ +// 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. + +#ifndef CEF_INCLUDE_BASE_CEF_LOCK_H_ +#define CEF_INCLUDE_BASE_CEF_LOCK_H_ +#pragma once + +#if defined(BASE_SYNCHRONIZATION_LOCK_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/synchronization/lock.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_macros.h" +#include "include/base/cef_platform_thread.h" +#include "include/base/internal/cef_lock_impl.h" + +namespace base { + +// A convenient wrapper for an OS specific critical section. The only real +// intelligence in this class is in debug mode for the support for the +// AssertAcquired() method. +class Lock { + public: +#if defined(NDEBUG) // Optimized wrapper implementation + Lock() : lock_() {} + ~Lock() {} + void Acquire() { lock_.Lock(); } + void Release() { lock_.Unlock(); } + + // If the lock is not held, take it and return true. If the lock is already + // held by another thread, immediately return false. This must not be called + // by a thread already holding the lock (what happens is undefined and an + // assertion may fail). + bool Try() { return lock_.Try(); } + + // Null implementation if not debug. + void AssertAcquired() const {} +#else + Lock(); + ~Lock(); + + // NOTE: Although windows critical sections support recursive locks, we do not + // allow this, and we will commonly fire a DCHECK() if a thread attempts to + // acquire the lock a second time (while already holding it). + void Acquire() { + lock_.Lock(); + CheckUnheldAndMark(); + } + void Release() { + CheckHeldAndUnmark(); + lock_.Unlock(); + } + + bool Try() { + bool rv = lock_.Try(); + if (rv) { + CheckUnheldAndMark(); + } + return rv; + } + + void AssertAcquired() const; +#endif // NDEBUG + + private: +#if !defined(NDEBUG) + // Members and routines taking care of locks assertions. + // Note that this checks for recursive locks and allows them + // if the variable is set. This is allowed by the underlying implementation + // on windows but not on Posix, so we're doing unneeded checks on Posix. + // It's worth it to share the code. + void CheckHeldAndUnmark(); + void CheckUnheldAndMark(); + + // All private data is implicitly protected by lock_. + // Be VERY careful to only access members under that lock. + base::PlatformThreadRef owning_thread_ref_; +#endif // NDEBUG + + // Platform specific underlying lock implementation. + internal::LockImpl lock_; + + DISALLOW_COPY_AND_ASSIGN(Lock); +}; + +// A helper class that acquires the given Lock while the AutoLock is in scope. +class AutoLock { + public: + struct AlreadyAcquired {}; + + explicit AutoLock(Lock& lock) : lock_(lock) { + lock_.Acquire(); + } + + AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) { + lock_.AssertAcquired(); + } + + ~AutoLock() { + lock_.AssertAcquired(); + lock_.Release(); + } + + private: + Lock& lock_; + DISALLOW_COPY_AND_ASSIGN(AutoLock); +}; + +// AutoUnlock is a helper that will Release() the |lock| argument in the +// constructor, and re-Acquire() it in the destructor. +class AutoUnlock { + public: + explicit AutoUnlock(Lock& lock) : lock_(lock) { + // We require our caller to have the lock. + lock_.AssertAcquired(); + lock_.Release(); + } + + ~AutoUnlock() { + lock_.Acquire(); + } + + private: + Lock& lock_; + DISALLOW_COPY_AND_ASSIGN(AutoUnlock); +}; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_LOCK_H_ diff --git a/include/base/cef_logging.h b/include/base/cef_logging.h new file mode 100644 index 000000000..b3951f12e --- /dev/null +++ b/include/base/cef_logging.h @@ -0,0 +1,746 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// +// WARNING: Logging macros should not be used in the main/browser process before +// calling CefInitialize or in sub-processes before calling CefExecuteProcess. +// +// Instructions +// ------------ +// +// Make a bunch of macros for logging. The way to log things is to stream +// things to LOG(). E.g., +// +// LOG(INFO) << "Found " << num_cookies << " cookies"; +// +// You can also do conditional logging: +// +// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; +// +// The CHECK(condition) macro is active in both debug and release builds and +// effectively performs a LOG(FATAL) which terminates the process and +// generates a crashdump unless a debugger is attached. +// +// There are also "debug mode" logging macros like the ones above: +// +// DLOG(INFO) << "Found cookies"; +// +// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; +// +// All "debug mode" logging is compiled away to nothing for non-debug mode +// compiles. LOG_IF and development flags also work well together +// because the code can be compiled away sometimes. +// +// We also have +// +// LOG_ASSERT(assertion); +// DLOG_ASSERT(assertion); +// +// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion; +// +// There are "verbose level" logging macros. They look like +// +// VLOG(1) << "I'm printed when you run the program with --v=1 or more"; +// VLOG(2) << "I'm printed when you run the program with --v=2 or more"; +// +// These always log at the INFO log level (when they log at all). +// The verbose logging can also be turned on module-by-module. For instance, +// --vmodule=profile=2,icon_loader=1,browser_*=3,*/chromeos/*=4 --v=0 +// will cause: +// a. VLOG(2) and lower messages to be printed from profile.{h,cc} +// b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc} +// c. VLOG(3) and lower messages to be printed from files prefixed with +// "browser" +// d. VLOG(4) and lower messages to be printed from files under a +// "chromeos" directory. +// e. VLOG(0) and lower messages to be printed from elsewhere +// +// The wildcarding functionality shown by (c) supports both '*' (match +// 0 or more characters) and '?' (match any single character) +// wildcards. Any pattern containing a forward or backward slash will +// be tested against the whole pathname and not just the module. +// E.g., "*/foo/bar/*=2" would change the logging level for all code +// in source files under a "foo/bar" directory. +// +// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as +// +// if (VLOG_IS_ON(2)) { +// // do some logging preparation and logging +// // that can't be accomplished with just VLOG(2) << ...; +// } +// +// There is also a VLOG_IF "verbose level" condition macro for sample +// cases, when some extra computation and preparation for logs is not +// needed. +// +// VLOG_IF(1, (size > 1024)) +// << "I'm printed when size is more than 1024 and when you run the " +// "program with --v=1 or more"; +// +// We also override the standard 'assert' to use 'DLOG_ASSERT'. +// +// Lastly, there is: +// +// PLOG(ERROR) << "Couldn't do foo"; +// DPLOG(ERROR) << "Couldn't do foo"; +// PLOG_IF(ERROR, cond) << "Couldn't do foo"; +// DPLOG_IF(ERROR, cond) << "Couldn't do foo"; +// PCHECK(condition) << "Couldn't do foo"; +// DPCHECK(condition) << "Couldn't do foo"; +// +// which append the last system error to the message in string form (taken from +// GetLastError() on Windows and errno on POSIX). +// +// The supported severity levels for macros that allow you to specify one +// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. +// +// Very important: logging a message at the FATAL severity level causes +// the program to terminate (after the message is logged). +// +// There is the special severity of DFATAL, which logs FATAL in debug mode, +// ERROR in normal mode. +// + +#ifndef CEF_INCLUDE_BASE_CEF_LOGGING_H_ +#define CEF_INCLUDE_BASE_CEF_LOGGING_H_ +#pragma once + +#if defined(DCHECK) +// Do nothing if the macros provided by this header already exist. +// 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/logging.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 +#include +#include + +#include "include/base/cef_build.h" +#include "include/base/cef_macros.h" +#include "include/internal/cef_logging_internal.h" + +namespace cef { +namespace logging { + +// Gets the current log level. +inline int GetMinLogLevel() { + return cef_get_min_log_level(); +} + +// Gets the current vlog level for the given file (usually taken from +// __FILE__). Note that |N| is the size *with* the null terminator. +template +int GetVlogLevel(const char (&file)[N]) { + return cef_get_vlog_level(file, N); +} + +typedef int LogSeverity; +const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity +// Note: the log severities are used to index into the array of names, +// see log_severity_names. +const LogSeverity LOG_INFO = 0; +const LogSeverity LOG_WARNING = 1; +const LogSeverity LOG_ERROR = 2; +const LogSeverity LOG_FATAL = 3; +const LogSeverity LOG_NUM_SEVERITIES = 4; + +// LOG_DFATAL is LOG_FATAL in debug mode, ERROR in normal mode +#ifdef NDEBUG +const LogSeverity LOG_DFATAL = LOG_ERROR; +#else +const LogSeverity LOG_DFATAL = LOG_FATAL; +#endif + +// A few definitions of macros that don't generate much code. These are used +// by LOG() and LOG_IF, etc. Since these are used all over our code, it's +// better to have compact code for these operations. +#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \ + cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_INFO , \ + ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ + cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_WARNING , \ + ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \ + cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_ERROR , \ + ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \ + cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_FATAL , \ + ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \ + cef::logging::ClassName(__FILE__, __LINE__, cef::logging::LOG_DFATAL , \ + ##__VA_ARGS__) + +#define COMPACT_GOOGLE_LOG_INFO \ + COMPACT_GOOGLE_LOG_EX_INFO(LogMessage) +#define COMPACT_GOOGLE_LOG_WARNING \ + COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage) +#define COMPACT_GOOGLE_LOG_ERROR \ + COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage) +#define COMPACT_GOOGLE_LOG_FATAL \ + COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage) +#define COMPACT_GOOGLE_LOG_DFATAL \ + COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage) + +#if defined(OS_WIN) +// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets +// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us +// to keep using this syntax, we define this macro to do the same thing +// as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that +// the Windows SDK does for consistency. +#define ERROR 0 +#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \ + COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR +// Needed for LOG_IS_ON(ERROR). +const LogSeverity LOG_0 = LOG_ERROR; +#endif + +// As special cases, we can assume that LOG_IS_ON(FATAL) always holds. Also, +// LOG_IS_ON(DFATAL) always holds in debug mode. In particular, CHECK()s will +// always fire if they fail. +#define LOG_IS_ON(severity) \ + ((::cef::logging::LOG_ ## severity) >= ::cef::logging::GetMinLogLevel()) + +// We can't do any caching tricks with VLOG_IS_ON() like the +// google-glog version since it requires GCC extensions. This means +// that using the v-logging functions in conjunction with --vmodule +// may be slow. +#define VLOG_IS_ON(verboselevel) \ + ((verboselevel) <= ::cef::logging::GetVlogLevel(__FILE__)) + +// Helper macro which avoids evaluating the arguments to a stream if +// the condition doesn't hold. +#define LAZY_STREAM(stream, condition) \ + !(condition) ? (void) 0 : ::cef::logging::LogMessageVoidify() & (stream) + +// We use the preprocessor's merging operator, "##", so that, e.g., +// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny +// subtle difference between ostream member streaming functions (e.g., +// ostream::operator<<(int) and ostream non-member streaming functions +// (e.g., ::operator<<(ostream&, string&): it turns out that it's +// impossible to stream something like a string directly to an unnamed +// ostream. We employ a neat hack by calling the stream() member +// function of LogMessage which seems to avoid the problem. +#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream() + +#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity)) +#define LOG_IF(severity, condition) \ + LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) + +#define SYSLOG(severity) LOG(severity) +#define SYSLOG_IF(severity, condition) LOG_IF(severity, condition) + +// The VLOG macros log with negative verbosities. +#define VLOG_STREAM(verbose_level) \ + cef::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream() + +#define VLOG(verbose_level) \ + LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) + +#define VLOG_IF(verbose_level, condition) \ + LAZY_STREAM(VLOG_STREAM(verbose_level), \ + VLOG_IS_ON(verbose_level) && (condition)) + +#if defined (OS_WIN) +#define VPLOG_STREAM(verbose_level) \ + cef::logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \ + ::cef::logging::GetLastSystemErrorCode()).stream() +#elif defined(OS_POSIX) +#define VPLOG_STREAM(verbose_level) \ + cef::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \ + ::cef::logging::GetLastSystemErrorCode()).stream() +#endif + +#define VPLOG(verbose_level) \ + LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) + +#define VPLOG_IF(verbose_level, condition) \ + LAZY_STREAM(VPLOG_STREAM(verbose_level), \ + VLOG_IS_ON(verbose_level) && (condition)) + +// TODO(akalin): Add more VLOG variants, e.g. VPLOG. + +#define LOG_ASSERT(condition) \ + LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " +#define SYSLOG_ASSERT(condition) \ + SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " + +#if defined(OS_WIN) +#define PLOG_STREAM(severity) \ + COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \ + ::cef::logging::GetLastSystemErrorCode()).stream() +#elif defined(OS_POSIX) +#define PLOG_STREAM(severity) \ + COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \ + ::cef::logging::GetLastSystemErrorCode()).stream() +#endif + +#define PLOG(severity) \ + LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity)) + +#define PLOG_IF(severity, condition) \ + LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) + +// The actual stream used isn't important. +#define EAT_STREAM_PARAMETERS \ + true ? (void) 0 : ::cef::logging::LogMessageVoidify() & LOG_STREAM(FATAL) + +// CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG, so the check will be executed regardless of +// compilation mode. +// +// We make sure CHECK et al. always evaluates their arguments, as +// doing CHECK(FunctionWithSideEffect()) is a common idiom. + +#define CHECK(condition) \ + LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \ + << "Check failed: " #condition ". " + +#define PCHECK(condition) \ + LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \ + << "Check failed: " #condition ". " + +// Helper macro for binary operators. +// Don't use this macro directly in your code, use CHECK_EQ et al below. +// +// TODO(akalin): Rewrite this so that constructs like if (...) +// CHECK_EQ(...) else { ... } work properly. +#define CHECK_OP(name, op, val1, val2) \ + if (std::string* _result = \ + cef::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ + cef::logging::LogMessage(__FILE__, __LINE__, _result).stream() + +// Build the error message string. This is separate from the "Impl" +// function template because it is not performance critical and so can +// be out of line, while the "Impl" code should be inline. Caller +// takes ownership of the returned string. +template +std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { + std::ostringstream ss; + ss << names << " (" << v1 << " vs. " << v2 << ")"; + std::string* msg = new std::string(ss.str()); + return msg; +} + +// MSVC doesn't like complex extern templates and DLLs. +#if !defined(COMPILER_MSVC) +// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated +// in logging.cc. +extern template std::string* MakeCheckOpString( + const int&, const int&, const char* names); +extern template +std::string* MakeCheckOpString( + const unsigned long&, const unsigned long&, const char* names); +extern template +std::string* MakeCheckOpString( + const unsigned long&, const unsigned int&, const char* names); +extern template +std::string* MakeCheckOpString( + const unsigned int&, const unsigned long&, const char* names); +extern template +std::string* MakeCheckOpString( + const std::string&, const std::string&, const char* name); +#endif + +// Helper functions for CHECK_OP macro. +// The (int, int) specialization works around the issue that the compiler +// will not instantiate the template version of the function on values of +// unnamed enum type - see comment below. +#define DEFINE_CHECK_OP_IMPL(name, op) \ + template \ + inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ + const char* names) { \ + if (v1 op v2) return NULL; \ + else return MakeCheckOpString(v1, v2, names); \ + } \ + inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ + if (v1 op v2) return NULL; \ + else return MakeCheckOpString(v1, v2, names); \ + } +DEFINE_CHECK_OP_IMPL(EQ, ==) +DEFINE_CHECK_OP_IMPL(NE, !=) +DEFINE_CHECK_OP_IMPL(LE, <=) +DEFINE_CHECK_OP_IMPL(LT, < ) +DEFINE_CHECK_OP_IMPL(GE, >=) +DEFINE_CHECK_OP_IMPL(GT, > ) +#undef DEFINE_CHECK_OP_IMPL + +#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2) +#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2) +#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2) +#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2) +#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) +#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) + +#if defined(NDEBUG) +#define ENABLE_DLOG 0 +#else +#define ENABLE_DLOG 1 +#endif + +#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) +#define DCHECK_IS_ON 0 +#else +#define DCHECK_IS_ON 1 +#endif + +// Definitions for DLOG et al. + +#if ENABLE_DLOG + +#define DLOG_IS_ON(severity) LOG_IS_ON(severity) +#define DLOG_IF(severity, condition) LOG_IF(severity, condition) +#define DLOG_ASSERT(condition) LOG_ASSERT(condition) +#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition) +#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition) +#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition) + +#else // ENABLE_DLOG + +// If ENABLE_DLOG is off, we want to avoid emitting any references to +// |condition| (which may reference a variable defined only if NDEBUG +// is not defined). Contrast this with DCHECK et al., which has +// different behavior. + +#define DLOG_IS_ON(severity) false +#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS +#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS +#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS +#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS +#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS + +#endif // ENABLE_DLOG + +// DEBUG_MODE is for uses like +// if (DEBUG_MODE) foo.CheckThatFoo(); +// instead of +// #ifndef NDEBUG +// foo.CheckThatFoo(); +// #endif +// +// We tie its state to ENABLE_DLOG. +enum { DEBUG_MODE = ENABLE_DLOG }; + +#undef ENABLE_DLOG + +#define DLOG(severity) \ + LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) + +#define DPLOG(severity) \ + LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity)) + +#define DVLOG(verboselevel) DVLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) + +#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel)) + +// Definitions for DCHECK et al. + +#if DCHECK_IS_ON + +#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ + COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL +const LogSeverity LOG_DCHECK = LOG_FATAL; + +#else // DCHECK_IS_ON + +// These are just dummy values. +#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \ + COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO +const LogSeverity LOG_DCHECK = LOG_INFO; + +#endif // DCHECK_IS_ON + +// DCHECK et al. make sure to reference |condition| regardless of +// whether DCHECKs are enabled; this is so that we don't get unused +// variable warnings if the only use of a variable is in a DCHECK. +// This behavior is different from DLOG_IF et al. + +#define DCHECK(condition) \ + LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ + << "Check failed: " #condition ". " + +#define DPCHECK(condition) \ + LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON && !(condition)) \ + << "Check failed: " #condition ". " + +// Helper macro for binary operators. +// Don't use this macro directly in your code, use DCHECK_EQ et al below. +#define DCHECK_OP(name, op, val1, val2) \ + if (DCHECK_IS_ON) \ + if (std::string* _result = \ + cef::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ + cef::logging::LogMessage( \ + __FILE__, __LINE__, ::cef::logging::LOG_DCHECK, \ + _result).stream() + +// Equality/Inequality checks - compare two values, and log a +// LOG_DCHECK message including the two values when the result is not +// as expected. The values must have operator<<(ostream, ...) +// defined. +// +// You may append to the error message like so: +// DCHECK_NE(1, 2) << ": The world must be ending!"; +// +// We are very careful to ensure that each argument is evaluated exactly +// once, and that anything which is legal to pass as a function argument is +// legal here. In particular, the arguments may be temporary expressions +// which will end up being destroyed at the end of the apparent statement, +// for example: +// DCHECK_EQ(string("abc")[1], 'b'); +// +// WARNING: These may not compile correctly if one of the arguments is a pointer +// and the other is NULL. To work around this, simply static_cast NULL to the +// type of the desired pointer. + +#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) +#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) +#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) +#define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) +#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) +#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) + +#if defined(NDEBUG) && defined(OS_CHROMEOS) +#define NOTREACHED() LOG(ERROR) << "NOTREACHED() hit in " << \ + __FUNCTION__ << ". " +#else +#define NOTREACHED() DCHECK(false) +#endif + +// Redefine the standard assert to use our nice log files +#undef assert +#define assert(x) DLOG_ASSERT(x) + +// This class more or less represents a particular log message. You +// create an instance of LogMessage and then stream stuff to it. +// When you finish streaming to it, ~LogMessage is called and the +// full message gets streamed to the appropriate destination. +// +// You shouldn't actually use LogMessage's constructor to log things, +// though. You should use the LOG() macro (and variants thereof) +// above. +class LogMessage { + public: + // Used for LOG(severity). + LogMessage(const char* file, int line, LogSeverity severity); + + // Used for CHECK_EQ(), etc. Takes ownership of the given string. + // Implied severity = LOG_FATAL. + LogMessage(const char* file, int line, std::string* result); + + // Used for DCHECK_EQ(), etc. Takes ownership of the given string. + LogMessage(const char* file, int line, LogSeverity severity, + std::string* result); + + ~LogMessage(); + + std::ostream& stream() { return stream_; } + + private: + LogSeverity severity_; + std::ostringstream stream_; + + // The file and line information passed in to the constructor. + const char* file_; + const int line_; + +#if defined(OS_WIN) + // Stores the current value of GetLastError in the constructor and restores + // it in the destructor by calling SetLastError. + // This is useful since the LogMessage class uses a lot of Win32 calls + // that will lose the value of GLE and the code that called the log function + // will have lost the thread error value when the log call returns. + class SaveLastError { + public: + SaveLastError(); + ~SaveLastError(); + + unsigned long get_error() const { return last_error_; } + + protected: + unsigned long last_error_; + }; + + SaveLastError last_error_; +#endif + + DISALLOW_COPY_AND_ASSIGN(LogMessage); +}; + +// A non-macro interface to the log facility; (useful +// when the logging level is not a compile-time constant). +inline void LogAtLevel(int const log_level, std::string const &msg) { + LogMessage(__FILE__, __LINE__, log_level).stream() << msg; +} + +// This class is used to explicitly ignore values in the conditional +// logging macros. This avoids compiler warnings like "value computed +// is not used" and "statement has no effect". +class LogMessageVoidify { + public: + LogMessageVoidify() { } + // This has to be an operator with a precedence lower than << but + // higher than ?: + void operator&(std::ostream&) { } +}; + +#if defined(OS_WIN) +typedef unsigned long SystemErrorCode; +#elif defined(OS_POSIX) +typedef int SystemErrorCode; +#endif + +// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to +// pull in windows.h just for GetLastError() and DWORD. +SystemErrorCode GetLastSystemErrorCode(); +std::string SystemErrorCodeToString(SystemErrorCode error_code); + +#if defined(OS_WIN) +// Appends a formatted system message of the GetLastError() type. +class Win32ErrorLogMessage { + public: + Win32ErrorLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err); + + // Appends the error message before destructing the encapsulated class. + ~Win32ErrorLogMessage(); + + std::ostream& stream() { return log_message_.stream(); } + + private: + SystemErrorCode err_; + LogMessage log_message_; + + DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); +}; +#elif defined(OS_POSIX) +// Appends a formatted system message of the errno type +class ErrnoLogMessage { + public: + ErrnoLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err); + + // Appends the error message before destructing the encapsulated class. + ~ErrnoLogMessage(); + + std::ostream& stream() { return log_message_.stream(); } + + private: + SystemErrorCode err_; + LogMessage log_message_; + + DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage); +}; +#endif // OS_WIN + +} // namespace logging +} // namespace cef + +// These functions are provided as a convenience for logging, which is where we +// use streams (it is against Google style to use streams in other places). It +// is designed to allow you to emit non-ASCII Unicode strings to the log file, +// which is normally ASCII. It is relatively slow, so try not to use it for +// common cases. Non-ASCII characters will be converted to UTF-8 by these +// operators. +std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); +inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { + return out << wstr.c_str(); +} + +// The NOTIMPLEMENTED() macro annotates codepaths which have +// not been implemented yet. +// +// The implementation of this macro is controlled by NOTIMPLEMENTED_POLICY: +// 0 -- Do nothing (stripped by compiler) +// 1 -- Warn at compile time +// 2 -- Fail at compile time +// 3 -- Fail at runtime (DCHECK) +// 4 -- [default] LOG(ERROR) at runtime +// 5 -- LOG(ERROR) at runtime, only once per call-site + +#ifndef NOTIMPLEMENTED_POLICY +#if defined(OS_ANDROID) && defined(OFFICIAL_BUILD) +#define NOTIMPLEMENTED_POLICY 0 +#else +// Select default policy: LOG(ERROR) +#define NOTIMPLEMENTED_POLICY 4 +#endif +#endif + +#if defined(COMPILER_GCC) +// On Linux, with GCC, we can use __PRETTY_FUNCTION__ to get the demangled name +// of the current function in the NOTIMPLEMENTED message. +#define NOTIMPLEMENTED_MSG "Not implemented reached in " << __PRETTY_FUNCTION__ +#else +#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED" +#endif + +#if NOTIMPLEMENTED_POLICY == 0 +#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS +#elif NOTIMPLEMENTED_POLICY == 1 +// TODO, figure out how to generate a warning +#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#elif NOTIMPLEMENTED_POLICY == 2 +#define NOTIMPLEMENTED() COMPILE_ASSERT(false, NOT_IMPLEMENTED) +#elif NOTIMPLEMENTED_POLICY == 3 +#define NOTIMPLEMENTED() NOTREACHED() +#elif NOTIMPLEMENTED_POLICY == 4 +#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG +#elif NOTIMPLEMENTED_POLICY == 5 +#define NOTIMPLEMENTED() do {\ + static bool logged_once = false;\ + LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\ + logged_once = true;\ +} while(0);\ +EAT_STREAM_PARAMETERS +#endif + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_LOGGING_H_ diff --git a/include/base/cef_macros.h b/include/base/cef_macros.h new file mode 100644 index 000000000..41b40e79a --- /dev/null +++ b/include/base/cef_macros.h @@ -0,0 +1,217 @@ +// 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_MACROS_H_ +#define CEF_INCLUDE_BASE_CEF_MACROS_H_ +#pragma once + +#if defined(BUILDING_CEF_SHARED) +// When building CEF include the Chromium header directly. +#include "base/macros.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 // For size_t. + +#if !defined(ALLOW_THIS_IN_INITIALIZER_LIST) +#if defined(COMPILER_MSVC) + +// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled. +// The warning remains disabled until popped by MSVC_POP_WARNING. +#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ + __pragma(warning(disable:n)) + +// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level +// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all +// warnings. +#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n)) + +// Pop effects of innermost MSVC_PUSH_* macro. +#define MSVC_POP_WARNING() __pragma(warning(pop)) + +// Allows |this| to be passed as an argument in constructor initializer lists. +// This uses push/pop instead of the seemingly simpler suppress feature to avoid +// having the warning be disabled for more than just |code|. +// +// Example usage: +// Foo::Foo() : x(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(y(this)), z(3) {} +// +// Compiler warning C4355: 'this': used in base member initializer list: +// http://msdn.microsoft.com/en-us/library/3c594ae3(VS.80).aspx +#define ALLOW_THIS_IN_INITIALIZER_LIST(code) MSVC_PUSH_DISABLE_WARNING(4355) \ + code \ + MSVC_POP_WARNING() +#else // !COMPILER_MSVC + +#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code + +#endif // !COMPILER_MSVC +#endif // !ALLOW_THIS_IN_INITIALIZER_LIST + +#if !defined(arraysize) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template +char (&ArraySizeHelper(T (&array)[N]))[N]; + +// That gcc wants both of these prototypes seems mysterious. VC, for +// its part, can't decide which to use (another mystery). Matching of +// template overloads: the final frontier. +#ifndef _MSC_VER +template +char (&ArraySizeHelper(const T (&array)[N]))[N]; +#endif + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +#endif // !arraysize + +#if !defined(DISALLOW_COPY_AND_ASSIGN) + +// A macro to disallow the copy constructor and operator= functions +// This should be used in the private: declarations for a class +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // !DISALLOW_COPY_AND_ASSIGN + +#if !defined(DISALLOW_IMPLICIT_CONSTRUCTORS) + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +#endif // !DISALLOW_IMPLICIT_CONSTRUCTORS + +#if !defined(COMPILE_ASSERT) + +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +#if __cplusplus >= 201103L + +// Under C++11, just use static_assert. +#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) + +#else + +namespace cef { + +template +struct CompileAssert { +}; + +} // namespace cef + +#define COMPILE_ASSERT(expr, msg) \ + typedef cef::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ALLOW_UNUSED + +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outer parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +#endif // !(__cplusplus >= 201103L) + +#endif // !defined(COMPILE_ASSERT) + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_MACROS_H_ diff --git a/include/base/cef_move.h b/include/base/cef_move.h new file mode 100644 index 000000000..91069297d --- /dev/null +++ b/include/base/cef_move.h @@ -0,0 +1,259 @@ +// 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_MOVE_H_ +#define CEF_INCLUDE_BASE_CEF_MOVE_H_ + +#if defined(MOVE_ONLY_TYPE_FOR_CPP_03) +// Do nothing if the macro in this header has already been defined. +// 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/move.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. + +// Macro with the boilerplate that makes a type move-only in C++03. +// +// USAGE +// +// This macro should be used instead of DISALLOW_COPY_AND_ASSIGN to create +// a "move-only" type. Unlike DISALLOW_COPY_AND_ASSIGN, this macro should be +// the first line in a class declaration. +// +// A class using this macro must call .Pass() (or somehow be an r-value already) +// before it can be: +// +// * Passed as a function argument +// * Used as the right-hand side of an assignment +// * Returned from a function +// +// Each class will still need to define their own "move constructor" and "move +// operator=" to make this useful. Here's an example of the macro, the move +// constructor, and the move operator= from the scoped_ptr class: +// +// template +// class scoped_ptr { +// MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) +// public: +// scoped_ptr(RValue& other) : ptr_(other.release()) { } +// scoped_ptr& operator=(RValue& other) { +// swap(other); +// return *this; +// } +// }; +// +// Note that the constructor must NOT be marked explicit. +// +// For consistency, the second parameter to the macro should always be RValue +// unless you have a strong reason to do otherwise. It is only exposed as a +// macro parameter so that the move constructor and move operator= don't look +// like they're using a phantom type. +// +// +// HOW THIS WORKS +// +// For a thorough explanation of this technique, see: +// +// http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor +// +// The summary is that we take advantage of 2 properties: +// +// 1) non-const references will not bind to r-values. +// 2) C++ can apply one user-defined conversion when initializing a +// variable. +// +// The first lets us disable the copy constructor and assignment operator +// by declaring private version of them with a non-const reference parameter. +// +// For l-values, direct initialization still fails like in +// DISALLOW_COPY_AND_ASSIGN because the copy constructor and assignment +// operators are private. +// +// For r-values, the situation is different. The copy constructor and +// assignment operator are not viable due to (1), so we are trying to call +// a non-existent constructor and non-existing operator= rather than a private +// one. Since we have not committed an error quite yet, we can provide an +// alternate conversion sequence and a constructor. We add +// +// * a private struct named "RValue" +// * a user-defined conversion "operator RValue()" +// * a "move constructor" and "move operator=" that take the RValue& as +// their sole parameter. +// +// Only r-values will trigger this sequence and execute our "move constructor" +// or "move operator=." L-values will match the private copy constructor and +// operator= first giving a "private in this context" error. This combination +// gives us a move-only type. +// +// For signaling a destructive transfer of data from an l-value, we provide a +// method named Pass() which creates an r-value for the current instance +// triggering the move constructor or move operator=. +// +// Other ways to get r-values is to use the result of an expression like a +// function call. +// +// Here's an example with comments explaining what gets triggered where: +// +// class Foo { +// MOVE_ONLY_TYPE_FOR_CPP_03(Foo, RValue); +// +// public: +// ... API ... +// Foo(RValue other); // Move constructor. +// Foo& operator=(RValue rhs); // Move operator= +// }; +// +// Foo MakeFoo(); // Function that returns a Foo. +// +// Foo f; +// Foo f_copy(f); // ERROR: Foo(Foo&) is private in this context. +// Foo f_assign; +// f_assign = f; // ERROR: operator=(Foo&) is private in this context. +// +// +// Foo f(MakeFoo()); // R-value so alternate conversion executed. +// Foo f_copy(f.Pass()); // R-value so alternate conversion executed. +// f = f_copy.Pass(); // R-value so alternate conversion executed. +// +// +// IMPLEMENTATION SUBTLETIES WITH RValue +// +// The RValue struct is just a container for a pointer back to the original +// object. It should only ever be created as a temporary, and no external +// class should ever declare it or use it in a parameter. +// +// It is tempting to want to use the RValue type in function parameters, but +// excluding the limited usage here for the move constructor and move +// operator=, doing so would mean that the function could take both r-values +// and l-values equially which is unexpected. See COMPARED To Boost.Move for +// more details. +// +// An alternate, and incorrect, implementation of the RValue class used by +// Boost.Move makes RValue a fieldless child of the move-only type. RValue& +// is then used in place of RValue in the various operators. The RValue& is +// "created" by doing *reinterpret_cast(this). This has the appeal +// of never creating a temporary RValue struct even with optimizations +// disabled. Also, by virtue of inheritance you can treat the RValue +// reference as if it were the move-only type itself. Unfortunately, +// using the result of this reinterpret_cast<> is actually undefined behavior +// due to C++98 5.2.10.7. In certain compilers (e.g., NaCl) the optimizer +// will generate non-working code. +// +// In optimized builds, both implementations generate the same assembly so we +// choose the one that adheres to the standard. +// +// +// WHY HAVE typedef void MoveOnlyTypeForCPP03 +// +// Callback<>/Bind() needs to understand movable-but-not-copyable semantics +// to call .Pass() appropriately when it is expected to transfer the value. +// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check +// easy and automatic in helper templates for Callback<>/Bind(). +// See IsMoveOnlyType template and its usage in base/callback_internal.h +// for more details. +// +// +// COMPARED TO C++11 +// +// In C++11, you would implement this functionality using an r-value reference +// and our .Pass() method would be replaced with a call to std::move(). +// +// This emulation also has a deficiency where it uses up the single +// user-defined conversion allowed by C++ during initialization. This can +// cause problems in some API edge cases. For instance, in scoped_ptr, it is +// impossible to make a function "void Foo(scoped_ptr p)" accept a +// value of type scoped_ptr even if you add a constructor to +// scoped_ptr<> that would make it look like it should work. C++11 does not +// have this deficiency. +// +// +// COMPARED TO Boost.Move +// +// Our implementation similar to Boost.Move, but we keep the RValue struct +// private to the move-only type, and we don't use the reinterpret_cast<> hack. +// +// In Boost.Move, RValue is the boost::rv<> template. This type can be used +// when writing APIs like: +// +// void MyFunc(boost::rv& f) +// +// that can take advantage of rv<> to avoid extra copies of a type. However you +// would still be able to call this version of MyFunc with an l-value: +// +// Foo f; +// MyFunc(f); // Uh oh, we probably just destroyed |f| w/o calling Pass(). +// +// unless someone is very careful to also declare a parallel override like: +// +// void MyFunc(const Foo& f) +// +// that would catch the l-values first. This was declared unsafe in C++11 and +// a C++11 compiler will explicitly fail MyFunc(f). Unfortunately, we cannot +// ensure this in C++03. +// +// Since we have no need for writing such APIs yet, our implementation keeps +// RValue private and uses a .Pass() method to do the conversion instead of +// trying to write a version of "std::move()." Writing an API like std::move() +// would require the RValue struct to be public. +// +// +// CAVEATS +// +// If you include a move-only type as a field inside a class that does not +// explicitly declare a copy constructor, the containing class's implicit +// copy constructor will change from Containing(const Containing&) to +// Containing(Containing&). This can cause some unexpected errors. +// +// http://llvm.org/bugs/show_bug.cgi?id=11528 +// +// The workaround is to explicitly declare your copy constructor. +// +#define MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \ + private: \ + struct rvalue_type { \ + explicit rvalue_type(type* object) : object(object) {} \ + type* object; \ + }; \ + type(type&); \ + void operator=(type&); \ + public: \ + operator rvalue_type() { return rvalue_type(this); } \ + type Pass() { return type(rvalue_type(this)); } \ + typedef void MoveOnlyTypeForCPP03; \ + private: + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_MOVE_H_ diff --git a/include/base/cef_platform_thread.h b/include/base/cef_platform_thread.h new file mode 100644 index 000000000..cda1dc45b --- /dev/null +++ b/include/base/cef_platform_thread.h @@ -0,0 +1,113 @@ +// 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. + +// WARNING: You should *NOT* be using this class directly. PlatformThread is +// the low-level platform-specific abstraction to the OS's threading interface. +// You should instead be using a message-loop driven Thread, see thread.h. + +#ifndef CEF_INCLUDE_BASE_PLATFORM_THREAD_H_ +#define CEF_INCLUDE_BASE_PLATFORM_THREAD_H_ + +#if defined(BASE_THREADING_PLATFORM_THREAD_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/threading/platform_thread.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_basictypes.h" +#include "include/base/cef_build.h" +#include "include/internal/cef_thread_internal.h" + +namespace base { + +// Used for logging. Always an integer value. +typedef cef_platform_thread_id_t PlatformThreadId; + +// Used for thread checking and debugging. +// Meant to be as fast as possible. +// These are produced by PlatformThread::CurrentRef(), and used to later +// check if we are on the same thread or not by using ==. These are safe +// to copy between threads, but can't be copied to another process as they +// have no meaning there. Also, the internal identifier can be re-used +// after a thread dies, so a PlatformThreadRef cannot be reliably used +// to distinguish a new thread from an old, dead thread. +class PlatformThreadRef { + public: + typedef cef_platform_thread_handle_t RefType; + + PlatformThreadRef() + : id_(0) { + } + + explicit PlatformThreadRef(RefType id) + : id_(id) { + } + + bool operator==(PlatformThreadRef other) const { + return id_ == other.id_; + } + + bool is_null() const { + return id_ == 0; + } + private: + RefType id_; +}; + +// A namespace for low-level thread functions. +// Chromium uses a class with static methods but CEF uses an actual namespace +// to avoid linker problems with the sandbox libaries on Windows. +namespace PlatformThread { + +// Gets the current thread id, which may be useful for logging purposes. +inline PlatformThreadId CurrentId() { + return cef_get_current_platform_thread_id(); +} + +// Gets the current thread reference, which can be used to check if +// we're on the right thread quickly. +inline PlatformThreadRef CurrentRef() { + return PlatformThreadRef(cef_get_current_platform_thread_handle()); +} + +} // namespace PlatformThread + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_PLATFORM_THREAD_H_ diff --git a/include/base/cef_ref_counted.h b/include/base/cef_ref_counted.h new file mode 100644 index 000000000..55d41e1b4 --- /dev/null +++ b/include/base/cef_ref_counted.h @@ -0,0 +1,386 @@ +// 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_REF_COUNTED_H_ +#define CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_ +#pragma once + +#if defined(BASE_MEMORY_REF_COUNTED_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/memory/ref_counted.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 "include/base/cef_atomic_ref_count.h" +#include "include/base/cef_build.h" +#ifndef NDEBUG +#include "include/base/cef_logging.h" +#endif +#include "include/base/cef_thread_collision_warner.h" + +namespace base { + +namespace subtle { + +class RefCountedBase { + public: + bool HasOneRef() const { return ref_count_ == 1; } + + protected: + RefCountedBase() + : ref_count_(0) + #ifndef NDEBUG + , in_dtor_(false) + #endif + { + } + + ~RefCountedBase() { + #ifndef NDEBUG + DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; + #endif + } + + + void AddRef() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" + // without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); + #ifndef NDEBUG + DCHECK(!in_dtor_); + #endif + ++ref_count_; + } + + // Returns true if the object should self-delete. + bool Release() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" + // without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); + #ifndef NDEBUG + DCHECK(!in_dtor_); + #endif + if (--ref_count_ == 0) { + #ifndef NDEBUG + in_dtor_ = true; + #endif + return true; + } + return false; + } + + private: + mutable int ref_count_; +#ifndef NDEBUG + mutable bool in_dtor_; +#endif + + DFAKE_MUTEX(add_release_); + + DISALLOW_COPY_AND_ASSIGN(RefCountedBase); +}; + +class RefCountedThreadSafeBase { + public: + bool HasOneRef() const; + + protected: + RefCountedThreadSafeBase(); + ~RefCountedThreadSafeBase(); + + void AddRef() const; + + // Returns true if the object should self-delete. + bool Release() const; + + private: + mutable AtomicRefCount ref_count_; +#ifndef NDEBUG + mutable bool in_dtor_; +#endif + + DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); +}; + +} // namespace subtle + +// +// A base class for reference counted classes. Otherwise, known as a cheap +// knock-off of WebKit's RefCounted class. To use this guy just extend your +// class from it like so: +// +// class MyFoo : public base::RefCounted { +// ... +// private: +// friend class base::RefCounted; +// ~MyFoo(); +// }; +// +// You should always make your destructor private, to avoid any code deleting +// the object accidently while there are references to it. +template +class RefCounted : public subtle::RefCountedBase { + public: + RefCounted() {} + + void AddRef() const { + subtle::RefCountedBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedBase::Release()) { + delete static_cast(this); + } + } + + protected: + ~RefCounted() {} + + private: + DISALLOW_COPY_AND_ASSIGN(RefCounted); +}; + +// Forward declaration. +template class RefCountedThreadSafe; + +// Default traits for RefCountedThreadSafe. Deletes the object when its ref +// count reaches 0. Overload to delete it on a different thread etc. +template +struct DefaultRefCountedThreadSafeTraits { + static void Destruct(const T* x) { + // Delete through RefCountedThreadSafe to make child classes only need to be + // friend with RefCountedThreadSafe instead of this struct, which is an + // implementation detail. + RefCountedThreadSafe::DeleteInternal(x); + } +}; + +// +// A thread-safe variant of RefCounted +// +// class MyFoo : public base::RefCountedThreadSafe { +// ... +// }; +// +// If you're using the default trait, then you should add compile time +// asserts that no one else is deleting your object. i.e. +// private: +// friend class base::RefCountedThreadSafe; +// ~MyFoo(); +template > +class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { + public: + RefCountedThreadSafe() {} + + void AddRef() const { + subtle::RefCountedThreadSafeBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedThreadSafeBase::Release()) { + Traits::Destruct(static_cast(this)); + } + } + + protected: + ~RefCountedThreadSafe() {} + + private: + friend struct DefaultRefCountedThreadSafeTraits; + static void DeleteInternal(const T* x) { delete x; } + + DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); +}; + +// +// A thread-safe wrapper for some piece of data so we can place other +// things in scoped_refptrs<>. +// +template +class RefCountedData + : public base::RefCountedThreadSafe< base::RefCountedData > { + public: + RefCountedData() : data() {} + RefCountedData(const T& in_value) : data(in_value) {} + + T data; + + private: + friend class base::RefCountedThreadSafe >; + ~RefCountedData() {} +}; + +} // namespace base + +// +// A smart pointer class for reference counted objects. Use this class instead +// of calling AddRef and Release manually on a reference counted object to +// avoid common memory leaks caused by forgetting to Release an object +// reference. Sample usage: +// +// class MyFoo : public RefCounted { +// ... +// }; +// +// void some_function() { +// scoped_refptr foo = new MyFoo(); +// foo->Method(param); +// // |foo| is released when this function returns +// } +// +// void some_other_function() { +// scoped_refptr foo = new MyFoo(); +// ... +// foo = NULL; // explicitly releases |foo| +// ... +// if (foo) +// foo->Method(param); +// } +// +// The above examples show how scoped_refptr acts like a pointer to T. +// Given two scoped_refptr classes, it is also possible to exchange +// references between the two objects, like so: +// +// { +// scoped_refptr a = new MyFoo(); +// scoped_refptr b; +// +// b.swap(a); +// // now, |b| references the MyFoo object, and |a| references NULL. +// } +// +// To make both |a| and |b| in the above example reference the same MyFoo +// object, simply use the assignment operator: +// +// { +// scoped_refptr a = new MyFoo(); +// scoped_refptr b; +// +// b = a; +// // now, |a| and |b| each own a reference to the same MyFoo object. +// } +// +template +class scoped_refptr { + public: + typedef T element_type; + + scoped_refptr() : ptr_(NULL) { + } + + scoped_refptr(T* p) : ptr_(p) { + if (ptr_) + ptr_->AddRef(); + } + + scoped_refptr(const scoped_refptr& r) : ptr_(r.ptr_) { + if (ptr_) + ptr_->AddRef(); + } + + template + scoped_refptr(const scoped_refptr& r) : ptr_(r.get()) { + if (ptr_) + ptr_->AddRef(); + } + + ~scoped_refptr() { + if (ptr_) + ptr_->Release(); + } + + T* get() const { return ptr_; } + + // Allow scoped_refptr to be used in boolean expression + // and comparison operations. + operator T*() const { return ptr_; } + + T* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + + scoped_refptr& operator=(T* p) { + // AddRef first so that self assignment should work + if (p) + p->AddRef(); + T* old_ptr = ptr_; + ptr_ = p; + if (old_ptr) + old_ptr->Release(); + return *this; + } + + scoped_refptr& operator=(const scoped_refptr& r) { + return *this = r.ptr_; + } + + template + scoped_refptr& operator=(const scoped_refptr& r) { + return *this = r.get(); + } + + void swap(T** pp) { + T* p = ptr_; + ptr_ = *pp; + *pp = p; + } + + void swap(scoped_refptr& r) { + swap(&r.ptr_); + } + + protected: + T* ptr_; +}; + +// Handy utility for creating a scoped_refptr out of a T* explicitly without +// having to retype all the template arguments +template +scoped_refptr make_scoped_refptr(T* t) { + return scoped_refptr(t); +} + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_REF_COUNTED_H_ diff --git a/include/base/cef_scoped_ptr.h b/include/base/cef_scoped_ptr.h new file mode 100644 index 000000000..be9b2007a --- /dev/null +++ b/include/base/cef_scoped_ptr.h @@ -0,0 +1,623 @@ +// 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. + +// Scopers help you manage ownership of a pointer, helping you easily manage a +// pointer within a scope, and automatically destroying the pointer at the end +// of a scope. There are two main classes you will use, which correspond to the +// operators new/delete and new[]/delete[]. +// +// Example usage (scoped_ptr): +// { +// scoped_ptr foo(new Foo("wee")); +// } // foo goes out of scope, releasing the pointer with it. +// +// { +// scoped_ptr foo; // No pointer managed. +// foo.reset(new Foo("wee")); // Now a pointer is managed. +// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. +// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. +// foo->Method(); // Foo::Method() called. +// foo.get()->Method(); // Foo::Method() called. +// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer +// // manages a pointer. +// foo.reset(new Foo("wee4")); // foo manages a pointer again. +// foo.reset(); // Foo("wee4") destroyed, foo no longer +// // manages a pointer. +// } // foo wasn't managing a pointer, so nothing was destroyed. +// +// Example usage (scoped_ptr): +// { +// scoped_ptr foo(new Foo[100]); +// foo.get()->Method(); // Foo::Method on the 0th element. +// foo[10].Method(); // Foo::Method on the 10th element. +// } +// +// These scopers also implement part of the functionality of C++11 unique_ptr +// in that they are "movable but not copyable." You can use the scopers in +// the parameter and return types of functions to signify ownership transfer +// in to and out of a function. When calling a function that has a scoper +// as the argument type, it must be called with the result of an analogous +// scoper's Pass() function or another function that generates a temporary; +// passing by copy will NOT work. Here is an example using scoped_ptr: +// +// void TakesOwnership(scoped_ptr arg) { +// // Do something with arg +// } +// scoped_ptr CreateFoo() { +// // No need for calling Pass() because we are constructing a temporary +// // for the return value. +// return scoped_ptr(new Foo("new")); +// } +// scoped_ptr PassThru(scoped_ptr arg) { +// return arg.Pass(); +// } +// +// { +// scoped_ptr ptr(new Foo("yay")); // ptr manages Foo("yay"). +// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). +// scoped_ptr ptr2 = CreateFoo(); // ptr2 owns the return Foo. +// scoped_ptr ptr3 = // ptr3 now owns what was in ptr2. +// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. +// } +// +// Notice that if you do not call Pass() when returning from PassThru(), or +// when invoking TakesOwnership(), the code will not compile because scopers +// are not copyable; they only implement move semantics which require calling +// the Pass() function to signify a destructive transfer of state. CreateFoo() +// is different though because we are constructing a temporary on the return +// line and thus can avoid needing to call Pass(). +// +// Pass() properly handles upcast in initialization, i.e. you can use a +// scoped_ptr to initialize a scoped_ptr: +// +// scoped_ptr foo(new Foo()); +// scoped_ptr parent(foo.Pass()); +// +// PassAs<>() should be used to upcast return value in return statement: +// +// scoped_ptr CreateFoo() { +// scoped_ptr result(new FooChild()); +// return result.PassAs(); +// } +// +// Note that PassAs<>() is implemented only for scoped_ptr, but not for +// scoped_ptr. This is because casting array pointers may not be safe. + +#ifndef CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_ +#define CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_ +#pragma once + +#if defined(BASE_MEMORY_SCOPED_PTR_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/memory/scoped_ptr.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. + +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class. + +#include +#include +#include + +#include // For std::swap(). + +#include "include/base/cef_basictypes.h" +#include "include/base/cef_build.h" +#include "include/base/cef_move.h" +#include "include/base/cef_template_util.h" + +namespace base { + +namespace subtle { +class RefCountedBase; +class RefCountedThreadSafeBase; +} // namespace subtle + +// Function object which deletes its parameter, which must be a pointer. +// If C is an array type, invokes 'delete[]' on the parameter; otherwise, +// invokes 'delete'. The default deleter for scoped_ptr. +template +struct DefaultDeleter { + DefaultDeleter() {} + template DefaultDeleter(const DefaultDeleter& other) { + // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor + // if U* is implicitly convertible to T* and U is not an array type. + // + // Correct implementation should use SFINAE to disable this + // constructor. However, since there are no other 1-argument constructors, + // using a COMPILE_ASSERT() based on is_convertible<> and requiring + // complete types is simpler and will cause compile failures for equivalent + // misuses. + // + // Note, the is_convertible check also ensures that U is not an + // array. T is guaranteed to be a non-array, so any U* where U is an array + // cannot convert to T*. + enum { T_must_be_complete = sizeof(T) }; + enum { U_must_be_complete = sizeof(U) }; + COMPILE_ASSERT((base::is_convertible::value), + U_ptr_must_implicitly_convert_to_T_ptr); + } + inline void operator()(T* ptr) const { + enum { type_must_be_complete = sizeof(T) }; + delete ptr; + } +}; + +// Specialization of DefaultDeleter for array types. +template +struct DefaultDeleter { + inline void operator()(T* ptr) const { + enum { type_must_be_complete = sizeof(T) }; + delete[] ptr; + } + + private: + // Disable this operator for any U != T because it is undefined to execute + // an array delete when the static type of the array mismatches the dynamic + // type. + // + // References: + // C++98 [expr.delete]p3 + // http://cplusplus.github.com/LWG/lwg-defects.html#938 + template void operator()(U* array) const; +}; + +template +struct DefaultDeleter { + // Never allow someone to declare something like scoped_ptr. + COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); +}; + +// Function object which invokes 'free' on its parameter, which must be +// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: +// +// scoped_ptr foo_ptr( +// static_cast(malloc(sizeof(int)))); +struct FreeDeleter { + inline void operator()(void* ptr) const { + free(ptr); + } +}; + +namespace internal { + +template struct IsNotRefCounted { + enum { + value = !base::is_convertible::value && + !base::is_convertible:: + value + }; +}; + +// Minimal implementation of the core logic of scoped_ptr, suitable for +// reuse in both scoped_ptr and its specializations. +template +class scoped_ptr_impl { + public: + explicit scoped_ptr_impl(T* p) : data_(p) { } + + // Initializer for deleters that have data parameters. + scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} + + // Templated constructor that destructively takes the value from another + // scoped_ptr_impl. + template + scoped_ptr_impl(scoped_ptr_impl* other) + : data_(other->release(), other->get_deleter()) { + // We do not support move-only deleters. We could modify our move + // emulation to have base::subtle::move() and base::subtle::forward() + // functions that are imperfect emulations of their C++11 equivalents, + // but until there's a requirement, just assume deleters are copyable. + } + + template + void TakeState(scoped_ptr_impl* other) { + // See comment in templated constructor above regarding lack of support + // for move-only deleters. + reset(other->release()); + get_deleter() = other->get_deleter(); + } + + ~scoped_ptr_impl() { + if (data_.ptr != NULL) { + // Not using get_deleter() saves one function call in non-optimized + // builds. + static_cast(data_)(data_.ptr); + } + } + + void reset(T* p) { + // This is a self-reset, which is no longer allowed: http://crbug.com/162971 + if (p != NULL && p == data_.ptr) + abort(); + + // Note that running data_.ptr = p can lead to undefined behavior if + // get_deleter()(get()) deletes this. In order to prevent this, reset() + // should update the stored pointer before deleting its old value. + // + // However, changing reset() to use that behavior may cause current code to + // break in unexpected ways. If the destruction of the owned object + // dereferences the scoped_ptr when it is destroyed by a call to reset(), + // then it will incorrectly dispatch calls to |p| rather than the original + // value of |data_.ptr|. + // + // During the transition period, set the stored pointer to NULL while + // deleting the object. Eventually, this safety check will be removed to + // prevent the scenario initially described from occuring and + // http://crbug.com/176091 can be closed. + T* old = data_.ptr; + data_.ptr = NULL; + if (old != NULL) + static_cast(data_)(old); + data_.ptr = p; + } + + T* get() const { return data_.ptr; } + + D& get_deleter() { return data_; } + const D& get_deleter() const { return data_; } + + void swap(scoped_ptr_impl& p2) { + // Standard swap idiom: 'using std::swap' ensures that std::swap is + // present in the overload set, but we call swap unqualified so that + // any more-specific overloads can be used, if available. + using std::swap; + swap(static_cast(data_), static_cast(p2.data_)); + swap(data_.ptr, p2.data_.ptr); + } + + T* release() { + T* old_ptr = data_.ptr; + data_.ptr = NULL; + return old_ptr; + } + + private: + // Needed to allow type-converting constructor. + template friend class scoped_ptr_impl; + + // Use the empty base class optimization to allow us to have a D + // member, while avoiding any space overhead for it when D is an + // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good + // discussion of this technique. + struct Data : public D { + explicit Data(T* ptr_in) : ptr(ptr_in) {} + Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} + T* ptr; + }; + + Data data_; + + DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); +}; + +} // namespace internal + +} // namespace base + +// A scoped_ptr is like a T*, except that the destructor of scoped_ptr +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr owns the T object that it points to. +// Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. +// Also like T*, scoped_ptr is thread-compatible, and once you +// dereference it, you get the thread safety guarantees of T. +// +// The size of scoped_ptr is small. On most compilers, when using the +// DefaultDeleter, sizeof(scoped_ptr) == sizeof(T*). Custom deleters will +// increase the size proportional to whatever state they need to have. See +// comments inside scoped_ptr_impl<> for details. +// +// Current implementation targets having a strict subset of C++11's +// unique_ptr<> features. Known deficiencies include not supporting move-only +// deleteres, function pointers as deleters, and deleters with reference +// types. +template > +class scoped_ptr { + MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + + COMPILE_ASSERT(base::internal::IsNotRefCounted::value, + T_is_refcounted_type_and_needs_scoped_refptr); + + public: + // The element and deleter types. + typedef T element_type; + typedef D deleter_type; + + // Constructor. Defaults to initializing with NULL. + scoped_ptr() : impl_(NULL) { } + + // Constructor. Takes ownership of p. + explicit scoped_ptr(element_type* p) : impl_(p) { } + + // Constructor. Allows initialization of a stateful deleter. + scoped_ptr(element_type* p, const D& d) : impl_(p, d) { } + + // Constructor. Allows construction from a scoped_ptr rvalue for a + // convertible type and deleter. + // + // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct + // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor + // has different post-conditions if D is a reference type. Since this + // implementation does not support deleters with reference type, + // we do not need a separate move constructor allowing us to avoid one + // use of SFINAE. You only need to care about this if you modify the + // implementation of scoped_ptr. + template + scoped_ptr(scoped_ptr other) : impl_(&other.impl_) { + COMPILE_ASSERT(!base::is_array::value, U_cannot_be_an_array); + } + + // Constructor. Move constructor for C++03 move emulation of this type. + scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } + + // operator=. Allows assignment from a scoped_ptr rvalue for a convertible + // type and deleter. + // + // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from + // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated + // form has different requirements on for move-only Deleters. Since this + // implementation does not support move-only Deleters, we do not need a + // separate move assignment operator allowing us to avoid one use of SFINAE. + // You only need to care about this if you modify the implementation of + // scoped_ptr. + template + scoped_ptr& operator=(scoped_ptr rhs) { + COMPILE_ASSERT(!base::is_array::value, U_cannot_be_an_array); + impl_.TakeState(&rhs.impl_); + return *this; + } + + // Reset. Deletes the currently owned object, if any. + // Then takes ownership of a new object, if given. + void reset(element_type* p = NULL) { impl_.reset(p); } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + element_type& operator*() const { + assert(impl_.get() != NULL); + return *impl_.get(); + } + element_type* operator->() const { + assert(impl_.get() != NULL); + return impl_.get(); + } + element_type* get() const { return impl_.get(); } + + // Access to the deleter. + deleter_type& get_deleter() { return impl_.get_deleter(); } + const deleter_type& get_deleter() const { return impl_.get_deleter(); } + + // Allow scoped_ptr to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + // + // Note that this trick is only safe when the == and != operators + // are declared explicitly, as otherwise "scoped_ptr1 == + // scoped_ptr2" will compile but do the wrong thing (i.e., convert + // to Testable and then do the comparison). + private: + typedef base::internal::scoped_ptr_impl + scoped_ptr::*Testable; + + public: + operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(const element_type* p) const { return impl_.get() == p; } + bool operator!=(const element_type* p) const { return impl_.get() != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + impl_.swap(p2.impl_); + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + element_type* release() WARN_UNUSED_RESULT { + return impl_.release(); + } + + // C++98 doesn't support functions templates with default parameters which + // makes it hard to write a PassAs() that understands converting the deleter + // while preserving simple calling semantics. + // + // Until there is a use case for PassAs() with custom deleters, just ignore + // the custom deleter. + template + scoped_ptr PassAs() { + return scoped_ptr(Pass()); + } + + private: + // Needed to reach into |impl_| in the constructor. + template friend class scoped_ptr; + base::internal::scoped_ptr_impl impl_; + + // Forbidden for API compatibility with std::unique_ptr. + explicit scoped_ptr(int disallow_construction_from_null); + + // Forbid comparison of scoped_ptr types. If U != T, it totally + // doesn't make sense, and if U == T, it still doesn't make sense + // because you should never have the same object owned by two different + // scoped_ptrs. + template bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; +}; + +template +class scoped_ptr { + MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) + + public: + // The element and deleter types. + typedef T element_type; + typedef D deleter_type; + + // Constructor. Defaults to initializing with NULL. + scoped_ptr() : impl_(NULL) { } + + // Constructor. Stores the given array. Note that the argument's type + // must exactly match T*. In particular: + // - it cannot be a pointer to a type derived from T, because it is + // inherently unsafe in the general case to access an array through a + // pointer whose dynamic type does not match its static type (eg., if + // T and the derived types had different sizes access would be + // incorrectly calculated). Deletion is also always undefined + // (C++98 [expr.delete]p3). If you're doing this, fix your code. + // - it cannot be NULL, because NULL is an integral expression, not a + // pointer to T. Use the no-argument version instead of explicitly + // passing NULL. + // - it cannot be const-qualified differently from T per unique_ptr spec + // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting + // to work around this may use implicit_cast(). + // However, because of the first bullet in this comment, users MUST + // NOT use implicit_cast() to upcast the static type of the array. + explicit scoped_ptr(element_type* array) : impl_(array) { } + + // Constructor. Move constructor for C++03 move emulation of this type. + scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { } + + // operator=. Move operator= for C++03 move emulation of this type. + scoped_ptr& operator=(RValue rhs) { + impl_.TakeState(&rhs.object->impl_); + return *this; + } + + // Reset. Deletes the currently owned array, if any. + // Then takes ownership of a new object, if given. + void reset(element_type* array = NULL) { impl_.reset(array); } + + // Accessors to get the owned array. + element_type& operator[](size_t i) const { + assert(impl_.get() != NULL); + return impl_.get()[i]; + } + element_type* get() const { return impl_.get(); } + + // Access to the deleter. + deleter_type& get_deleter() { return impl_.get_deleter(); } + const deleter_type& get_deleter() const { return impl_.get_deleter(); } + + // Allow scoped_ptr to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + private: + typedef base::internal::scoped_ptr_impl + scoped_ptr::*Testable; + + public: + operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(element_type* array) const { return impl_.get() == array; } + bool operator!=(element_type* array) const { return impl_.get() != array; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + impl_.swap(p2.impl_); + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + element_type* release() WARN_UNUSED_RESULT { + return impl_.release(); + } + + private: + // Force element_type to be a complete type. + enum { type_must_be_complete = sizeof(element_type) }; + + // Actually hold the data. + base::internal::scoped_ptr_impl impl_; + + // Disable initialization from any type other than element_type*, by + // providing a constructor that matches such an initialization, but is + // private and has no definition. This is disabled because it is not safe to + // call delete[] on an array whose static type does not match its dynamic + // type. + template explicit scoped_ptr(U* array); + explicit scoped_ptr(int disallow_construction_from_null); + + // Disable reset() from any type other than element_type*, for the same + // reasons as the constructor above. + template void reset(U* array); + void reset(int disallow_reset_from_null); + + // Forbid comparison of scoped_ptr types. If U != T, it totally + // doesn't make sense, and if U == T, it still doesn't make sense + // because you should never have the same object owned by two different + // scoped_ptrs. + template bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; +}; + +// Free functions +template +void swap(scoped_ptr& p1, scoped_ptr& p2) { + p1.swap(p2); +} + +template +bool operator==(T* p1, const scoped_ptr& p2) { + return p1 == p2.get(); +} + +template +bool operator!=(T* p1, const scoped_ptr& p2) { + return p1 != p2.get(); +} + +// A function to convert T* into scoped_ptr +// Doing e.g. make_scoped_ptr(new FooBarBaz(arg)) is a shorter notation +// for scoped_ptr >(new FooBarBaz(arg)) +template +scoped_ptr make_scoped_ptr(T* ptr) { + return scoped_ptr(ptr); +} + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_MEMORY_SCOPED_PTR_H_ diff --git a/include/base/cef_string16.h b/include/base/cef_string16.h new file mode 100644 index 000000000..30d9dd114 --- /dev/null +++ b/include/base/cef_string16.h @@ -0,0 +1,225 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2013 +// 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_STRING16_H_ +#define CEF_INCLUDE_BASE_CEF_STRING16_H_ +#pragma once + +#if defined(BASE_STRINGS_STRING16_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/strings/string16.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. +// WHAT: +// A version of std::basic_string that provides 2-byte characters even when +// wchar_t is not implemented as a 2-byte type. You can access this class as +// string16. We also define char16, which string16 is based upon. +// +// WHY: +// On Windows, wchar_t is 2 bytes, and it can conveniently handle UTF-16/UCS-2 +// data. Plenty of existing code operates on strings encoded as UTF-16. +// +// On many other platforms, sizeof(wchar_t) is 4 bytes by default. We can make +// it 2 bytes by using the GCC flag -fshort-wchar. But then std::wstring fails +// at run time, because it calls some functions (like wcslen) that come from +// the system's native C library -- which was built with a 4-byte wchar_t! +// It's wasteful to use 4-byte wchar_t strings to carry UTF-16 data, and it's +// entirely improper on those systems where the encoding of wchar_t is defined +// as UTF-32. +// +// Here, we define string16, which is similar to std::wstring but replaces all +// libc functions with custom, 2-byte-char compatible routines. It is capable +// of carrying UTF-16-encoded data. + +#include +#include + +#include "include/base/cef_basictypes.h" + +#if defined(WCHAR_T_IS_UTF16) + +namespace base { + +typedef wchar_t char16; +typedef std::wstring string16; +typedef std::char_traits string16_char_traits; + +} // namespace base + +#elif defined(WCHAR_T_IS_UTF32) + +#include "include/base/cef_macros.h" + +namespace base { + +typedef uint16_t char16; + +// char16 versions of the functions required by string16_char_traits; these +// are based on the wide character functions of similar names ("w" or "wcs" +// instead of "c16"). +int c16memcmp(const char16* s1, const char16* s2, size_t n); +size_t c16len(const char16* s); +const char16* c16memchr(const char16* s, char16 c, size_t n); +char16* c16memmove(char16* s1, const char16* s2, size_t n); +char16* c16memcpy(char16* s1, const char16* s2, size_t n); +char16* c16memset(char16* s, char16 c, size_t n); + +struct string16_char_traits { + typedef char16 char_type; + typedef int int_type; + + // int_type needs to be able to hold each possible value of char_type, and in + // addition, the distinct value of eof(). + COMPILE_ASSERT(sizeof(int_type) > sizeof(char_type), unexpected_type_width); + + typedef std::streamoff off_type; + typedef mbstate_t state_type; + typedef std::fpos pos_type; + + static void assign(char_type& c1, const char_type& c2) { + c1 = c2; + } + + static bool eq(const char_type& c1, const char_type& c2) { + return c1 == c2; + } + static bool lt(const char_type& c1, const char_type& c2) { + return c1 < c2; + } + + static int compare(const char_type* s1, const char_type* s2, size_t n) { + return c16memcmp(s1, s2, n); + } + + static size_t length(const char_type* s) { + return c16len(s); + } + + static const char_type* find(const char_type* s, size_t n, + const char_type& a) { + return c16memchr(s, a, n); + } + + static char_type* move(char_type* s1, const char_type* s2, int_type n) { + return c16memmove(s1, s2, n); + } + + static char_type* copy(char_type* s1, const char_type* s2, size_t n) { + return c16memcpy(s1, s2, n); + } + + static char_type* assign(char_type* s, size_t n, char_type a) { + return c16memset(s, a, n); + } + + static int_type not_eof(const int_type& c) { + return eq_int_type(c, eof()) ? 0 : c; + } + + static char_type to_char_type(const int_type& c) { + return char_type(c); + } + + static int_type to_int_type(const char_type& c) { + return int_type(c); + } + + static bool eq_int_type(const int_type& c1, const int_type& c2) { + return c1 == c2; + } + + static int_type eof() { + return static_cast(EOF); + } +}; + +typedef std::basic_string string16; + +extern std::ostream& operator<<(std::ostream& out, const string16& str); + +// This is required by googletest to print a readable output on test failures. +extern void PrintTo(const string16& str, std::ostream* out); + +} // namespace base + +// The string class will be explicitly instantiated only once, in string16.cc. +// +// std::basic_string<> in GNU libstdc++ contains a static data member, +// _S_empty_rep_storage, to represent empty strings. When an operation such +// as assignment or destruction is performed on a string, causing its existing +// data member to be invalidated, it must not be freed if this static data +// member is being used. Otherwise, it counts as an attempt to free static +// (and not allocated) data, which is a memory error. +// +// Generally, due to C++ template magic, _S_empty_rep_storage will be marked +// as a coalesced symbol, meaning that the linker will combine multiple +// instances into a single one when generating output. +// +// If a string class is used by multiple shared libraries, a problem occurs. +// Each library will get its own copy of _S_empty_rep_storage. When strings +// are passed across a library boundary for alteration or destruction, memory +// errors will result. GNU libstdc++ contains a configuration option, +// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which +// disables the static data member optimization, but it's a good optimization +// and non-STL code is generally at the mercy of the system's STL +// configuration. Fully-dynamic strings are not the default for GNU libstdc++ +// libstdc++ itself or for the libstdc++ installations on the systems we care +// about, such as Mac OS X and relevant flavors of Linux. +// +// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 . +// +// To avoid problems, string classes need to be explicitly instantiated only +// once, in exactly one library. All other string users see it via an "extern" +// declaration. This is precisely how GNU libstdc++ handles +// std::basic_string (string) and std::basic_string (wstring). +// +// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2), +// in which the linker does not fully coalesce symbols when dead code +// stripping is enabled. This bug causes the memory errors described above +// to occur even when a std::basic_string<> does not cross shared library +// boundaries, such as in statically-linked executables. +// +// TODO(mark): File this bug with Apple and update this note with a bug number. + +extern template +class std::basic_string; + +#endif // WCHAR_T_IS_UTF32 + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_STRING16_H_ diff --git a/include/base/cef_template_util.h b/include/base/cef_template_util.h new file mode 100644 index 000000000..dc82548a5 --- /dev/null +++ b/include/base/cef_template_util.h @@ -0,0 +1,192 @@ +// 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. + +#ifndef CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_ +#define CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_ +#pragma once + +#if defined(BASE_TEMPLATE_UTIL_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/template_util.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 // For size_t. + +#include "include/base/cef_build.h" + +namespace base { + +// template definitions from tr1 + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template struct is_pointer : false_type {}; +template struct is_pointer : true_type {}; + +// Member function pointer detection up to four params. Add more as needed +// below. This is built-in to C++ 11, and we can remove this when we switch. +template +struct is_member_function_pointer : false_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + +template +struct is_member_function_pointer : true_type {}; +template +struct is_member_function_pointer : true_type {}; + + +template struct is_same : public false_type {}; +template struct is_same : true_type {}; + +template struct is_array : public false_type {}; +template struct is_array : public true_type {}; +template struct is_array : public true_type {}; + +template struct is_non_const_reference : false_type {}; +template struct is_non_const_reference : true_type {}; +template struct is_non_const_reference : false_type {}; + +template struct is_const : false_type {}; +template struct is_const : true_type {}; + +template struct is_void : false_type {}; +template <> struct is_void : true_type {}; + +namespace internal { + +// Types YesType and NoType are guaranteed such that sizeof(YesType) < +// sizeof(NoType). +typedef char YesType; + +struct NoType { + YesType dummy[2]; +}; + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +struct ConvertHelper { + template + static YesType Test(To); + + template + static NoType Test(...); + + template + static From& Create(); +}; + +// Used to determine if a type is a struct/union/class. Inspired by Boost's +// is_class type_trait implementation. +struct IsClassHelper { + template + static YesType Test(void(C::*)(void)); + + template + static NoType Test(...); +}; + +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +// +// Note that if the type is convertible, this will be a true_type REGARDLESS +// of whether or not the conversion would emit a warning. +template +struct is_convertible + : integral_constant( + internal::ConvertHelper::Create())) == + sizeof(internal::YesType)> { +}; + +template +struct is_class + : integral_constant(0)) == + sizeof(internal::YesType)> { +}; + +template +struct enable_if {}; + +template +struct enable_if { typedef T type; }; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_TEMPLATE_UTIL_H_ diff --git a/include/base/cef_thread_checker.h b/include/base/cef_thread_checker.h new file mode 100644 index 000000000..2fd4f271a --- /dev/null +++ b/include/base/cef_thread_checker.h @@ -0,0 +1,125 @@ +// 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_THREAD_CHECKER_H_ +#define CEF_INCLUDE_BASE_THREAD_CHECKER_H_ +#pragma once + +#if defined(BASE_THREADING_THREAD_CHECKER_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/threading/thread_checker.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. + +// Apart from debug builds, we also enable the thread checker in +// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots +// with this define will get the same level of thread checking as +// debug bots. +// +// Note that this does not perfectly match situations where DCHECK is +// enabled. For example a non-official release build may have +// DCHECK_ALWAYS_ON undefined (and therefore ThreadChecker would be +// disabled) but have DCHECKs enabled at runtime. +#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) +#define ENABLE_THREAD_CHECKER 1 +#else +#define ENABLE_THREAD_CHECKER 0 +#endif + +#include "include/base/internal/cef_thread_checker_impl.h" + +namespace base { + +// Do nothing implementation, for use in release mode. +// +// Note: You should almost always use the ThreadChecker class to get the +// right version for your build configuration. +class ThreadCheckerDoNothing { + public: + bool CalledOnValidThread() const { + return true; + } + + void DetachFromThread() {} +}; + +// ThreadChecker is a helper class used to help verify that some methods of a +// class are called from the same thread. It provides identical functionality to +// base::NonThreadSafe, but it is meant to be held as a member variable, rather +// than inherited from base::NonThreadSafe. +// +// While inheriting from base::NonThreadSafe may give a clear indication about +// the thread-safety of a class, it may also lead to violations of the style +// guide with regard to multiple inheritance. The choice between having a +// ThreadChecker member and inheriting from base::NonThreadSafe should be based +// on whether: +// - Derived classes need to know the thread they belong to, as opposed to +// having that functionality fully encapsulated in the base class. +// - Derived classes should be able to reassign the base class to another +// thread, via DetachFromThread. +// +// If neither of these are true, then having a ThreadChecker member and calling +// CalledOnValidThread is the preferable solution. +// +// Example: +// class MyClass { +// public: +// void Foo() { +// DCHECK(thread_checker_.CalledOnValidThread()); +// ... (do stuff) ... +// } +// +// private: +// ThreadChecker thread_checker_; +// } +// +// In Release mode, CalledOnValidThread will always return true. +#if ENABLE_THREAD_CHECKER +class ThreadChecker : public ThreadCheckerImpl { +}; +#else +class ThreadChecker : public ThreadCheckerDoNothing { +}; +#endif // ENABLE_THREAD_CHECKER + +#undef ENABLE_THREAD_CHECKER + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_THREAD_CHECKER_H_ diff --git a/include/base/cef_thread_collision_warner.h b/include/base/cef_thread_collision_warner.h new file mode 100644 index 000000000..bbc88759c --- /dev/null +++ b/include/base/cef_thread_collision_warner.h @@ -0,0 +1,287 @@ +// 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_THREAD_COLLISION_WARNER_H_ +#define CEF_INCLUDE_BASE_CEF_THREAD_COLLISION_WARNER_H_ +#pragma once + +#if defined(BASE_THREADING_THREAD_COLLISION_WARNER_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/threading/thread_collision_warner.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 "include/base/cef_atomicops.h" +#include "include/base/cef_basictypes.h" +#include "include/base/cef_build.h" +#include "include/base/cef_macros.h" + +// A helper class alongside macros to be used to verify assumptions about thread +// safety of a class. +// +// Example: Queue implementation non thread-safe but still usable if clients +// are synchronized somehow. +// +// In this case the macro DFAKE_SCOPED_LOCK has to be +// used, it checks that if a thread is inside the push/pop then +// noone else is still inside the pop/push +// +// class NonThreadSafeQueue { +// public: +// ... +// void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... } +// int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... } +// ... +// private: +// DFAKE_MUTEX(push_pop_); +// }; +// +// +// Example: Queue implementation non thread-safe but still usable if clients +// are synchronized somehow, it calls a method to "protect" from +// a "protected" method +// +// In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK +// has to be used, it checks that if a thread is inside the push/pop +// then noone else is still inside the pop/push +// +// class NonThreadSafeQueue { +// public: +// void push(int) { +// DFAKE_SCOPED_LOCK(push_pop_); +// ... +// } +// int pop() { +// DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); +// bar(); +// ... +// } +// void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... } +// ... +// private: +// DFAKE_MUTEX(push_pop_); +// }; +// +// +// Example: Queue implementation not usable even if clients are synchronized, +// so only one thread in the class life cycle can use the two members +// push/pop. +// +// In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the +// specified +// critical section the first time a thread enters push or pop, from +// that time on only that thread is allowed to execute push or pop. +// +// class NonThreadSafeQueue { +// public: +// ... +// void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... } +// int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... } +// ... +// private: +// DFAKE_MUTEX(push_pop_); +// }; +// +// +// Example: Class that has to be contructed/destroyed on same thread, it has +// a "shareable" method (with external synchronization) and a not +// shareable method (even with external synchronization). +// +// In this case 3 Critical sections have to be defined +// +// class ExoticClass { +// public: +// ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } +// ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } +// +// void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... } +// void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... } +// ... +// private: +// DFAKE_MUTEX(ctor_dtor_); +// DFAKE_MUTEX(shareable_section_); +// }; + + +#if !defined(NDEBUG) + +// Defines a class member that acts like a mutex. It is used only as a +// verification tool. +#define DFAKE_MUTEX(obj) \ + mutable base::ThreadCollisionWarner obj +// Asserts the call is never called simultaneously in two threads. Used at +// member function scope. +#define DFAKE_SCOPED_LOCK(obj) \ + base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj) +// Asserts the call is never called simultaneously in two threads. Used at +// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks. +#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \ + base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj) +// Asserts the code is always executed in the same thread. +#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \ + base::ThreadCollisionWarner::Check check_##obj(&obj) + +#else + +#define DFAKE_MUTEX(obj) typedef void InternalFakeMutexType##obj +#define DFAKE_SCOPED_LOCK(obj) ((void)0) +#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0) +#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0) + +#endif + +namespace base { + +// The class ThreadCollisionWarner uses an Asserter to notify the collision +// AsserterBase is the interfaces and DCheckAsserter is the default asserter +// used. During the unit tests is used another class that doesn't "DCHECK" +// in case of collision (check thread_collision_warner_unittests.cc) +struct AsserterBase { + virtual ~AsserterBase() {} + virtual void warn() = 0; +}; + +struct DCheckAsserter : public AsserterBase { + virtual ~DCheckAsserter() {} + virtual void warn() OVERRIDE; +}; + +class ThreadCollisionWarner { + public: + // The parameter asserter is there only for test purpose + explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter()) + : valid_thread_id_(0), + counter_(0), + asserter_(asserter) {} + + ~ThreadCollisionWarner() { + delete asserter_; + } + + // This class is meant to be used through the macro + // DFAKE_SCOPED_LOCK_THREAD_LOCKED + // it doesn't leave the critical section, as opposed to ScopedCheck, + // because the critical section being pinned is allowed to be used only + // from one thread + class Check { + public: + explicit Check(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->EnterSelf(); + } + + ~Check() {} + + private: + ThreadCollisionWarner* warner_; + + DISALLOW_COPY_AND_ASSIGN(Check); + }; + + // This class is meant to be used through the macro + // DFAKE_SCOPED_LOCK + class ScopedCheck { + public: + explicit ScopedCheck(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->Enter(); + } + + ~ScopedCheck() { + warner_->Leave(); + } + + private: + ThreadCollisionWarner* warner_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCheck); + }; + + // This class is meant to be used through the macro + // DFAKE_SCOPED_RECURSIVE_LOCK + class ScopedRecursiveCheck { + public: + explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner) + : warner_(warner) { + warner_->EnterSelf(); + } + + ~ScopedRecursiveCheck() { + warner_->Leave(); + } + + private: + ThreadCollisionWarner* warner_; + + DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck); + }; + + private: + // This method stores the current thread identifier and does a DCHECK + // if a another thread has already done it, it is safe if same thread + // calls this multiple time (recursion allowed). + void EnterSelf(); + + // Same as EnterSelf but recursion is not allowed. + void Enter(); + + // Removes the thread_id stored in order to allow other threads to + // call EnterSelf or Enter. + void Leave(); + + // This stores the thread id that is inside the critical section, if the + // value is 0 then no thread is inside. + volatile subtle::Atomic32 valid_thread_id_; + + // Counter to trace how many time a critical section was "pinned" + // (when allowed) in order to unpin it when counter_ reaches 0. + volatile subtle::Atomic32 counter_; + + // Here only for class unit tests purpose, during the test I need to not + // DCHECK but notify the collision with something else. + AsserterBase* asserter_; + + DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner); +}; + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_THREAD_COLLISION_WARNER_H_ diff --git a/include/base/cef_trace_event.h b/include/base/cef_trace_event.h new file mode 100644 index 000000000..a24146cd0 --- /dev/null +++ b/include/base/cef_trace_event.h @@ -0,0 +1,427 @@ +// 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. + +/// +// Trace events are for tracking application performance and resource usage. +// Macros are provided to track: +// Begin and end of function calls +// Counters +// +// Events are issued against categories. Whereas LOG's categories are statically +// defined, TRACE categories are created implicitly with a string. For example: +// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") +// +// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: +// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") +// doSomethingCostly() +// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") +// Note: Our tools can't always determine the correct BEGIN/END pairs unless +// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you +// need them to be in separate scopes. +// +// A common use case is to trace entire function scopes. This issues a trace +// BEGIN and END automatically: +// void doSomethingCostly() { +// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); +// ... +// } +// +// Additional parameters can be associated with an event: +// void doSomethingCostly2(int howMuch) { +// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", +// "howMuch", howMuch); +// ... +// } +// +// The trace system will automatically add to this information the current +// process id, thread id, and a timestamp in microseconds. +// +// To trace an asynchronous procedure such as an IPC send/receive, use +// ASYNC_BEGIN and ASYNC_END: +// [single threaded sender code] +// static int send_count = 0; +// ++send_count; +// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// Send(new MyMessage(send_count)); +// [receive code] +// void OnMyMessage(send_count) { +// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// } +// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. +// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. +// Pointers can be used for the ID parameter, and they will be mangled +// internally so that the same pointer on two different processes will not +// match. For example: +// class MyTracedClass { +// public: +// MyTracedClass() { +// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// } +// ~MyTracedClass() { +// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// } +// } +// +// The trace event also supports counters, which is a way to track a quantity +// as it varies over time. Counters are created with the following macro: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); +// +// Counters are process-specific. The macro itself can be issued from any +// thread, however. +// +// Sometimes, you want to track two counters at once. You can do this with two +// counter macros: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); +// Or you can do it with a combined macro: +// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", +// "bytesPinned", g_myCounterValue[0], +// "bytesAllocated", g_myCounterValue[1]); +// This indicates to the tracing UI that these counters should be displayed +// in a single graph, as a summed area chart. +// +// Since counters are in a global namespace, you may want to disembiguate with a +// unique ID, by using the TRACE_COUNTER_ID* variations. +// +// By default, trace collection is compiled in, but turned off at runtime. +// Collecting trace data is the responsibility of the embedding application. In +// CEF's case, calling BeginTracing will turn on tracing on all active +// processes. +// +// +// Memory scoping note: +// Tracing copies the pointers, not the string content, of the strings passed +// in for category, name, and arg_names. Thus, the following code will cause +// problems: +// char* str = strdup("impprtantName"); +// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! +// free(str); // Trace system now has dangling pointer +// +// To avoid this issue with the |name| and |arg_name| parameters, use the +// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime +// overhead. +// Notes: The category must always be in a long-lived char* (i.e. static const). +// The |arg_values|, when used, are always deep copied with the _COPY +// macros. +// +// +// Thread Safety: +// All macros are thread safe and can be used from any process. +/// + +#ifndef CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ +#define CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ +#pragma once + +#if defined(TRACE_EVENT0) +// Do nothing if the macros provided by this header already exist. +// 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/debug/trace_event.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/internal/cef_trace_event_internal.h" + +// Records a pair of begin and end events called "name" for the current +// scope, with 0, 1 or 2 associated arguments. If the category is not +// enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT0(category, name) \ + cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false); \ + CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) +#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false); \ + CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) +#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val, false); \ + CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) + +// Implementation detail: trace event macros create temporary variable names. +// These macros give each temporary variable a unique name based on the line +// number to prevent name collisions. +#define CEF_INTERNAL_TRACE_EVENT_UID3(a,b) \ + cef_trace_event_unique_##a##b +#define CEF_INTERNAL_TRACE_EVENT_UID2(a,b) \ + CEF_INTERNAL_TRACE_EVENT_UID3(a,b) +#define CEF_INTERNAL_TRACE_EVENT_UID(name_prefix) \ + CEF_INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) + +// Implementation detail: internal macro to end end event when the scope ends. +#define CEF_INTERNAL_TRACE_END_ON_SCOPE_CLOSE(category, name) \ + cef_trace_event::CefTraceEndOnScopeClose \ + CEF_INTERNAL_TRACE_EVENT_UID(profileScope)(category, name) + +// Records a single event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_INSTANT0(category, name) \ + cef_trace_event_instant(category, name, NULL, 0, NULL, 0, false) +#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ + cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, false) +#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, false) +#define TRACE_EVENT_COPY_INSTANT0(category, name) \ + cef_trace_event_instant(category, name, NULL, 0, NULL, 0, true) +#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ + cef_trace_event_instant(category, name, arg1_name, arg1_val, NULL, 0, true) +#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_instant(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, true) + +// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_BEGIN0(category, name) \ + cef_trace_event_begin(category, name, NULL, 0, NULL, 0, false) +#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, false) +#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, false) +#define TRACE_EVENT_COPY_BEGIN0(category, name) \ + cef_trace_event_begin(category, name, NULL, 0, NULL, 0, true) +#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, NULL, 0, true) +#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_begin(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, true) + +// Records a single END event for "name" immediately. If the category +// is not enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_END0(category, name) \ + cef_trace_event_end(category, name, NULL, 0, NULL, 0, false) +#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ + cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, false) +#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, false) +#define TRACE_EVENT_COPY_END0(category, name) \ + cef_trace_event_end(category, name, NULL, 0, NULL, 0, true) +#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ + cef_trace_event_end(category, name, arg1_name, arg1_val, NULL, 0, true) +#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_end(category, name, arg1_name, arg1_val, arg2_name, \ + arg2_val, true) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER1(category, name, value) \ + cef_trace_counter(category, name, NULL, value, NULL, 0, false) +#define TRACE_COPY_COUNTER1(category, name, value) \ + cef_trace_counter(category, name, NULL, value, NULL, 0, true) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ + value2_val, false) +#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + cef_trace_counter(category, name, value1_name, value1_val, value2_name, \ + value2_val, true) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the +// bits will be xored with a hash of the process ID so that the same pointer +// on two different processes will not collide. +#define TRACE_COUNTER_ID1(category, name, id, value) \ + cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, false) +#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ + cef_trace_counter_id(category, name, id, NULL, value, NULL, 0, true) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the +// bits will be xored with a hash of the process ID so that the same pointer +// on two different processes will not collide. +#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + cef_trace_counter_id(category, name, id, value1_name, value1_val, \ + value2_name, value2_val, false) +#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, \ + value1_val, value2_name, value2_val) \ + cef_trace_counter_id(category, name, id, value1_name, value1_val, \ + value2_name, value2_val, true) + + +// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. +// ASYNC events are considered to match if their category, name and id values +// all match. |id| must either be a pointer or an integer value up to 64 +// bits. If it's a pointer, the bits will be xored with a hash of the process +// ID sothat the same pointer on two different processes will not collide. +// An asynchronous operation can consist of multiple phases. The first phase is +// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the +// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. +// An async operation can span threads and processes, but all events in that +// operation must use the same |name| and |id|. Each event can have its own +// args. +#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ + cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, false) +#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ + 0, false) +#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val, false) +#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ + cef_trace_event_async_begin(category, name, id, NULL, 0, NULL, 0, true) +#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, \ + arg1_val) \ + cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, NULL, \ + 0, true) +#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + cef_trace_event_async_begin(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val, true) + +// Records a single ASYNC_STEP_INTO event for |step| immediately. If the +// category is not enabled, then this does nothing. The |name| and |id| must +// match the ASYNC_BEGIN event above. The |step| param identifies this step +// within the async event. This should be called at the beginning of the next +// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any +// ASYNC_STEP_PAST events. +#define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \ + cef_trace_event_async_step_into(category, name, id, step, NULL, 0, false) +#define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, \ + arg1_name, arg1_val) \ + cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ + arg1_val, false) +#define TRACE_EVENT_COPY_ASYNC_STEP_INTO0(category, name, id, step) \ + cef_trace_event_async_step_into(category, name, id, step, NULL, 0, true) +#define TRACE_EVENT_COPY_ASYNC_STEP_INTO1(category, name, id, step, \ + arg1_name, arg1_val) \ + cef_trace_event_async_step_into(category, name, id, step, arg1_name, \ + arg1_val, true) + +// Records a single ASYNC_STEP_PAST event for |step| immediately. If the +// category is not enabled, then this does nothing. The |name| and |id| must +// match the ASYNC_BEGIN event above. The |step| param identifies this step +// within the async event. This should be called at the beginning of the next +// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any +// ASYNC_STEP_INTO events. +#define TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step) \ + cef_trace_event_async_step_past(category, name, id, step, NULL, 0, false) +#define TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, \ + arg1_name, arg1_val) \ + cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ + arg1_val, false) +#define TRACE_EVENT_COPY_ASYNC_STEP_PAST0(category, name, id, step) \ + cef_trace_event_async_step_past(category, name, id, step, NULL, 0, true) +#define TRACE_EVENT_COPY_ASYNC_STEP_PAST1(category, name, id, step, \ + arg1_name, arg1_val) \ + cef_trace_event_async_step_past(category, name, id, step, arg1_name, \ + arg1_val, true) + +// Records a single ASYNC_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_ASYNC_END0(category, name, id) \ + cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, false) +#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ + false) +#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val, false) +#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ + cef_trace_event_async_end(category, name, id, NULL, 0, NULL, 0, true) +#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, \ + arg1_val) \ + cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, NULL, 0, \ + true) +#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, \ + arg1_val, arg2_name, arg2_val) \ + cef_trace_event_async_end(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val, true) + +namespace cef_trace_event { + +// Used by TRACE_EVENTx macro. Do not use directly. +class CefTraceEndOnScopeClose { + public: + CefTraceEndOnScopeClose(const char* category, const char* name) + : category_(category), name_(name) { + } + ~CefTraceEndOnScopeClose() { + cef_trace_event_end(category_, name_, NULL, 0, NULL, 0, false); + } + + private: + const char* category_; + const char* name_; +}; + +} // cef_trace_event + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_TRACE_EVENT_H_ diff --git a/include/base/cef_tuple.h b/include/base/cef_tuple.h new file mode 100644 index 000000000..b33eae9b0 --- /dev/null +++ b/include/base/cef_tuple.h @@ -0,0 +1,1333 @@ +// 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. + +// A Tuple is a generic templatized container, similar in concept to std::pair. +// There are classes Tuple0 to Tuple6, cooresponding to the number of elements +// it contains. The convenient MakeTuple() function takes 0 to 6 arguments, +// and will construct and return the appropriate Tuple object. The functions +// DispatchToMethod and DispatchToFunction take a function pointer or instance +// and method pointer, and unpack a tuple into arguments to the call. +// +// Tuple elements are copied by value, and stored in the tuple. See the unit +// tests for more details of how/when the values are copied. +// +// Example usage: +// // These two methods of creating a Tuple are identical. +// Tuple2 tuple_a(1, "wee"); +// Tuple2 tuple_b = MakeTuple(1, "wee"); +// +// void SomeFunc(int a, const char* b) { } +// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") +// DispatchToFunction( +// &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo") +// +// struct { void SomeMeth(int a, int b, int c) { } } foo; +// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3)); +// // foo->SomeMeth(1, 2, 3); + +#ifndef CEF_INCLUDE_BASE_CEF_TUPLE_H_ +#define CEF_INCLUDE_BASE_CEF_TUPLE_H_ +#pragma once + +#if defined(BASE_TUPLE_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/tuple.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_bind_helpers.h" + +// Traits ---------------------------------------------------------------------- +// +// A simple traits class for tuple arguments. +// +// ValueType: the bare, nonref version of a type (same as the type for nonrefs). +// RefType: the ref version of a type (same as the type for refs). +// ParamType: what type to pass to functions (refs should not be constified). + +template +struct TupleTraits { + typedef P ValueType; + typedef P& RefType; + typedef const P& ParamType; +}; + +template +struct TupleTraits { + typedef P ValueType; + typedef P& RefType; + typedef P& ParamType; +}; + +template +struct TupleTypes { }; + +// Tuple ----------------------------------------------------------------------- +// +// This set of classes is useful for bundling 0 or more heterogeneous data types +// into a single variable. The advantage of this is that it greatly simplifies +// function objects that need to take an arbitrary number of parameters; see +// RunnableMethod and IPC::MessageWithTuple. +// +// Tuple0 is supplied to act as a 'void' type. It can be used, for example, +// when dispatching to a function that accepts no arguments (see the +// Dispatchers below). +// Tuple1 is rarely useful. One such use is when A is non-const ref that you +// want filled by the dispatchee, and the tuple is merely a container for that +// output (a "tier"). See MakeRefTuple and its usages. + +struct Tuple0 { + typedef Tuple0 ValueTuple; + typedef Tuple0 RefTuple; + typedef Tuple0 ParamTuple; +}; + +template +struct Tuple1 { + public: + typedef A TypeA; + + Tuple1() {} + explicit Tuple1(typename TupleTraits::ParamType a) : a(a) {} + + A a; +}; + +template +struct Tuple2 { + public: + typedef A TypeA; + typedef B TypeB; + + Tuple2() {} + Tuple2(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b) + : a(a), b(b) { + } + + A a; + B b; +}; + +template +struct Tuple3 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + + Tuple3() {} + Tuple3(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c) + : a(a), b(b), c(c){ + } + + A a; + B b; + C c; +}; + +template +struct Tuple4 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + + Tuple4() {} + Tuple4(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d) + : a(a), b(b), c(c), d(d) { + } + + A a; + B b; + C c; + D d; +}; + +template +struct Tuple5 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + + Tuple5() {} + Tuple5(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e) + : a(a), b(b), c(c), d(d), e(e) { + } + + A a; + B b; + C c; + D d; + E e; +}; + +template +struct Tuple6 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + + Tuple6() {} + Tuple6(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f) + : a(a), b(b), c(c), d(d), e(e), f(f) { + } + + A a; + B b; + C c; + D d; + E e; + F f; +}; + +template +struct Tuple7 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + typedef G TypeG; + + Tuple7() {} + Tuple7(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f, + typename TupleTraits::ParamType g) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g) { + } + + A a; + B b; + C c; + D d; + E e; + F f; + G g; +}; + +template +struct Tuple8 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + typedef G TypeG; + typedef H TypeH; + + Tuple8() {} + Tuple8(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f, + typename TupleTraits::ParamType g, + typename TupleTraits::ParamType h) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) { + } + + A a; + B b; + C c; + D d; + E e; + F f; + G g; + H h; +}; + +// Tuple types ---------------------------------------------------------------- +// +// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the +// definitions of class types the tuple takes as parameters. + +template <> +struct TupleTypes< Tuple0 > { + typedef Tuple0 ValueTuple; + typedef Tuple0 RefTuple; + typedef Tuple0 ParamTuple; +}; + +template +struct TupleTypes< Tuple1 > { + typedef Tuple1::ValueType> ValueTuple; + typedef Tuple1::RefType> RefTuple; + typedef Tuple1::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple2 > { + typedef Tuple2::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple2::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple2::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple3 > { + typedef Tuple3::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple3::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple3::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple4 > { + typedef Tuple4::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple4::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple4::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple5 > { + typedef Tuple5::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple5::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple5::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple6 > { + typedef Tuple6::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple6::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple6::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple7 > { + typedef Tuple7::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple7::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple7::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple8 > { + typedef Tuple8::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple8::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple8::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +// Tuple creators ------------------------------------------------------------- +// +// Helper functions for constructing tuples while inferring the template +// argument types. + +inline Tuple0 MakeTuple() { + return Tuple0(); +} + +template +inline Tuple1 MakeTuple(const A& a) { + return Tuple1(a); +} + +template +inline Tuple2 MakeTuple(const A& a, const B& b) { + return Tuple2(a, b); +} + +template +inline Tuple3 MakeTuple(const A& a, const B& b, const C& c) { + return Tuple3(a, b, c); +} + +template +inline Tuple4 MakeTuple(const A& a, const B& b, const C& c, + const D& d) { + return Tuple4(a, b, c, d); +} + +template +inline Tuple5 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e) { + return Tuple5(a, b, c, d, e); +} + +template +inline Tuple6 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e, const F& f) { + return Tuple6(a, b, c, d, e, f); +} + +template +inline Tuple7 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e, const F& f, + const G& g) { + return Tuple7(a, b, c, d, e, f, g); +} + +template +inline Tuple8 MakeTuple(const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f, + const G& g, const H& h) { + return Tuple8(a, b, c, d, e, f, g, h); +} + +// The following set of helpers make what Boost refers to as "Tiers" - a tuple +// of references. + +template +inline Tuple1 MakeRefTuple(A& a) { + return Tuple1(a); +} + +template +inline Tuple2 MakeRefTuple(A& a, B& b) { + return Tuple2(a, b); +} + +template +inline Tuple3 MakeRefTuple(A& a, B& b, C& c) { + return Tuple3(a, b, c); +} + +template +inline Tuple4 MakeRefTuple(A& a, B& b, C& c, D& d) { + return Tuple4(a, b, c, d); +} + +template +inline Tuple5 MakeRefTuple(A& a, B& b, C& c, D& d, E& e) { + return Tuple5(a, b, c, d, e); +} + +template +inline Tuple6 MakeRefTuple(A& a, B& b, C& c, D& d, E& e, + F& f) { + return Tuple6(a, b, c, d, e, f); +} + +template +inline Tuple7 MakeRefTuple(A& a, B& b, C& c, D& d, + E& e, F& f, G& g) { + return Tuple7(a, b, c, d, e, f, g); +} + +template +inline Tuple8 MakeRefTuple(A& a, B& b, C& c, + D& d, E& e, F& f, + G& g, H& h) { + return Tuple8(a, b, c, d, e, f, g, h); +} + +// Dispatchers ---------------------------------------------------------------- +// +// Helper functions that call the given method on an object, with the unpacked +// tuple arguments. Notice that they all have the same number of arguments, +// so you need only write: +// DispatchToMethod(object, &Object::method, args); +// This is very useful for templated dispatchers, since they don't need to know +// what type |args| is. + +// Non-Static Dispatchers with no out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) { + (obj->*method)(); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a)); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple2& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple7& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple8& arg) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g), + base::internal::UnwrapTraits::Unwrap(arg.h)); +} + +// Static Dispatchers with no out params. + +template +inline void DispatchToFunction(Function function, const Tuple0& arg) { + (*function)(); +} + +template +inline void DispatchToFunction(Function function, const A& arg) { + (*function)(arg); +} + +template +inline void DispatchToFunction(Function function, const Tuple1& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a)); +} + +template +inline void DispatchToFunction(Function function, const Tuple2& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); +} + +template +inline void DispatchToFunction(Function function, const Tuple3& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); +} + +template +inline void DispatchToFunction(Function function, + const Tuple4& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); +} + +template +inline void DispatchToFunction(Function function, + const Tuple5& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); +} + +template +inline void DispatchToFunction(Function function, + const Tuple6& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); +} + +template +inline void DispatchToFunction(Function function, + const Tuple7& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g)); +} + +template +inline void DispatchToFunction(Function function, + const Tuple8& arg) { + (*function)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f), + base::internal::UnwrapTraits::Unwrap(arg.g), + base::internal::UnwrapTraits::Unwrap(arg.h)); +} + +// Dispatchers with 0 out param (as a Tuple0). + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple0& arg, Tuple0*) { + (obj->*method)(); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg)); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple1& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a)); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple2& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e)); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& arg, Tuple0*) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(arg.a), + base::internal::UnwrapTraits::Unwrap(arg.b), + base::internal::UnwrapTraits::Unwrap(arg.c), + base::internal::UnwrapTraits::Unwrap(arg.d), + base::internal::UnwrapTraits::Unwrap(arg.e), + base::internal::UnwrapTraits::Unwrap(arg.f)); +} + +// Dispatchers with 1 out param. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple1* out) { + (obj->*method)(&out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple1* out) { + (obj->*method)(in, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple1* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a); +} + +// Dispatchers with 2 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple2* out) { + (obj->*method)(&out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple2* out) { + (obj->*method)(in, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple2* out) { + (obj->*method)( + base::internal::UnwrapTraits::Unwrap(in.a), &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple2* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple2* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple2* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple2* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple2* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b); +} + +// Dispatchers with 3 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple3* out) { + (obj->*method)(&out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple3* out) { + (obj->*method)(in, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple3* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b, + &out->c); +} + +// Dispatchers with 4 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple4* out) { + (obj->*method)(&out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c, + &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple4* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b, + &out->c, + &out->d); +} + +// Dispatchers with 5 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple5* out) { + (obj->*method)(&out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple5* out) { + (obj->*method)(base::internal::UnwrapTraits::Unwrap(in.a), + base::internal::UnwrapTraits::Unwrap(in.b), + base::internal::UnwrapTraits::Unwrap(in.c), + base::internal::UnwrapTraits::Unwrap(in.d), + base::internal::UnwrapTraits::Unwrap(in.e), + base::internal::UnwrapTraits::Unwrap(in.f), + &out->a, + &out->b, + &out->c, + &out->d, + &out->e); +} + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_TUPLE_H_ diff --git a/include/base/cef_weak_ptr.h b/include/base/cef_weak_ptr.h new file mode 100644 index 000000000..6d8e2dbe7 --- /dev/null +++ b/include/base/cef_weak_ptr.h @@ -0,0 +1,382 @@ +// 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. + +// Weak pointers are pointers to an object that do not affect its lifetime, +// and which may be invalidated (i.e. reset to NULL) by the object, or its +// owner, at any time, most commonly when the object is about to be deleted. + +// Weak pointers are useful when an object needs to be accessed safely by one +// or more objects other than its owner, and those callers can cope with the +// object vanishing and e.g. tasks posted to it being silently dropped. +// Reference-counting such an object would complicate the ownership graph and +// make it harder to reason about the object's lifetime. + +// EXAMPLE: +// +// class Controller { +// public: +// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } +// void WorkComplete(const Result& result) { ... } +// private: +// // Member variables should appear before the WeakPtrFactory, to ensure +// // that any WeakPtrs to Controller are invalidated before its members +// // variable's destructors are executed, rendering them invalid. +// WeakPtrFactory weak_factory_; +// }; +// +// class Worker { +// public: +// static void StartNew(const WeakPtr& controller) { +// Worker* worker = new Worker(controller); +// // Kick off asynchronous processing... +// } +// private: +// Worker(const WeakPtr& controller) +// : controller_(controller) {} +// void DidCompleteAsynchronousProcessing(const Result& result) { +// if (controller_) +// controller_->WorkComplete(result); +// } +// WeakPtr controller_; +// }; +// +// With this implementation a caller may use SpawnWorker() to dispatch multiple +// Workers and subsequently delete the Controller, without waiting for all +// Workers to have completed. + +// ------------------------- IMPORTANT: Thread-safety ------------------------- + +// Weak pointers may be passed safely between threads, but must always be +// dereferenced and invalidated on the same thread otherwise checking the +// pointer would be racey. +// +// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory +// is dereferenced, the factory and its WeakPtrs become bound to the calling +// thread, and cannot be dereferenced or invalidated on any other thread. Bound +// WeakPtrs can still be handed off to other threads, e.g. to use to post tasks +// back to object on the bound thread. +// +// Invalidating the factory's WeakPtrs un-binds it from the thread, allowing it +// to be passed for a different thread to use or delete it. + +#ifndef CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_ +#define CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_ +#pragma once + +#if defined(BASE_MEMORY_WEAK_PTR_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/memory/weak_ptr.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_basictypes.h" +#include "include/base/cef_logging.h" +#include "include/base/cef_ref_counted.h" +#include "include/base/cef_template_util.h" +#include "include/base/cef_thread_checker.h" + +namespace base { + +template class SupportsWeakPtr; +template class WeakPtr; + +namespace internal { +// These classes are part of the WeakPtr implementation. +// DO NOT USE THESE CLASSES DIRECTLY YOURSELF. + +class WeakReference { + public: + // Although Flag is bound to a specific thread, it may be deleted from another + // via base::WeakPtr::~WeakPtr(). + class Flag : public RefCountedThreadSafe { + public: + Flag(); + + void Invalidate(); + bool IsValid() const; + + private: + friend class base::RefCountedThreadSafe; + + ~Flag(); + + // The current Chromium implementation uses SequenceChecker instead of + // ThreadChecker to support SequencedWorkerPools. CEF does not yet expose + // the concept of SequencedWorkerPools. + ThreadChecker thread_checker_; + bool is_valid_; + }; + + WeakReference(); + explicit WeakReference(const Flag* flag); + ~WeakReference(); + + bool is_valid() const; + + private: + scoped_refptr flag_; +}; + +class WeakReferenceOwner { + public: + WeakReferenceOwner(); + ~WeakReferenceOwner(); + + WeakReference GetRef() const; + + bool HasRefs() const { + return flag_.get() && !flag_->HasOneRef(); + } + + void Invalidate(); + + private: + mutable scoped_refptr flag_; +}; + +// This class simplifies the implementation of WeakPtr's type conversion +// constructor by avoiding the need for a public accessor for ref_. A +// WeakPtr cannot access the private members of WeakPtr, so this +// base class gives us a way to access ref_ in a protected fashion. +class WeakPtrBase { + public: + WeakPtrBase(); + ~WeakPtrBase(); + + protected: + explicit WeakPtrBase(const WeakReference& ref); + + WeakReference ref_; +}; + +// This class provides a common implementation of common functions that would +// otherwise get instantiated separately for each distinct instantiation of +// SupportsWeakPtr<>. +class SupportsWeakPtrBase { + public: + // A safe static downcast of a WeakPtr to WeakPtr. This + // conversion will only compile if there is exists a Base which inherits + // from SupportsWeakPtr. See base::AsWeakPtr() below for a helper + // function that makes calling this easier. + template + static WeakPtr StaticAsWeakPtr(Derived* t) { + typedef + is_convertible convertible; + COMPILE_ASSERT(convertible::value, + AsWeakPtr_argument_inherits_from_SupportsWeakPtr); + return AsWeakPtrImpl(t, *t); + } + + private: + // This template function uses type inference to find a Base of Derived + // which is an instance of SupportsWeakPtr. We can then safely + // static_cast the Base* to a Derived*. + template + static WeakPtr AsWeakPtrImpl( + Derived* t, const SupportsWeakPtr&) { + WeakPtr ptr = t->Base::AsWeakPtr(); + return WeakPtr(ptr.ref_, static_cast(ptr.ptr_)); + } +}; + +} // namespace internal + +template class WeakPtrFactory; + +// The WeakPtr class holds a weak reference to |T*|. +// +// This class is designed to be used like a normal pointer. You should always +// null-test an object of this class before using it or invoking a method that +// may result in the underlying object being destroyed. +// +// EXAMPLE: +// +// class Foo { ... }; +// WeakPtr foo; +// if (foo) +// foo->method(); +// +template +class WeakPtr : public internal::WeakPtrBase { + public: + WeakPtr() : ptr_(NULL) { + } + + // Allow conversion from U to T provided U "is a" T. Note that this + // is separate from the (implicit) copy constructor. + template + WeakPtr(const WeakPtr& other) : WeakPtrBase(other), ptr_(other.ptr_) { + } + + T* get() const { return ref_.is_valid() ? ptr_ : NULL; } + + T& operator*() const { + DCHECK(get() != NULL); + return *get(); + } + T* operator->() const { + DCHECK(get() != NULL); + return get(); + } + + // Allow WeakPtr to be used in boolean expressions, but not + // implicitly convertible to a real bool (which is dangerous). + // + // Note that this trick is only safe when the == and != operators + // are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2" + // will compile but do the wrong thing (i.e., convert to Testable + // and then do the comparison). + private: + typedef T* WeakPtr::*Testable; + + public: + operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; } + + void reset() { + ref_ = internal::WeakReference(); + ptr_ = NULL; + } + + private: + // Explicitly declare comparison operators as required by the bool + // trick, but keep them private. + template bool operator==(WeakPtr const&) const; + template bool operator!=(WeakPtr const&) const; + + friend class internal::SupportsWeakPtrBase; + template friend class WeakPtr; + friend class SupportsWeakPtr; + friend class WeakPtrFactory; + + WeakPtr(const internal::WeakReference& ref, T* ptr) + : WeakPtrBase(ref), + ptr_(ptr) { + } + + // This pointer is only valid when ref_.is_valid() is true. Otherwise, its + // value is undefined (as opposed to NULL). + T* ptr_; +}; + +// A class may be composed of a WeakPtrFactory and thereby +// control how it exposes weak pointers to itself. This is helpful if you only +// need weak pointers within the implementation of a class. This class is also +// useful when working with primitive types. For example, you could have a +// WeakPtrFactory that is used to pass around a weak reference to a bool. +template +class WeakPtrFactory { + public: + explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { + } + + ~WeakPtrFactory() { + ptr_ = NULL; + } + + WeakPtr GetWeakPtr() { + DCHECK(ptr_); + return WeakPtr(weak_reference_owner_.GetRef(), ptr_); + } + + // Call this method to invalidate all existing weak pointers. + void InvalidateWeakPtrs() { + DCHECK(ptr_); + weak_reference_owner_.Invalidate(); + } + + // Call this method to determine if any weak pointers exist. + bool HasWeakPtrs() const { + DCHECK(ptr_); + return weak_reference_owner_.HasRefs(); + } + + private: + internal::WeakReferenceOwner weak_reference_owner_; + T* ptr_; + DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); +}; + +// A class may extend from SupportsWeakPtr to let others take weak pointers to +// it. This avoids the class itself implementing boilerplate to dispense weak +// pointers. However, since SupportsWeakPtr's destructor won't invalidate +// weak pointers to the class until after the derived class' members have been +// destroyed, its use can lead to subtle use-after-destroy issues. +template +class SupportsWeakPtr : public internal::SupportsWeakPtrBase { + public: + SupportsWeakPtr() {} + + WeakPtr AsWeakPtr() { + return WeakPtr(weak_reference_owner_.GetRef(), static_cast(this)); + } + + protected: + ~SupportsWeakPtr() {} + + private: + internal::WeakReferenceOwner weak_reference_owner_; + DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr); +}; + +// Helper function that uses type deduction to safely return a WeakPtr +// when Derived doesn't directly extend SupportsWeakPtr, instead it +// extends a Base that extends SupportsWeakPtr. +// +// EXAMPLE: +// class Base : public base::SupportsWeakPtr {}; +// class Derived : public Base {}; +// +// Derived derived; +// base::WeakPtr ptr = base::AsWeakPtr(&derived); +// +// Note that the following doesn't work (invalid type conversion) since +// Derived::AsWeakPtr() is WeakPtr SupportsWeakPtr::AsWeakPtr(), +// and there's no way to safely cast WeakPtr to WeakPtr at +// the caller. +// +// base::WeakPtr ptr = derived.AsWeakPtr(); // Fails. + +template +WeakPtr AsWeakPtr(Derived* t) { + return internal::SupportsWeakPtrBase::StaticAsWeakPtr(t); +} + +} // namespace base + +#endif // !BUILDING_CEF_SHARED + +#endif // CEF_INCLUDE_BASE_CEF_WEAK_PTR_H_ diff --git a/include/base/internal/cef_atomicops_atomicword_compat.h b/include/base/internal/cef_atomicops_atomicword_compat.h new file mode 100644 index 000000000..985f0f9b9 --- /dev/null +++ b/include/base/internal/cef_atomicops_atomicword_compat.h @@ -0,0 +1,126 @@ +// 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. + +// Do not include this header file directly. Use base/cef_atomicops.h +// instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_ + +// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32, +// which in turn means int. On some LP32 platforms, intptr_t is an int, but +// on others, it's a long. When AtomicWord and Atomic32 are based on different +// fundamental types, their pointers are incompatible. +// +// This file defines function overloads to allow both AtomicWord and Atomic32 +// data to be used with this interface. +// +// On LP64 platforms, AtomicWord and Atomic64 are both always long, +// so this problem doesn't occur. + +#if !defined(ARCH_CPU_64_BITS) + +namespace base { +namespace subtle { + +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Acquire_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return base::subtle::Release_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store( + reinterpret_cast(ptr), value); +} + +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Acquire_Store( + reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return base::subtle::Release_Store( + reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return base::subtle::Acquire_Load( + reinterpret_cast(ptr)); +} + +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { + return base::subtle::Release_Load( + reinterpret_cast(ptr)); +} + +} // namespace base::subtle +} // namespace base + +#endif // !defined(ARCH_CPU_64_BITS) + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_ATOMICWORD_COMPAT_H_ diff --git a/include/base/internal/cef_atomicops_mac.h b/include/base/internal/cef_atomicops_mac.h new file mode 100644 index 000000000..9f268dd67 --- /dev/null +++ b/include/base/internal/cef_atomicops_mac.h @@ -0,0 +1,223 @@ +// 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. + +// Do not include this header file directly. Use base/cef_atomicops.h +// instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_ + +#include + +namespace base { +namespace subtle { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32(increment, const_cast(ptr)); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32Barrier(increment, const_cast(ptr)); +} + +inline void MemoryBarrier() { + OSMemoryBarrier(); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#ifdef __LP64__ + +// 64-bit implementation on 64-bit platform + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64(increment, reinterpret_cast(ptr)); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64Barrier(increment, + reinterpret_cast(ptr)); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Barrier( + old_value, new_value, reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + // The lib kern interface does not distinguish between + // Acquire and Release memory barriers; they are equivalent. + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +#endif // defined(__LP64__) + +} // namespace base::subtle +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_MAC_H_ diff --git a/include/base/internal/cef_atomicops_x86_gcc.h b/include/base/internal/cef_atomicops_x86_gcc.h new file mode 100644 index 000000000..0e2139d95 --- /dev/null +++ b/include/base/internal/cef_atomicops_x86_gcc.h @@ -0,0 +1,265 @@ +// 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. + +// Do not include this header file directly. Use base/cef_atomicops.h +// instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_ + +// This struct is not part of the public API of this module; clients may not +// use it. +// Features of this x86. Values may not be correct before main() is run, +// but are set conservatively. +struct AtomicOps_x86CPUFeatureStruct { + bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence + // after acquire compare-and-swap. +}; +extern struct AtomicOps_x86CPUFeatureStruct + AtomicOps_Internalx86CPUFeatures; + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +namespace base { +namespace subtle { + +// 32-bit low-level operations on any platform. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev; + __asm__ __volatile__("lock; cmpxchgl %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + return temp + increment; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + __asm__ __volatile__("mfence" : : : "memory"); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ATOMICOPS_COMPILER_BARRIER(); + *ptr = value; // An x86 store acts as a release barrier. + // See comments in Atomic64 version of Release_Store(), below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. + // See comments in Atomic64 version of Release_Store(), below. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(__x86_64__) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + __asm__ __volatile__("lock; cmpxchgq %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + return temp + increment; +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ATOMICOPS_COMPILER_BARRIER(); + + *ptr = value; // An x86 store acts as a release barrier + // for current AMD/Intel chips as of Jan 2008. + // See also Acquire_Load(), below. + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm + // + // x86 stores/loads fail to act as barriers for a few instructions (clflush + // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are + // not generated by the compiler, and are rare. Users of these instructions + // need to know about cache behaviour in any case since all of these involve + // either flushing cache lines or non-temporal cache hints. +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, + // for current AMD/Intel chips as of Jan 2008. + // See also Release_Store(), above. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +#endif // defined(__x86_64__) + +} // namespace base::subtle +} // namespace base + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_ diff --git a/include/base/internal/cef_atomicops_x86_msvc.h b/include/base/internal/cef_atomicops_x86_msvc.h new file mode 100644 index 000000000..12bb0f468 --- /dev/null +++ b/include/base/internal/cef_atomicops_x86_msvc.h @@ -0,0 +1,224 @@ +// Copyright (c) 2008 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. + +// Do not include this header file directly. Use base/cef_atomicops.h +// instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_ + +#include + +#include + +#include "include/base/cef_macros.h" + +#if 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 { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + LONG result = _InterlockedCompareExchange( + reinterpret_cast(ptr), + static_cast(new_value), + static_cast(old_value)); + return static_cast(result); +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + LONG result = _InterlockedExchange( + reinterpret_cast(ptr), + static_cast(new_value)); + return static_cast(result); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return _InterlockedExchangeAdd( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +#if !(defined(_MSC_VER) && _MSC_VER >= 1400) +#error "We require at least vs2005 for MemoryBarrier" +#endif +inline void MemoryBarrier() { +#if defined(ARCH_CPU_64_BITS) + // See #undef and note at the top of this file. + __faststorefence(); +#else + // We use MemoryBarrier from WinNT.h + ::MemoryBarrier(); +#endif +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + // See comments in Atomic64 version of Release_Store() below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(_WIN64) + +// 64-bit low-level operations on 64-bit platform. + +COMPILE_ASSERT(sizeof(Atomic64) == sizeof(PVOID), atomic_word_is_atomic); + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + PVOID result = InterlockedCompareExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value), reinterpret_cast(old_value)); + return reinterpret_cast(result); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + PVOID result = InterlockedExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value)); + return reinterpret_cast(result); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return InterlockedExchangeAdd64( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + + +#endif // defined(_WIN64) + +} // namespace base::subtle +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_MSVC_H_ diff --git a/include/base/internal/cef_bind_internal.h b/include/base/internal/cef_bind_internal.h new file mode 100644 index 000000000..725405a05 --- /dev/null +++ b/include/base/internal/cef_bind_internal.h @@ -0,0 +1,2811 @@ +// 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. + +// Do not include this header file directly. Use base/cef_bind.h instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ + +#include "include/base/cef_bind_helpers.h" +#include "include/base/cef_build.h" +#include "include/base/cef_template_util.h" +#include "include/base/cef_weak_ptr.h" +#include "include/base/internal/cef_callback_internal.h" +#include "include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h" + +#if defined(OS_WIN) +#include "include/base/internal/cef_bind_internal_win.h" +#endif + +namespace base { +namespace internal { + +// See base/callback.h for user documentation. +// +// +// CONCEPTS: +// Runnable -- A type (really a type class) that has a single Run() method +// and a RunType typedef that corresponds to the type of Run(). +// A Runnable can declare that it should treated like a method +// call by including a typedef named IsMethod. The value of +// this typedef is NOT inspected, only the existence. When a +// Runnable declares itself a method, Bind() will enforce special +// refcounting + WeakPtr handling semantics for the first +// parameter which is expected to be an object. +// Functor -- A copyable type representing something that should be called. +// All function pointers, Callback<>, and Runnables are functors +// even if the invocation syntax differs. +// RunType -- A function type (as opposed to function _pointer_ type) for +// a Run() function. Usually just a convenience typedef. +// (Bound)ArgsType -- A function type that is being (ab)used to store the +// types of set of arguments. The "return" type is always +// void here. We use this hack so that we do not need +// a new type name for each arity of type. (eg., +// BindState1, BindState2). This makes forward +// declarations and friending much much easier. +// +// Types: +// RunnableAdapter<> -- Wraps the various "function" pointer types into an +// object that adheres to the Runnable interface. +// There are |3*ARITY| RunnableAdapter types. +// FunctionTraits<> -- Type traits that unwrap a function signature into a +// a set of easier to use typedefs. Used mainly for +// compile time asserts. +// There are |ARITY| FunctionTraits types. +// ForceVoidReturn<> -- Helper class for translating function signatures to +// equivalent forms with a "void" return type. +// There are |ARITY| ForceVoidReturn types. +// FunctorTraits<> -- Type traits used determine the correct RunType and +// RunnableType for a Functor. This is where function +// signature adapters are applied. +// There are |ARITY| ForceVoidReturn types. +// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable +// type class that represents the underlying Functor. +// There are |O(1)| MakeRunnable types. +// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// Handle the differing syntaxes needed for WeakPtr<> support, +// and for ignoring return values. This is separate from +// Invoker to avoid creating multiple version of Invoker<> +// which grows at O(n^2) with the arity. +// There are |k*ARITY| InvokeHelper types. +// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// There are |(ARITY^2 + ARITY)/2| Invoketypes. +// BindState<> -- Stores the curried parameters, and is the main entry point +// into the Bind() system, doing most of the type resolution. +// There are ARITY BindState types. + +// RunnableAdapter<> +// +// The RunnableAdapter<> templates provide a uniform interface for invoking +// a function pointer, method pointer, or const method pointer. The adapter +// exposes a Run() method with an appropriate signature. Using this wrapper +// allows for writing code that supports all three pointer types without +// undue repetition. Without it, a lot of code would need to be repeated 3 +// times. +// +// For method pointers and const method pointers the first argument to Run() +// is considered to be the received of the method. This is similar to STL's +// mem_fun(). +// +// This class also exposes a RunType typedef that is the function type of the +// Run() function. +// +// If and only if the wrapper contains a method or const method pointer, an +// IsMethod typedef is exposed. The existence of this typedef (NOT the value) +// marks that the wrapper should be considered a method wrapper. + +template +class RunnableAdapter; + +// Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(*function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (*function_)(); +}; + +// Method: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)()) + : method_(method) { + } + + R Run(T* object) { + return (object->*method_)(); + } + + private: + R (T::*method_)(); +}; + +// Const Method: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)() const) + : method_(method) { + } + + R Run(const T* object) { + return (object->*method_)(); + } + + private: + R (T::*method_)() const; +}; + +// Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(*function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(CallbackForward(a1)); + } + + private: + R (*function_)(A1); +}; + +// Method: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1) { + return (object->*method_)(CallbackForward(a1)); + } + + private: + R (T::*method_)(A1); +}; + +// Const Method: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1) { + return (object->*method_)(CallbackForward(a1)); + } + + private: + R (T::*method_)(A1) const; +}; + +// Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(*function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (*function_)(A1, A2); +}; + +// Method: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (T::*method_)(A1, A2); +}; + +// Const Method: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2)); + } + + private: + R (T::*method_)(A1, A2) const; +}; + +// Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(*function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (*function_)(A1, A2, A3); +}; + +// Method: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (T::*method_)(A1, A2, A3); +}; + +// Const Method: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } + + private: + R (T::*method_)(A1, A2, A3) const; +}; + +// Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (*function_)(A1, A2, A3, A4); +}; + +// Method: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (T::*method_)(A1, A2, A3, A4); +}; + +// Const Method: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } + + private: + R (T::*method_)(A1, A2, A3, A4) const; +}; + +// Function: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5); +}; + +// Method: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5); +}; + +// Const Method: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5) const; +}; + +// Function: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5, A6); +}; + +// Method: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6); +}; + +// Const Method: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6) const; +}; + +// Function: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return function_(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (*function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Method: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Const Method: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return (object->*method_)(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7) const; +}; + + +// FunctionTraits<> +// +// Breaks a function signature apart into typedefs for easier introspection. +template +struct FunctionTraits; + +template +struct FunctionTraits { + typedef R ReturnType; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; +}; + +template +struct FunctionTraits { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; + typedef A7 A7Type; +}; + + +// ForceVoidReturn<> +// +// Set of templates that support forcing the function return type to void. +template +struct ForceVoidReturn; + +template +struct ForceVoidReturn { + typedef void(RunType)(); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5, A6); +}; + +template +struct ForceVoidReturn { + typedef void(RunType)(A1, A2, A3, A4, A5, A6, A7); +}; + + +// FunctorTraits<> +// +// See description at top of file. +template +struct FunctorTraits { + typedef RunnableAdapter RunnableType; + typedef typename RunnableType::RunType RunType; +}; + +template +struct FunctorTraits > { + typedef typename FunctorTraits::RunnableType RunnableType; + typedef typename ForceVoidReturn< + typename RunnableType::RunType>::RunType RunType; +}; + +template +struct FunctorTraits > { + typedef Callback RunnableType; + typedef typename Callback::RunType RunType; +}; + + +// MakeRunnable<> +// +// Converts a passed in functor to a RunnableType using type inference. + +template +typename FunctorTraits::RunnableType MakeRunnable(const T& t) { + return RunnableAdapter(t); +} + +template +typename FunctorTraits::RunnableType +MakeRunnable(const IgnoreResultHelper& t) { + return MakeRunnable(t.functor_); +} + +template +const typename FunctorTraits >::RunnableType& +MakeRunnable(const Callback& t) { + DCHECK(!t.is_null()); + return t; +} + + +// InvokeHelper<> +// +// There are 3 logical InvokeHelper<> specializations: normal, void-return, +// WeakCalls. +// +// The normal type just calls the underlying runnable. +// +// We need a InvokeHelper to handle void return types in order to support +// IgnoreResult(). Normally, if the Runnable's RunType had a void return, +// the template system would just accept "return functor.Run()" ignoring +// the fact that a void function is being used with return. This piece of +// sugar breaks though when the Runnable's RunType is not void. Thus, we +// need a partial specialization to change the syntax to drop the "return" +// from the invocation call. +// +// WeakCalls similarly need special syntax that is applied to the first +// argument to check if they should no-op themselves. +template +struct InvokeHelper; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable) { + return runnable.Run(); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable) { + runnable.Run(); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1) { + return runnable.Run(CallbackForward(a1)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1) { + runnable.Run(CallbackForward(a1)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get()); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2) { + runnable.Run(CallbackForward(a1), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5, A6 a6) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6)); + } +}; + +template +struct InvokeHelper { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6, A7 a7) { + return runnable.Run(CallbackForward(a1), CallbackForward(a2), + CallbackForward(a3), CallbackForward(a4), CallbackForward(a5), + CallbackForward(a6), CallbackForward(a7)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6, A7 a7) { + runnable.Run(CallbackForward(a1), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); + } +}; + +template +struct InvokeHelper { + static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, A2 a2, A3 a3, + A4 a4, A5 a5, A6 a6, A7 a7) { + if (!weak_ptr.get()) { + return; + } + runnable.Run(weak_ptr.get(), CallbackForward(a2), CallbackForward(a3), + CallbackForward(a4), CallbackForward(a5), CallbackForward(a6), + CallbackForward(a7)); + } +}; + +#if !defined(_MSC_VER) + +template +struct InvokeHelper { + // WeakCalls are only supported for functions with a void return type. + // Otherwise, the function result would be undefined if the the WeakPtr<> + // is invalidated. + COMPILE_ASSERT(is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); +}; + +#endif + +// Invoker<> +// +// See description at the top of the file. +template +struct Invoker; + +// Arity 0 -> 0. +template +struct Invoker<0, StorageType, R()> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper + ::MakeItSo(storage->runnable_); + } +}; + +// Arity 1 -> 1. +template +struct Invoker<0, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1)> + ::MakeItSo(storage->runnable_, CallbackForward(x1)); + } +}; + +// Arity 1 -> 0. +template +struct Invoker<1, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1)); + } +}; + +// Arity 2 -> 2. +template +struct Invoker<0, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 2 -> 1. +template +struct Invoker<1, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 2 -> 0. +template +struct Invoker<2, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2)); + } +}; + +// Arity 3 -> 3. +template +struct Invoker<0, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 2. +template +struct Invoker<1, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 1. +template +struct Invoker<2, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 3 -> 0. +template +struct Invoker<3, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3)); + } +}; + +// Arity 4 -> 4. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 3. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 2. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 1. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 4 -> 0. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4)); + } +}; + +// Arity 5 -> 5. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 4. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 3. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 2. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 1. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 5 -> 0. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5)); + } +}; + +// Arity 6 -> 6. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 5. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 4. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 3. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 2. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5, + typename CallbackParamTraits::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 1. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x6) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper::ForwardType x6)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 6 -> 0. +template +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6)); + } +}; + +// Arity 7 -> 7. +template +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper::ForwardType x1, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 6. +template +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper::ForwardType x2, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 5. +template +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper::ForwardType x3, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 4. +template +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper::ForwardType x4, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 3. +template +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper::ForwardType x5, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 2. +template +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x6, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper::ForwardType x6, + typename CallbackParamTraits::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 1. +template +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits::ForwardType); + + typedef R(UnboundRunType)(X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits::ForwardType x7) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + return InvokeHelper::ForwardType x7)> + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + +// Arity 7 -> 0. +template +struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + typename Bound7UnwrapTraits::ForwardType x7 = + Bound7UnwrapTraits::Unwrap(storage->p7_); + return InvokeHelper + ::MakeItSo(storage->runnable_, CallbackForward(x1), + CallbackForward(x2), CallbackForward(x3), + CallbackForward(x4), CallbackForward(x5), + CallbackForward(x6), CallbackForward(x7)); + } +}; + + +// BindState<> +// +// This stores all the state passed into Bind() and is also where most +// of the template resolution magic occurs. +// +// Runnable is the functor we are binding arguments to. +// RunType is type of the Run() function that the Invoker<> should use. +// Normally, this is the same as the RunType of the Runnable, but it can +// be different if an adapter like IgnoreResult() has been used. +// +// BoundArgsType contains the storage type for all the bound arguments by +// (ab)using a function type. +template +struct BindState; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef false_type IsWeakCall; + typedef Invoker<0, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + explicit BindState(const Runnable& runnable) + : runnable_(runnable) { + } + + virtual ~BindState() { } + + RunnableType runnable_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<1, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1) + : runnable_(runnable), + p1_(p1) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<2, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2) + : runnable_(runnable), + p1_(p1), + p2_(p2) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<3, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<4, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<5, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<6, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + typedef UnwrapTraits Bound6UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5, const P6& p6) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; + P6 p6_; +}; + +template +struct BindState : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod::value, P1> IsWeakCall; + typedef Invoker<7, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits Bound1UnwrapTraits; + typedef UnwrapTraits Bound2UnwrapTraits; + typedef UnwrapTraits Bound3UnwrapTraits; + typedef UnwrapTraits Bound4UnwrapTraits; + typedef UnwrapTraits Bound5UnwrapTraits; + typedef UnwrapTraits Bound6UnwrapTraits; + typedef UnwrapTraits Bound7UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5, const P6& p6, const P7& p7) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6), + p7_(p7) { + MaybeRefcount::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; + P6 p6_; + P7 p7_; +}; + +} // namespace internal +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_H_ diff --git a/include/base/internal/cef_bind_internal_win.h b/include/base/internal/cef_bind_internal_win.h new file mode 100644 index 000000000..9fde64649 --- /dev/null +++ b/include/base/internal/cef_bind_internal_win.h @@ -0,0 +1,390 @@ +// 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. + +// Do not include this header file directly. Use base/cef_bind.h instead. + +// Specializations of RunnableAdapter<> for Windows specific calling +// conventions. Please see base/bind_internal.h for more info. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_ + +// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all +// the same as __cdecl which would turn the following specializations into +// multiple definitions. +#if !defined(ARCH_CPU_X86_64) + +namespace base { +namespace internal { + +template +class RunnableAdapter; + +// __stdcall Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(__stdcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (__stdcall *function_)(); +}; + +// __fastcall Function: Arity 0. +template +class RunnableAdapter { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(__fastcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (__fastcall *function_)(); +}; + +// __stdcall Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(__stdcall *function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(a1); + } + + private: + R (__stdcall *function_)(A1); +}; + +// __fastcall Function: Arity 1. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(__fastcall *function)(A1)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1) { + return function_(a1); + } + + private: + R (__fastcall *function_)(A1); +}; + +// __stdcall Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__stdcall *function_)(A1, A2); +}; + +// __fastcall Function: Arity 2. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__fastcall *function_)(A1, A2); +}; + +// __stdcall Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__stdcall *function_)(A1, A2, A3); +}; + +// __fastcall Function: Arity 3. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__fastcall *function_)(A1, A2, A3); +}; + +// __stdcall Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4); +}; + +// __fastcall Function: Arity 4. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4); +}; + +// __stdcall Function: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5); +}; + +// __fastcall Function: Arity 5. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5); +}; + +// __stdcall Function: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return function_(a1, a2, a3, a4, a5, a6); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5, A6); +}; + +// __fastcall Function: Arity 6. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6) { + return function_(a1, a2, a3, a4, a5, a6); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5, A6); +}; + +// __stdcall Function: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return function_(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// __fastcall Function: Arity 7. +template +class RunnableAdapter { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits::ForwardType a1, + typename CallbackParamTraits::ForwardType a2, + typename CallbackParamTraits::ForwardType a3, + typename CallbackParamTraits::ForwardType a4, + typename CallbackParamTraits::ForwardType a5, + typename CallbackParamTraits::ForwardType a6, + typename CallbackParamTraits::ForwardType a7) { + return function_(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +} // namespace internal +} // namespace base + +#endif // !defined(ARCH_CPU_X86_64) + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_BIND_INTERNAL_WIN_H_ diff --git a/include/base/internal/cef_callback_internal.h b/include/base/internal/cef_callback_internal.h new file mode 100644 index 000000000..34a1b5f44 --- /dev/null +++ b/include/base/internal/cef_callback_internal.h @@ -0,0 +1,205 @@ +// 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. + +// Do not include this header file directly. Use base/cef_bind.h or +// base/cef_callback.h instead. + +// This file contains utility functions and classes that help the +// implementation, and management of the Callback objects. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_ + +#include + +#include "include/base/cef_ref_counted.h" +#include "include/base/cef_scoped_ptr.h" + +template +class ScopedVector; + +namespace base { +namespace internal { + +// BindStateBase is used to provide an opaque handle that the Callback +// class can use to represent a function object with bound arguments. It +// behaves as an existential type that is used by a corresponding +// DoInvoke function to perform the function execution. This allows +// us to shield the Callback class from the types of the bound argument via +// "type erasure." +class BindStateBase : public RefCountedThreadSafe { + protected: + friend class RefCountedThreadSafe; + virtual ~BindStateBase() {} +}; + +// Holds the Callback methods that don't require specialization to reduce +// template bloat. +class CallbackBase { + public: + // Returns true if Callback is null (doesn't refer to anything). + bool is_null() const; + + // Returns the Callback into an uninitialized state. + void Reset(); + + protected: + // In C++, it is safe to cast function pointers to function pointers of + // another type. It is not okay to use void*. We create a InvokeFuncStorage + // that that can store our function pointer, and then cast it back to + // the original type on usage. + typedef void(*InvokeFuncStorage)(void); + + // Returns true if this callback equals |other|. |other| may be null. + bool Equals(const CallbackBase& other) const; + + // Allow initializing of |bind_state_| via the constructor to avoid default + // initialization of the scoped_refptr. We do not also initialize + // |polymorphic_invoke_| here because doing a normal assignment in the + // derived Callback templates makes for much nicer compiler errors. + explicit CallbackBase(BindStateBase* bind_state); + + // Force the destructor to be instantiated inside this translation unit so + // that our subclasses will not get inlined versions. Avoids more template + // bloat. + ~CallbackBase(); + + scoped_refptr bind_state_; + InvokeFuncStorage polymorphic_invoke_; +}; + +// A helper template to determine if given type is non-const move-only-type, +// i.e. if a value of the given type should be passed via .Pass() in a +// destructive way. +template struct IsMoveOnlyType { + template + static YesType Test(const typename U::MoveOnlyTypeForCPP03*); + + template + static NoType Test(...); + + static const bool value = sizeof(Test(0)) == sizeof(YesType) && + !is_const::value; +}; + +// This is a typetraits object that's used to take an argument type, and +// extract a suitable type for storing and forwarding arguments. +// +// In particular, it strips off references, and converts arrays to +// pointers for storage; and it avoids accidentally trying to create a +// "reference of a reference" if the argument is a reference type. +// +// This array type becomes an issue for storage because we are passing bound +// parameters by const reference. In this case, we end up passing an actual +// array type in the initializer list which C++ does not allow. This will +// break passing of C-string literals. +template ::value> +struct CallbackParamTraits { + typedef const T& ForwardType; + typedef T StorageType; +}; + +// The Storage should almost be impossible to trigger unless someone manually +// specifies type of the bind parameters. However, in case they do, +// this will guard against us accidentally storing a reference parameter. +// +// The ForwardType should only be used for unbound arguments. +template +struct CallbackParamTraits { + typedef T& ForwardType; + typedef T StorageType; +}; + +// Note that for array types, we implicitly add a const in the conversion. This +// means that it is not possible to bind array arguments to functions that take +// a non-const pointer. Trying to specialize the template based on a "const +// T[n]" does not seem to match correctly, so we are stuck with this +// restriction. +template +struct CallbackParamTraits { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// See comment for CallbackParamTraits. +template +struct CallbackParamTraits { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// Parameter traits for movable-but-not-copyable scopers. +// +// Callback<>/Bind() understands movable-but-not-copyable semantics where +// the type cannot be copied but can still have its state destructively +// transferred (aka. moved) to another instance of the same type by calling a +// helper function. When used with Bind(), this signifies transferal of the +// object's state to the target function. +// +// For these types, the ForwardType must not be a const reference, or a +// reference. A const reference is inappropriate, and would break const +// correctness, because we are implementing a destructive move. A non-const +// reference cannot be used with temporaries which means the result of a +// function or a cast would not be usable with Callback<> or Bind(). +template +struct CallbackParamTraits { + typedef T ForwardType; + typedef T StorageType; +}; + +// CallbackForward() is a very limited simulation of C++11's std::forward() +// used by the Callback/Bind system for a set of movable-but-not-copyable +// types. It is needed because forwarding a movable-but-not-copyable +// argument to another function requires us to invoke the proper move +// operator to create a rvalue version of the type. The supported types are +// whitelisted below as overloads of the CallbackForward() function. The +// default template compiles out to be a no-op. +// +// In C++11, std::forward would replace all uses of this function. However, it +// is impossible to implement a general std::forward with C++11 due to a lack +// of rvalue references. +// +// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to +// simulate std::forward() and forward the result of one Callback as a +// parameter to another callback. This is to support Callbacks that return +// the movable-but-not-copyable types whitelisted above. +template +typename enable_if::value, T>::type& CallbackForward(T& t) { + return t; +} + +template +typename enable_if::value, T>::type CallbackForward(T& t) { + return t.Pass(); +} + +} // namespace internal +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_CALLBACK_INTERNAL_H_ diff --git a/include/base/internal/cef_lock_impl.h b/include/base/internal/cef_lock_impl.h new file mode 100644 index 000000000..bd708c20d --- /dev/null +++ b/include/base/internal/cef_lock_impl.h @@ -0,0 +1,87 @@ +// 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. + +// Do not include this header file directly. Use base/cef_lock.h instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_ + +#include "include/base/cef_build.h" + +#if defined(OS_WIN) +#include +#elif defined(OS_POSIX) +#include +#endif + +#include "include/base/cef_macros.h" + +namespace base { +namespace internal { + +// This class implements the underlying platform-specific spin-lock mechanism +// used for the Lock class. Most users should not use LockImpl directly, but +// should instead use Lock. +class LockImpl { + public: +#if defined(OS_WIN) + typedef CRITICAL_SECTION NativeHandle; +#elif defined(OS_POSIX) + typedef pthread_mutex_t NativeHandle; +#endif + + LockImpl(); + ~LockImpl(); + + // If the lock is not held, take it and return true. If the lock is already + // held by something else, immediately return false. + bool Try(); + + // Take the lock, blocking until it is available if necessary. + void Lock(); + + // Release the lock. This must only be called by the lock's holder: after + // a successful call to Try, or a call to Lock. + void Unlock(); + + // Return the native underlying lock. + // TODO(awalker): refactor lock and condition variables so that this is + // unnecessary. + NativeHandle* native_handle() { return &native_handle_; } + + private: + NativeHandle native_handle_; + + DISALLOW_COPY_AND_ASSIGN(LockImpl); +}; + +} // namespace internal +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_LOCK_IMPL_H_ diff --git a/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h b/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h new file mode 100644 index 000000000..c643a9ecd --- /dev/null +++ b/include/base/internal/cef_raw_scoped_refptr_mismatch_checker.h @@ -0,0 +1,154 @@ +// 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. + +// Do not include this header file directly. Use base/cef_callback.h instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#define CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ + +#include "include/base/cef_build.h" +#include "include/base/cef_ref_counted.h" +#include "include/base/cef_template_util.h" +#include "include/base/cef_tuple.h" + +// It is dangerous to post a task with a T* argument where T is a subtype of +// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the +// object may already have been deleted since it was not held with a +// scoped_refptr. Example: http://crbug.com/27191 +// The following set of traits are designed to generate a compile error +// whenever this antipattern is attempted. + +namespace base { + +namespace internal { + +template +struct NeedsScopedRefptrButGetsRawPtr { +#if defined(OS_WIN) + enum { + value = base::false_type::value + }; +#else + enum { + // Human readable translation: you needed to be a scoped_refptr if you are a + // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) + // type. + value = (is_pointer::value && + (is_convertible::value || + is_convertible::value)) + }; +#endif +}; + +template +struct ParamsUseScopedRefptrCorrectly { + enum { value = 0 }; +}; + +template <> +struct ParamsUseScopedRefptrCorrectly { + enum { value = 1 }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !NeedsScopedRefptrButGetsRawPtr::value }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +template +struct ParamsUseScopedRefptrCorrectly > { + enum { value = !(NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value || + NeedsScopedRefptrButGetsRawPtr::value) }; +}; + +} // namespace internal + +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_CEF_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/include/base/internal/cef_thread_checker_impl.h b/include/base/internal/cef_thread_checker_impl.h new file mode 100644 index 000000000..e74bcf8ac --- /dev/null +++ b/include/base/internal/cef_thread_checker_impl.h @@ -0,0 +1,70 @@ +// 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. + +// Do not include this header file directly. Use base/cef_thread_checker.h +// instead. + +#ifndef CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_ +#define CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_ + +#include "include/base/cef_lock.h" +#include "include/base/cef_platform_thread.h" + +namespace base { + +// Real implementation of ThreadChecker, for use in debug mode, or +// for temporary use in release mode (e.g. to CHECK on a threading issue +// seen only in the wild). +// +// Note: You should almost always use the ThreadChecker class to get the +// right version for your build configuration. +class ThreadCheckerImpl { + public: + ThreadCheckerImpl(); + ~ThreadCheckerImpl(); + + bool CalledOnValidThread() const; + + // Changes the thread that is checked for in CalledOnValidThread. This may + // be useful when an object may be created on one thread and then used + // exclusively on another thread. + void DetachFromThread(); + + private: + void EnsureThreadIdAssigned() const; + + mutable base::Lock lock_; + // This is mutable so that CalledOnValidThread can set it. + // It's guarded by |lock_|. + mutable PlatformThreadRef valid_thread_id_; +}; + +} // namespace base + +#endif // CEF_INCLUDE_BASE_INTERNAL_THREAD_CHECKER_IMPL_H_ diff --git a/include/capi/cef_app_capi.h b/include/capi/cef_app_capi.h new file mode 100644 index 000000000..06e0da245 --- /dev/null +++ b/include/capi/cef_app_capi.h @@ -0,0 +1,182 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_process_handler_capi.h" +#include "include/capi/cef_command_line_capi.h" +#include "include/capi/cef_render_process_handler_capi.h" +#include "include/capi/cef_resource_bundle_handler_capi.h" +#include "include/capi/cef_scheme_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_app_t; + +/// +// Implement this structure to provide handler implementations. Methods will be +// called by the process and/or thread indicated. +/// +typedef struct _cef_app_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Provides an opportunity to view and/or modify command-line arguments before + // processing by CEF and Chromium. The |process_type| value will be NULL for + // the browser process. Do not keep a reference to the cef_command_line_t + // object passed to this function. The CefSettings.command_line_args_disabled + // value can be used to start with an NULL command-line object. Any values + // specified in CefSettings that equate to command-line arguments will be set + // before this function is called. Be cautious when using this function to + // modify command-line arguments for non-browser processes as this may result + // in undefined behavior including crashes. + /// + void (CEF_CALLBACK *on_before_command_line_processing)( + struct _cef_app_t* self, const cef_string_t* process_type, + struct _cef_command_line_t* command_line); + + /// + // Provides an opportunity to register custom schemes. Do not keep a reference + // to the |registrar| object. This function is called on the main thread for + // each process and the registered schemes should be the same across all + // processes. + /// + void (CEF_CALLBACK *on_register_custom_schemes)(struct _cef_app_t* self, + struct _cef_scheme_registrar_t* registrar); + + /// + // Return the handler for resource bundle events. If + // CefSettings.pack_loading_disabled is true (1) a handler must be returned. + // If no handler is returned resources will be loaded from pack files. This + // function is called by the browser and render processes on multiple threads. + /// + struct _cef_resource_bundle_handler_t* ( + CEF_CALLBACK *get_resource_bundle_handler)(struct _cef_app_t* self); + + /// + // Return the handler for functionality specific to the browser process. This + // function is called on multiple threads in the browser process. + /// + struct _cef_browser_process_handler_t* ( + CEF_CALLBACK *get_browser_process_handler)(struct _cef_app_t* self); + + /// + // Return the handler for functionality specific to the render process. This + // function is called on the render process main thread. + /// + struct _cef_render_process_handler_t* ( + CEF_CALLBACK *get_render_process_handler)(struct _cef_app_t* self); +} cef_app_t; + + +/// +// This function should be called from the application entry point function to +// execute a secondary process. It can be used to run secondary processes from +// the browser client executable (default behavior) or from a separate +// executable specified by the CefSettings.browser_subprocess_path value. If +// called for the browser process (identified by no "type" command-line value) +// it will return immediately with a value of -1. If called for a recognized +// secondary process it will block until the process should exit and then return +// the process exit code. The |application| parameter may be NULL. The +// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see +// cef_sandbox_win.h for details). +/// +CEF_EXPORT int cef_execute_process(const struct _cef_main_args_t* args, + cef_app_t* application, void* windows_sandbox_info); + +/// +// This function should be called on the main application thread to initialize +// the CEF browser process. The |application| parameter may be NULL. A return +// value of true (1) indicates that it succeeded and false (0) indicates that it +// failed. The |windows_sandbox_info| parameter is only used on Windows and may +// be NULL (see cef_sandbox_win.h for details). +/// +CEF_EXPORT int cef_initialize(const struct _cef_main_args_t* args, + const struct _cef_settings_t* settings, cef_app_t* application, + void* windows_sandbox_info); + +/// +// This function should be called on the main application thread to shut down +// the CEF browser process before the application exits. +/// +CEF_EXPORT void cef_shutdown(); + +/// +// Perform a single iteration of CEF message loop processing. This function is +// used to integrate the CEF message loop into an existing application message +// loop. Care must be taken to balance performance against excessive CPU usage. +// This function should only be called on the main application thread and only +// if cef_initialize() is called with a CefSettings.multi_threaded_message_loop +// value of false (0). This function will not block. +/// +CEF_EXPORT void cef_do_message_loop_work(); + +/// +// Run the CEF message loop. Use this function instead of an application- +// provided message loop to get the best balance between performance and CPU +// usage. This function should only be called on the main application thread and +// only if cef_initialize() is called with a +// CefSettings.multi_threaded_message_loop value of false (0). This function +// will block until a quit message is received by the system. +/// +CEF_EXPORT void cef_run_message_loop(); + +/// +// Quit the CEF message loop that was started by calling cef_run_message_loop(). +// This function should only be called on the main application thread and only +// if cef_run_message_loop() was used. +/// +CEF_EXPORT void cef_quit_message_loop(); + +/// +// Set to true (1) before calling Windows APIs like TrackPopupMenu that enter a +// modal message loop. Set to false (0) after exiting the modal message loop. +/// +CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_ diff --git a/include/capi/cef_auth_callback_capi.h b/include/capi/cef_auth_callback_capi.h new file mode 100644 index 000000000..e62131ab3 --- /dev/null +++ b/include/capi/cef_auth_callback_capi.h @@ -0,0 +1,75 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_AUTH_CALLBACK_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_AUTH_CALLBACK_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure used for asynchronous continuation of authentication +// requests. +/// +typedef struct _cef_auth_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the authentication request. + /// + void (CEF_CALLBACK *cont)(struct _cef_auth_callback_t* self, + const cef_string_t* username, const cef_string_t* password); + + /// + // Cancel the authentication request. + /// + void (CEF_CALLBACK *cancel)(struct _cef_auth_callback_t* self); +} cef_auth_callback_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_AUTH_CALLBACK_CAPI_H_ diff --git a/include/capi/cef_base_capi.h b/include/capi/cef_base_capi.h new file mode 100644 index 000000000..edeef3c0e --- /dev/null +++ b/include/capi/cef_base_capi.h @@ -0,0 +1,89 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_CAPI_CEF_BASE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_BASE_CAPI_H_ + +#include + +#include "include/internal/cef_export.h" +#include "include/internal/cef_string.h" +#include "include/internal/cef_string_list.h" +#include "include/internal/cef_string_map.h" +#include "include/internal/cef_string_multimap.h" +#include "include/internal/cef_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// Structure defining the reference count implementation functions. All +// framework structures must include the cef_base_t structure first. +/// +typedef struct _cef_base_t { + /// + // Size of the data structure. + /// + size_t size; + + /// + // Called to increment the reference count for the object. Should be called + // for every new copy of a pointer to a given object. + /// + void (CEF_CALLBACK *add_ref)(struct _cef_base_t* self); + + /// + // Called to decrement the reference count for the object. If the reference + // count falls to 0 the object should self-delete. Returns true (1) if the + // resulting reference count is 0. + /// + int (CEF_CALLBACK *release)(struct _cef_base_t* self); + + /// + // Returns true (1) if the current reference count is 1. + /// + int (CEF_CALLBACK *has_one_ref)(struct _cef_base_t* self); +} cef_base_t; + + +// Check that the structure |s|, which is defined with a cef_base_t member named +// |base|, is large enough to contain the specified member |f|. +#define CEF_MEMBER_EXISTS(s, f) \ + ((intptr_t)&((s)->f) - (intptr_t)(s) + sizeof((s)->f) <= (s)->base.size) + +#define CEF_MEMBER_MISSING(s, f) (!CEF_MEMBER_EXISTS(s, f) || !((s)->f)) + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_BASE_CAPI_H_ diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h new file mode 100644 index 000000000..23274630b --- /dev/null +++ b/include/capi/cef_browser_capi.h @@ -0,0 +1,557 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_drag_data_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_process_message_capi.h" +#include "include/capi/cef_request_context_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_browser_host_t; +struct _cef_client_t; + +/// +// Structure used to represent a browser window. When used in the browser +// process the functions of this structure may be called on any thread unless +// otherwise indicated in the comments. When used in the render process the +// functions of this structure may only be called on the main thread. +/// +typedef struct _cef_browser_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the browser host object. This function can only be called in the + // browser process. + /// + struct _cef_browser_host_t* (CEF_CALLBACK *get_host)( + struct _cef_browser_t* self); + + /// + // Returns true (1) if the browser can navigate backwards. + /// + int (CEF_CALLBACK *can_go_back)(struct _cef_browser_t* self); + + /// + // Navigate backwards. + /// + void (CEF_CALLBACK *go_back)(struct _cef_browser_t* self); + + /// + // Returns true (1) if the browser can navigate forwards. + /// + int (CEF_CALLBACK *can_go_forward)(struct _cef_browser_t* self); + + /// + // Navigate forwards. + /// + void (CEF_CALLBACK *go_forward)(struct _cef_browser_t* self); + + /// + // Returns true (1) if the browser is currently loading. + /// + int (CEF_CALLBACK *is_loading)(struct _cef_browser_t* self); + + /// + // Reload the current page. + /// + void (CEF_CALLBACK *reload)(struct _cef_browser_t* self); + + /// + // Reload the current page ignoring any cached data. + /// + void (CEF_CALLBACK *reload_ignore_cache)(struct _cef_browser_t* self); + + /// + // Stop loading the page. + /// + void (CEF_CALLBACK *stop_load)(struct _cef_browser_t* self); + + /// + // Returns the globally unique identifier for this browser. + /// + int (CEF_CALLBACK *get_identifier)(struct _cef_browser_t* self); + + /// + // Returns true (1) if this object is pointing to the same handle as |that| + // object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_browser_t* self, + struct _cef_browser_t* that); + + /// + // Returns true (1) if the window is a popup window. + /// + int (CEF_CALLBACK *is_popup)(struct _cef_browser_t* self); + + /// + // Returns true (1) if a document has been loaded in the browser. + /// + int (CEF_CALLBACK *has_document)(struct _cef_browser_t* self); + + /// + // Returns the main (top-level) frame for the browser window. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_main_frame)( + struct _cef_browser_t* self); + + /// + // Returns the focused frame for the browser window. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_focused_frame)( + struct _cef_browser_t* self); + + /// + // Returns the frame with the specified identifier, or NULL if not found. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_frame_byident)( + struct _cef_browser_t* self, int64 identifier); + + /// + // Returns the frame with the specified name, or NULL if not found. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_frame)(struct _cef_browser_t* self, + const cef_string_t* name); + + /// + // Returns the number of frames that currently exist. + /// + size_t (CEF_CALLBACK *get_frame_count)(struct _cef_browser_t* self); + + /// + // Returns the identifiers of all existing frames. + /// + void (CEF_CALLBACK *get_frame_identifiers)(struct _cef_browser_t* self, + size_t* identifiersCount, int64* identifiers); + + /// + // Returns the names of all existing frames. + /// + void (CEF_CALLBACK *get_frame_names)(struct _cef_browser_t* self, + cef_string_list_t names); + + // + // Send a message to the specified |target_process|. Returns true (1) if the + // message was sent successfully. + /// + int (CEF_CALLBACK *send_process_message)(struct _cef_browser_t* self, + cef_process_id_t target_process, + struct _cef_process_message_t* message); +} cef_browser_t; + + +/// +// Callback structure for cef_browser_host_t::RunFileDialog. The functions of +// this structure will be called on the browser process UI thread. +/// +typedef struct _cef_run_file_dialog_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called asynchronously after the file dialog is dismissed. If the selection + // was successful |file_paths| will be a single value or a list of values + // depending on the dialog mode. If the selection was cancelled |file_paths| + // will be NULL. + /// + void (CEF_CALLBACK *cont)(struct _cef_run_file_dialog_callback_t* self, + struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths); +} cef_run_file_dialog_callback_t; + + +/// +// Structure used to represent the browser process aspects of a browser window. +// The functions of this structure can only be called in the browser process. +// They may be called on any thread in that process unless otherwise indicated +// in the comments. +/// +typedef struct _cef_browser_host_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the hosted browser object. + /// + struct _cef_browser_t* (CEF_CALLBACK *get_browser)( + struct _cef_browser_host_t* self); + + /// + // Request that the browser close. The JavaScript 'onbeforeunload' event will + // be fired. If |force_close| is false (0) the event handler, if any, will be + // allowed to prompt the user and the user can optionally cancel the close. If + // |force_close| is true (1) the prompt will not be displayed and the close + // will proceed. Results in a call to cef_life_span_handler_t::do_close() if + // the event handler allows the close or if |force_close| is true (1). See + // cef_life_span_handler_t::do_close() documentation for additional usage + // information. + /// + void (CEF_CALLBACK *close_browser)(struct _cef_browser_host_t* self, + int force_close); + + /// + // Set whether the browser is focused. + /// + void (CEF_CALLBACK *set_focus)(struct _cef_browser_host_t* self, int focus); + + /// + // Set whether the window containing the browser is visible + // (minimized/unminimized, app hidden/unhidden, etc). Only used on Mac OS X. + /// + void (CEF_CALLBACK *set_window_visibility)(struct _cef_browser_host_t* self, + int visible); + + /// + // Retrieve the window handle for this browser. + /// + cef_window_handle_t (CEF_CALLBACK *get_window_handle)( + struct _cef_browser_host_t* self); + + /// + // Retrieve the window handle of the browser that opened this browser. Will + // return NULL for non-popup windows. This function can be used in combination + // with custom handling of modal windows. + /// + cef_window_handle_t (CEF_CALLBACK *get_opener_window_handle)( + struct _cef_browser_host_t* self); + + /// + // Returns the client for this browser. + /// + struct _cef_client_t* (CEF_CALLBACK *get_client)( + struct _cef_browser_host_t* self); + + /// + // Returns the request context for this browser. + /// + struct _cef_request_context_t* (CEF_CALLBACK *get_request_context)( + struct _cef_browser_host_t* self); + + /// + // Get the current zoom level. The default zoom level is 0.0. This function + // can only be called on the UI thread. + /// + double (CEF_CALLBACK *get_zoom_level)(struct _cef_browser_host_t* self); + + /// + // Change the zoom level to the specified value. Specify 0.0 to reset the zoom + // level. If called on the UI thread the change will be applied immediately. + // Otherwise, the change will be applied asynchronously on the UI thread. + /// + void (CEF_CALLBACK *set_zoom_level)(struct _cef_browser_host_t* self, + double zoomLevel); + + /// + // Call to run a file chooser dialog. Only a single file chooser dialog may be + // pending at any given time. |mode| represents the type of dialog to display. + // |title| to the title to be used for the dialog and may be NULL to show the + // default title ("Open" or "Save" depending on the mode). |default_file_name| + // is the default file name to select in the dialog. |accept_types| is a list + // of valid lower-cased MIME types or file extensions specified in an input + // element and is used to restrict selectable files to such types. |callback| + // will be executed after the dialog is dismissed or immediately if another + // dialog is already pending. The dialog will be initiated asynchronously on + // the UI thread. + /// + void (CEF_CALLBACK *run_file_dialog)(struct _cef_browser_host_t* self, + cef_file_dialog_mode_t mode, const cef_string_t* title, + const cef_string_t* default_file_name, cef_string_list_t accept_types, + struct _cef_run_file_dialog_callback_t* callback); + + /// + // Download the file at |url| using cef_download_handler_t. + /// + void (CEF_CALLBACK *start_download)(struct _cef_browser_host_t* self, + const cef_string_t* url); + + /// + // Print the current browser contents. + /// + void (CEF_CALLBACK *print)(struct _cef_browser_host_t* self); + + /// + // Search for |searchText|. |identifier| can be used to have multiple searches + // running simultaniously. |forward| indicates whether to search forward or + // backward within the page. |matchCase| indicates whether the search should + // be case-sensitive. |findNext| indicates whether this is the first request + // or a follow-up. + /// + void (CEF_CALLBACK *find)(struct _cef_browser_host_t* self, int identifier, + const cef_string_t* searchText, int forward, int matchCase, + int findNext); + + /// + // Cancel all searches that are currently going on. + /// + void (CEF_CALLBACK *stop_finding)(struct _cef_browser_host_t* self, + int clearSelection); + + /// + // Open developer tools in its own window. + /// + void (CEF_CALLBACK *show_dev_tools)(struct _cef_browser_host_t* self, + const struct _cef_window_info_t* windowInfo, + struct _cef_client_t* client, + const struct _cef_browser_settings_t* settings); + + /// + // Explicitly close the developer tools window if one exists for this browser + // instance. + /// + void (CEF_CALLBACK *close_dev_tools)(struct _cef_browser_host_t* self); + + /// + // Set whether mouse cursor change is disabled. + /// + void (CEF_CALLBACK *set_mouse_cursor_change_disabled)( + struct _cef_browser_host_t* self, int disabled); + + /// + // Returns true (1) if mouse cursor change is disabled. + /// + int (CEF_CALLBACK *is_mouse_cursor_change_disabled)( + struct _cef_browser_host_t* self); + + /// + // Returns true (1) if window rendering is disabled. + /// + int (CEF_CALLBACK *is_window_rendering_disabled)( + struct _cef_browser_host_t* self); + + /// + // Notify the browser that the widget has been resized. The browser will first + // call cef_render_handler_t::GetViewRect to get the new size and then call + // cef_render_handler_t::OnPaint asynchronously with the updated regions. This + // function is only used when window rendering is disabled. + /// + void (CEF_CALLBACK *was_resized)(struct _cef_browser_host_t* self); + + /// + // Notify the browser that it has been hidden or shown. Layouting and + // cef_render_handler_t::OnPaint notification will stop when the browser is + // hidden. This function is only used when window rendering is disabled. + /// + void (CEF_CALLBACK *was_hidden)(struct _cef_browser_host_t* self, int hidden); + + /// + // Send a notification to the browser that the screen info has changed. The + // browser will then call cef_render_handler_t::GetScreenInfo to update the + // screen information with the new values. This simulates moving the webview + // window from one display to another, or changing the properties of the + // current display. This function is only used when window rendering is + // disabled. + /// + void (CEF_CALLBACK *notify_screen_info_changed)( + struct _cef_browser_host_t* self); + + /// + // Invalidate the view. The browser will call cef_render_handler_t::OnPaint + // asynchronously. This function is only used when window rendering is + // disabled. + /// + void (CEF_CALLBACK *invalidate)(struct _cef_browser_host_t* self, + cef_paint_element_type_t type); + + /// + // Send a key event to the browser. + /// + void (CEF_CALLBACK *send_key_event)(struct _cef_browser_host_t* self, + const struct _cef_key_event_t* event); + + /// + // Send a mouse click event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. + /// + void (CEF_CALLBACK *send_mouse_click_event)(struct _cef_browser_host_t* self, + const struct _cef_mouse_event_t* event, cef_mouse_button_type_t type, + int mouseUp, int clickCount); + + /// + // Send a mouse move event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. + /// + void (CEF_CALLBACK *send_mouse_move_event)(struct _cef_browser_host_t* self, + const struct _cef_mouse_event_t* event, int mouseLeave); + + /// + // Send a mouse wheel event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. The |deltaX| and |deltaY| + // values represent the movement delta in the X and Y directions respectively. + // In order to scroll inside select popups with window rendering disabled + // cef_render_handler_t::GetScreenPoint should be implemented properly. + /// + void (CEF_CALLBACK *send_mouse_wheel_event)(struct _cef_browser_host_t* self, + const struct _cef_mouse_event_t* event, int deltaX, int deltaY); + + /// + // Send a focus event to the browser. + /// + void (CEF_CALLBACK *send_focus_event)(struct _cef_browser_host_t* self, + int setFocus); + + /// + // Send a capture lost event to the browser. + /// + void (CEF_CALLBACK *send_capture_lost_event)( + struct _cef_browser_host_t* self); + + /// + // Get the NSTextInputContext implementation for enabling IME on Mac when + // window rendering is disabled. + /// + cef_text_input_context_t (CEF_CALLBACK *get_nstext_input_context)( + struct _cef_browser_host_t* self); + + /// + // Handles a keyDown event prior to passing it through the NSTextInputClient + // machinery. + /// + void (CEF_CALLBACK *handle_key_event_before_text_input_client)( + struct _cef_browser_host_t* self, cef_event_handle_t keyEvent); + + /// + // Performs any additional actions after NSTextInputClient handles the event. + /// + void (CEF_CALLBACK *handle_key_event_after_text_input_client)( + struct _cef_browser_host_t* self, cef_event_handle_t keyEvent); + + /// + // Call this function when the user drags the mouse into the web view (before + // calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). |drag_data| + // should not contain file contents as this type of data is not allowed to be + // dragged into the web view. File contents can be removed using + // cef_drag_data_t::ResetFileContents (for example, if |drag_data| comes from + // cef_render_handler_t::StartDragging). This function is only used when + // window rendering is disabled. + /// + void (CEF_CALLBACK *drag_target_drag_enter)(struct _cef_browser_host_t* self, + struct _cef_drag_data_t* drag_data, + const struct _cef_mouse_event_t* event, + cef_drag_operations_mask_t allowed_ops); + + /// + // Call this function each time the mouse is moved across the web view during + // a drag operation (after calling DragTargetDragEnter and before calling + // DragTargetDragLeave/DragTargetDrop). This function is only used when window + // rendering is disabled. + /// + void (CEF_CALLBACK *drag_target_drag_over)(struct _cef_browser_host_t* self, + const struct _cef_mouse_event_t* event, + cef_drag_operations_mask_t allowed_ops); + + /// + // Call this function when the user drags the mouse out of the web view (after + // calling DragTargetDragEnter). This function is only used when window + // rendering is disabled. + /// + void (CEF_CALLBACK *drag_target_drag_leave)(struct _cef_browser_host_t* self); + + /// + // Call this function when the user completes the drag operation by dropping + // the object onto the web view (after calling DragTargetDragEnter). The + // object being dropped is |drag_data|, given as an argument to the previous + // DragTargetDragEnter call. This function is only used when window rendering + // is disabled. + /// + void (CEF_CALLBACK *drag_target_drop)(struct _cef_browser_host_t* self, + const struct _cef_mouse_event_t* event); + + /// + // Call this function when the drag operation started by a + // cef_render_handler_t::StartDragging call has ended either in a drop or by + // being cancelled. |x| and |y| are mouse coordinates relative to the upper- + // left corner of the view. If the web view is both the drag source and the + // drag target then all DragTarget* functions should be called before + // DragSource* mthods. This function is only used when window rendering is + // disabled. + /// + void (CEF_CALLBACK *drag_source_ended_at)(struct _cef_browser_host_t* self, + int x, int y, cef_drag_operations_mask_t op); + + /// + // Call this function when the drag operation started by a + // cef_render_handler_t::StartDragging call has completed. This function may + // be called immediately without first calling DragSourceEndedAt to cancel a + // drag operation. If the web view is both the drag source and the drag target + // then all DragTarget* functions should be called before DragSource* mthods. + // This function is only used when window rendering is disabled. + /// + void (CEF_CALLBACK *drag_source_system_drag_ended)( + struct _cef_browser_host_t* self); +} cef_browser_host_t; + + +/// +// Create a new browser window using the window parameters specified by +// |windowInfo|. All values will be copied internally and the actual window will +// be created on the UI thread. If |request_context| is NULL the global request +// context will be used. This function can be called on any browser process +// thread and will not block. +/// +CEF_EXPORT int cef_browser_host_create_browser( + const cef_window_info_t* windowInfo, struct _cef_client_t* client, + const cef_string_t* url, const struct _cef_browser_settings_t* settings, + struct _cef_request_context_t* request_context); + +/// +// Create a new browser window using the window parameters specified by +// |windowInfo|. If |request_context| is NULL the global request context will be +// used. This function can only be called on the browser process UI thread. +/// +CEF_EXPORT cef_browser_t* cef_browser_host_create_browser_sync( + const cef_window_info_t* windowInfo, struct _cef_client_t* client, + const cef_string_t* url, const struct _cef_browser_settings_t* settings, + struct _cef_request_context_t* request_context); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_ diff --git a/include/capi/cef_browser_process_handler_capi.h b/include/capi/cef_browser_process_handler_capi.h new file mode 100644 index 000000000..099c7e989 --- /dev/null +++ b/include/capi/cef_browser_process_handler_capi.h @@ -0,0 +1,104 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_command_line_capi.h" +#include "include/capi/cef_print_handler_capi.h" +#include "include/capi/cef_values_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to implement browser process callbacks. The functions of this +// structure will be called on the browser process main thread unless otherwise +// indicated. +/// +typedef struct _cef_browser_process_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called on the browser process UI thread immediately after the CEF context + // has been initialized. + /// + void (CEF_CALLBACK *on_context_initialized)( + struct _cef_browser_process_handler_t* self); + + /// + // Called before a child process is launched. Will be called on the browser + // process UI thread when launching a render process and on the browser + // process IO thread when launching a GPU or plugin process. Provides an + // opportunity to modify the child process command line. Do not keep a + // reference to |command_line| outside of this function. + /// + void (CEF_CALLBACK *on_before_child_process_launch)( + struct _cef_browser_process_handler_t* self, + struct _cef_command_line_t* command_line); + + /// + // Called on the browser process IO thread after the main thread has been + // created for a new render process. Provides an opportunity to specify extra + // information that will be passed to + // cef_render_process_handler_t::on_render_thread_created() in the render + // process. Do not keep a reference to |extra_info| outside of this function. + /// + void (CEF_CALLBACK *on_render_process_thread_created)( + struct _cef_browser_process_handler_t* self, + struct _cef_list_value_t* extra_info); + + /// + // Return the handler for printing on Linux. If a print handler is not + // provided then printing will not be supported on the Linux platform. + /// + struct _cef_print_handler_t* (CEF_CALLBACK *get_print_handler)( + struct _cef_browser_process_handler_t* self); +} cef_browser_process_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_ diff --git a/include/capi/cef_callback_capi.h b/include/capi/cef_callback_capi.h new file mode 100644 index 000000000..232f82262 --- /dev/null +++ b/include/capi/cef_callback_capi.h @@ -0,0 +1,89 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_CALLBACK_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_CALLBACK_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Generic callback structure used for asynchronous continuation. +/// +typedef struct _cef_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue processing. + /// + void (CEF_CALLBACK *cont)(struct _cef_callback_t* self); + + /// + // Cancel processing. + /// + void (CEF_CALLBACK *cancel)(struct _cef_callback_t* self); +} cef_callback_t; + + +/// +// Generic callback structure used for asynchronous completion. +/// +typedef struct _cef_completion_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called once the task is complete. + /// + void (CEF_CALLBACK *on_complete)(struct _cef_completion_callback_t* self); +} cef_completion_callback_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_CALLBACK_CAPI_H_ diff --git a/include/capi/cef_client_capi.h b/include/capi/cef_client_capi.h new file mode 100644 index 000000000..b51484971 --- /dev/null +++ b/include/capi/cef_client_capi.h @@ -0,0 +1,169 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_context_menu_handler_capi.h" +#include "include/capi/cef_dialog_handler_capi.h" +#include "include/capi/cef_display_handler_capi.h" +#include "include/capi/cef_download_handler_capi.h" +#include "include/capi/cef_drag_handler_capi.h" +#include "include/capi/cef_focus_handler_capi.h" +#include "include/capi/cef_geolocation_handler_capi.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "include/capi/cef_keyboard_handler_capi.h" +#include "include/capi/cef_life_span_handler_capi.h" +#include "include/capi/cef_load_handler_capi.h" +#include "include/capi/cef_process_message_capi.h" +#include "include/capi/cef_render_handler_capi.h" +#include "include/capi/cef_request_handler_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to provide handler implementations. +/// +typedef struct _cef_client_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Return the handler for context menus. If no handler is provided the default + // implementation will be used. + /// + struct _cef_context_menu_handler_t* (CEF_CALLBACK *get_context_menu_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for dialogs. If no handler is provided the default + // implementation will be used. + /// + struct _cef_dialog_handler_t* (CEF_CALLBACK *get_dialog_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for browser display state events. + /// + struct _cef_display_handler_t* (CEF_CALLBACK *get_display_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for download events. If no handler is returned downloads + // will not be allowed. + /// + struct _cef_download_handler_t* (CEF_CALLBACK *get_download_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for drag events. + /// + struct _cef_drag_handler_t* (CEF_CALLBACK *get_drag_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for focus events. + /// + struct _cef_focus_handler_t* (CEF_CALLBACK *get_focus_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for geolocation permissions requests. If no handler is + // provided geolocation access will be denied by default. + /// + struct _cef_geolocation_handler_t* (CEF_CALLBACK *get_geolocation_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for JavaScript dialogs. If no handler is provided the + // default implementation will be used. + /// + struct _cef_jsdialog_handler_t* (CEF_CALLBACK *get_jsdialog_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for keyboard events. + /// + struct _cef_keyboard_handler_t* (CEF_CALLBACK *get_keyboard_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for browser life span events. + /// + struct _cef_life_span_handler_t* (CEF_CALLBACK *get_life_span_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for browser load status events. + /// + struct _cef_load_handler_t* (CEF_CALLBACK *get_load_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for off-screen rendering events. + /// + struct _cef_render_handler_t* (CEF_CALLBACK *get_render_handler)( + struct _cef_client_t* self); + + /// + // Return the handler for browser request events. + /// + struct _cef_request_handler_t* (CEF_CALLBACK *get_request_handler)( + struct _cef_client_t* self); + + /// + // Called when a new message is received from a different process. Return true + // (1) if the message was handled or false (0) otherwise. Do not keep a + // reference to or attempt to access the message outside of this callback. + /// + int (CEF_CALLBACK *on_process_message_received)(struct _cef_client_t* self, + struct _cef_browser_t* browser, cef_process_id_t source_process, + struct _cef_process_message_t* message); +} cef_client_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_ diff --git a/include/capi/cef_command_line_capi.h b/include/capi/cef_command_line_capi.h new file mode 100644 index 000000000..83e28cd3c --- /dev/null +++ b/include/capi/cef_command_line_capi.h @@ -0,0 +1,213 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_COMMAND_LINE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_COMMAND_LINE_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to create and/or parse command line arguments. Arguments with +// '--', '-' and, on Windows, '/' prefixes are considered switches. Switches +// will always precede any arguments without switch prefixes. Switches can +// optionally have a value specified using the '=' delimiter (e.g. +// "-switch=value"). An argument of "--" will terminate switch parsing with all +// subsequent tokens, regardless of prefix, being interpreted as non-switch +// arguments. Switch names are considered case-insensitive. This structure can +// be used before cef_initialize() is called. +/// +typedef struct _cef_command_line_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_command_line_t* self); + + /// + // Returns true (1) if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_command_line_t* self); + + /// + // Returns a writable copy of this object. + /// + struct _cef_command_line_t* (CEF_CALLBACK *copy)( + struct _cef_command_line_t* self); + + /// + // Initialize the command line with the specified |argc| and |argv| values. + // The first argument must be the name of the program. This function is only + // supported on non-Windows platforms. + /// + void (CEF_CALLBACK *init_from_argv)(struct _cef_command_line_t* self, + int argc, const char* const* argv); + + /// + // Initialize the command line with the string returned by calling + // GetCommandLineW(). This function is only supported on Windows. + /// + void (CEF_CALLBACK *init_from_string)(struct _cef_command_line_t* self, + const cef_string_t* command_line); + + /// + // Reset the command-line switches and arguments but leave the program + // component unchanged. + /// + void (CEF_CALLBACK *reset)(struct _cef_command_line_t* self); + + /// + // Retrieve the original command line string as a vector of strings. The argv + // array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* } + /// + void (CEF_CALLBACK *get_argv)(struct _cef_command_line_t* self, + cef_string_list_t argv); + + /// + // Constructs and returns the represented command line string. Use this + // function cautiously because quoting behavior is unclear. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_command_line_string)( + struct _cef_command_line_t* self); + + /// + // Get the program part of the command line string (the first item). + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_program)( + struct _cef_command_line_t* self); + + /// + // Set the program part of the command line string (the first item). + /// + void (CEF_CALLBACK *set_program)(struct _cef_command_line_t* self, + const cef_string_t* program); + + /// + // Returns true (1) if the command line has switches. + /// + int (CEF_CALLBACK *has_switches)(struct _cef_command_line_t* self); + + /// + // Returns true (1) if the command line contains the given switch. + /// + int (CEF_CALLBACK *has_switch)(struct _cef_command_line_t* self, + const cef_string_t* name); + + /// + // Returns the value associated with the given switch. If the switch has no + // value or isn't present this function returns the NULL string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_switch_value)( + struct _cef_command_line_t* self, const cef_string_t* name); + + /// + // Returns the map of switch names and values. If a switch has no value an + // NULL string is returned. + /// + void (CEF_CALLBACK *get_switches)(struct _cef_command_line_t* self, + cef_string_map_t switches); + + /// + // Add a switch to the end of the command line. If the switch has no value + // pass an NULL value string. + /// + void (CEF_CALLBACK *append_switch)(struct _cef_command_line_t* self, + const cef_string_t* name); + + /// + // Add a switch with the specified value to the end of the command line. + /// + void (CEF_CALLBACK *append_switch_with_value)( + struct _cef_command_line_t* self, const cef_string_t* name, + const cef_string_t* value); + + /// + // True if there are remaining command line arguments. + /// + int (CEF_CALLBACK *has_arguments)(struct _cef_command_line_t* self); + + /// + // Get the remaining command line arguments. + /// + void (CEF_CALLBACK *get_arguments)(struct _cef_command_line_t* self, + cef_string_list_t arguments); + + /// + // Add an argument to the end of the command line. + /// + void (CEF_CALLBACK *append_argument)(struct _cef_command_line_t* self, + const cef_string_t* argument); + + /// + // Insert a command before the current command. Common for debuggers, like + // "valgrind" or "gdb --args". + /// + void (CEF_CALLBACK *prepend_wrapper)(struct _cef_command_line_t* self, + const cef_string_t* wrapper); +} cef_command_line_t; + + +/// +// Create a new cef_command_line_t instance. +/// +CEF_EXPORT cef_command_line_t* cef_command_line_create(); + +/// +// Returns the singleton global cef_command_line_t object. The returned object +// will be read-only. +/// +CEF_EXPORT cef_command_line_t* cef_command_line_get_global(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_COMMAND_LINE_CAPI_H_ diff --git a/include/capi/cef_context_menu_handler_capi.h b/include/capi/cef_context_menu_handler_capi.h new file mode 100644 index 000000000..115d291b8 --- /dev/null +++ b/include/capi/cef_context_menu_handler_capi.h @@ -0,0 +1,219 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_CONTEXT_MENU_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_CONTEXT_MENU_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_menu_model_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_context_menu_params_t; + +/// +// Implement this structure to handle context menu events. The functions of this +// structure will be called on the UI thread. +/// +typedef struct _cef_context_menu_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called before a context menu is displayed. |params| provides information + // about the context menu state. |model| initially contains the default + // context menu. The |model| can be cleared to show no context menu or + // modified to show a custom menu. Do not keep references to |params| or + // |model| outside of this callback. + /// + void (CEF_CALLBACK *on_before_context_menu)( + struct _cef_context_menu_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_context_menu_params_t* params, + struct _cef_menu_model_t* model); + + /// + // Called to execute a command selected from the context menu. Return true (1) + // if the command was handled or false (0) for the default implementation. See + // cef_menu_id_t for the command ids that have default implementations. All + // user-defined command ids should be between MENU_ID_USER_FIRST and + // MENU_ID_USER_LAST. |params| will have the same values as what was passed to + // on_before_context_menu(). Do not keep a reference to |params| outside of + // this callback. + /// + int (CEF_CALLBACK *on_context_menu_command)( + struct _cef_context_menu_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_context_menu_params_t* params, + int command_id, cef_event_flags_t event_flags); + + /// + // Called when the context menu is dismissed irregardless of whether the menu + // was NULL or a command was selected. + /// + void (CEF_CALLBACK *on_context_menu_dismissed)( + struct _cef_context_menu_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame); +} cef_context_menu_handler_t; + + +/// +// Provides information about the context menu state. The ethods of this +// structure can only be accessed on browser process the UI thread. +/// +typedef struct _cef_context_menu_params_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the X coordinate of the mouse where the context menu was invoked. + // Coords are relative to the associated RenderView's origin. + /// + int (CEF_CALLBACK *get_xcoord)(struct _cef_context_menu_params_t* self); + + /// + // Returns the Y coordinate of the mouse where the context menu was invoked. + // Coords are relative to the associated RenderView's origin. + /// + int (CEF_CALLBACK *get_ycoord)(struct _cef_context_menu_params_t* self); + + /// + // Returns flags representing the type of node that the context menu was + // invoked on. + /// + cef_context_menu_type_flags_t (CEF_CALLBACK *get_type_flags)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the URL of the link, if any, that encloses the node that the + // context menu was invoked on. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_link_url)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the link URL, if any, to be used ONLY for "copy link address". We + // don't validate this field in the frontend process. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_unfiltered_link_url)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the source URL, if any, for the element that the context menu was + // invoked on. Example of elements with source URLs are img, audio, and video. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_source_url)( + struct _cef_context_menu_params_t* self); + + /// + // Returns true (1) if the context menu was invoked on an image which has non- + // NULL contents. + /// + int (CEF_CALLBACK *has_image_contents)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the URL of the top level page that the context menu was invoked on. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_page_url)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the URL of the subframe that the context menu was invoked on. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_frame_url)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the character encoding of the subframe that the context menu was + // invoked on. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_frame_charset)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the type of context node that the context menu was invoked on. + /// + cef_context_menu_media_type_t (CEF_CALLBACK *get_media_type)( + struct _cef_context_menu_params_t* self); + + /// + // Returns flags representing the actions supported by the media element, if + // any, that the context menu was invoked on. + /// + cef_context_menu_media_state_flags_t (CEF_CALLBACK *get_media_state_flags)( + struct _cef_context_menu_params_t* self); + + /// + // Returns the text of the selection, if any, that the context menu was + // invoked on. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_selection_text)( + struct _cef_context_menu_params_t* self); + + /// + // Returns true (1) if the context menu was invoked on an editable node. + /// + int (CEF_CALLBACK *is_editable)(struct _cef_context_menu_params_t* self); + + /// + // Returns flags representing the actions supported by the editable node, if + // any, that the context menu was invoked on. + /// + cef_context_menu_edit_state_flags_t (CEF_CALLBACK *get_edit_state_flags)( + struct _cef_context_menu_params_t* self); +} cef_context_menu_params_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_CONTEXT_MENU_HANDLER_CAPI_H_ diff --git a/include/capi/cef_cookie_capi.h b/include/capi/cef_cookie_capi.h new file mode 100644 index 000000000..eeca1837f --- /dev/null +++ b/include/capi/cef_cookie_capi.h @@ -0,0 +1,176 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_callback_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_cookie_visitor_t; + +/// +// Structure used for managing cookies. The functions of this structure may be +// called on any thread unless otherwise indicated. +/// +typedef struct _cef_cookie_manager_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Set the schemes supported by this manager. By default only "http" and + // "https" schemes are supported. Must be called before any cookies are + // accessed. + /// + void (CEF_CALLBACK *set_supported_schemes)(struct _cef_cookie_manager_t* self, + cef_string_list_t schemes); + + /// + // Visit all cookies. The returned cookies are ordered by longest path, then + // by earliest creation date. Returns false (0) if cookies cannot be accessed. + /// + int (CEF_CALLBACK *visit_all_cookies)(struct _cef_cookie_manager_t* self, + struct _cef_cookie_visitor_t* visitor); + + /// + // Visit a subset of cookies. The results are filtered by the given url + // scheme, host, domain and path. If |includeHttpOnly| is true (1) HTTP-only + // cookies will also be included in the results. The returned cookies are + // ordered by longest path, then by earliest creation date. Returns false (0) + // if cookies cannot be accessed. + /// + int (CEF_CALLBACK *visit_url_cookies)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, int includeHttpOnly, + struct _cef_cookie_visitor_t* visitor); + + /// + // Sets a cookie given a valid URL and explicit user-provided cookie + // attributes. This function expects each attribute to be well-formed. It will + // check for disallowed characters (e.g. the ';' character is disallowed + // within the cookie value attribute) and will return false (0) without + // setting the cookie if such characters are found. This function must be + // called on the IO thread. + /// + int (CEF_CALLBACK *set_cookie)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const struct _cef_cookie_t* cookie); + + /// + // Delete all cookies that match the specified parameters. If both |url| and + // values |cookie_name| are specified all host and domain cookies matching + // both will be deleted. If only |url| is specified all host cookies (but not + // domain cookies) irrespective of path will be deleted. If |url| is NULL all + // cookies for all hosts and domains will be deleted. Returns false (0) if a + // non- NULL invalid URL is specified or if cookies cannot be accessed. This + // function must be called on the IO thread. + /// + int (CEF_CALLBACK *delete_cookies)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const cef_string_t* cookie_name); + + /// + // Sets the directory path that will be used for storing cookie data. If + // |path| is NULL data will be stored in memory only. Otherwise, data will be + // stored at the specified |path|. To persist session cookies (cookies without + // an expiry date or validity interval) set |persist_session_cookies| to true + // (1). Session cookies are generally intended to be transient and most Web + // browsers do not persist them. Returns false (0) if cookies cannot be + // accessed. + /// + int (CEF_CALLBACK *set_storage_path)(struct _cef_cookie_manager_t* self, + const cef_string_t* path, int persist_session_cookies); + + /// + // Flush the backing store (if any) to disk and execute the specified + // |callback| on the IO thread when done. Returns false (0) if cookies cannot + // be accessed. + /// + int (CEF_CALLBACK *flush_store)(struct _cef_cookie_manager_t* self, + struct _cef_completion_callback_t* callback); +} cef_cookie_manager_t; + + +/// +// Returns the global cookie manager. By default data will be stored at +// CefSettings.cache_path if specified or in memory otherwise. +/// +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager(); + +/// +// Creates a new cookie manager. If |path| is NULL data will be stored in memory +// only. Otherwise, data will be stored at the specified |path|. To persist +// session cookies (cookies without an expiry date or validity interval) set +// |persist_session_cookies| to true (1). Session cookies are generally intended +// to be transient and most Web browsers do not persist them. Returns NULL if +// creation fails. +/// +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( + const cef_string_t* path, int persist_session_cookies); + + +/// +// Structure to implement for visiting cookie values. The functions of this +// structure will always be called on the IO thread. +/// +typedef struct _cef_cookie_visitor_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called once for each cookie. |count| is the 0-based + // index for the current cookie. |total| is the total number of cookies. Set + // |deleteCookie| to true (1) to delete the cookie currently being visited. + // Return false (0) to stop visiting cookies. This function may never be + // called if no cookies are found. + /// + int (CEF_CALLBACK *visit)(struct _cef_cookie_visitor_t* self, + const struct _cef_cookie_t* cookie, int count, int total, + int* deleteCookie); +} cef_cookie_visitor_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_ diff --git a/include/capi/cef_dialog_handler_capi.h b/include/capi/cef_dialog_handler_capi.h new file mode 100644 index 000000000..a8165bd65 --- /dev/null +++ b/include/capi/cef_dialog_handler_capi.h @@ -0,0 +1,106 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure for asynchronous continuation of file dialog requests. +/// +typedef struct _cef_file_dialog_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the file selection with the specified |file_paths|. This may be a + // single value or a list of values depending on the dialog mode. An NULL + // value is treated the same as calling cancel(). + /// + void (CEF_CALLBACK *cont)(struct _cef_file_dialog_callback_t* self, + cef_string_list_t file_paths); + + /// + // Cancel the file selection. + /// + void (CEF_CALLBACK *cancel)(struct _cef_file_dialog_callback_t* self); +} cef_file_dialog_callback_t; + + +/// +// Implement this structure to handle dialog events. The functions of this +// structure will be called on the browser process UI thread. +/// +typedef struct _cef_dialog_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called to run a file chooser dialog. |mode| represents the type of dialog + // to display. |title| to the title to be used for the dialog and may be NULL + // to show the default title ("Open" or "Save" depending on the mode). + // |default_file_name| is the default file name to select in the dialog. + // |accept_types| is a list of valid lower-cased MIME types or file extensions + // specified in an input element and is used to restrict selectable files to + // such types. To display a custom dialog return true (1) and execute + // |callback| either inline or at a later time. To display the default dialog + // return false (0). + /// + int (CEF_CALLBACK *on_file_dialog)(struct _cef_dialog_handler_t* self, + struct _cef_browser_t* browser, cef_file_dialog_mode_t mode, + const cef_string_t* title, const cef_string_t* default_file_name, + cef_string_list_t accept_types, + struct _cef_file_dialog_callback_t* callback); +} cef_dialog_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DIALOG_HANDLER_CAPI_H_ diff --git a/include/capi/cef_display_handler_capi.h b/include/capi/cef_display_handler_capi.h new file mode 100644 index 000000000..2b7906bf1 --- /dev/null +++ b/include/capi/cef_display_handler_capi.h @@ -0,0 +1,105 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DISPLAY_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DISPLAY_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events related to browser display state. +// The functions of this structure will be called on the UI thread. +/// +typedef struct _cef_display_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when a frame's address has changed. + /// + void (CEF_CALLBACK *on_address_change)(struct _cef_display_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + const cef_string_t* url); + + /// + // Called when the page title changes. + /// + void (CEF_CALLBACK *on_title_change)(struct _cef_display_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* title); + + /// + // Called when the browser is about to display a tooltip. |text| contains the + // text that will be displayed in the tooltip. To handle the display of the + // tooltip yourself return true (1). Otherwise, you can optionally modify + // |text| and then return false (0) to allow the browser to display the + // tooltip. When window rendering is disabled the application is responsible + // for drawing tooltips and the return value is ignored. + /// + int (CEF_CALLBACK *on_tooltip)(struct _cef_display_handler_t* self, + struct _cef_browser_t* browser, cef_string_t* text); + + /// + // Called when the browser receives a status message. |value| contains the + // text that will be displayed in the status message. + /// + void (CEF_CALLBACK *on_status_message)(struct _cef_display_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* value); + + /// + // Called to display a console message. Return true (1) to stop the message + // from being output to the console. + /// + int (CEF_CALLBACK *on_console_message)(struct _cef_display_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* message, + const cef_string_t* source, int line); +} cef_display_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DISPLAY_HANDLER_CAPI_H_ diff --git a/include/capi/cef_dom_capi.h b/include/capi/cef_dom_capi.h new file mode 100644 index 000000000..5a8361033 --- /dev/null +++ b/include/capi/cef_dom_capi.h @@ -0,0 +1,447 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DOM_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DOM_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_domdocument_t; +struct _cef_domevent_listener_t; +struct _cef_domnode_t; + +/// +// Structure to implement for visiting the DOM. The functions of this structure +// will be called on the render process main thread. +/// +typedef struct _cef_domvisitor_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method executed for visiting the DOM. The document object passed to this + // function represents a snapshot of the DOM at the time this function is + // executed. DOM objects are only valid for the scope of this function. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this function. + /// + void (CEF_CALLBACK *visit)(struct _cef_domvisitor_t* self, + struct _cef_domdocument_t* document); +} cef_domvisitor_t; + + +/// +// Structure used to represent a DOM document. The functions of this structure +// should only be called on the render process main thread thread. +/// +typedef struct _cef_domdocument_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the document type. + /// + cef_dom_document_type_t (CEF_CALLBACK *get_type)( + struct _cef_domdocument_t* self); + + /// + // Returns the root document node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_document)( + struct _cef_domdocument_t* self); + + /// + // Returns the BODY node of an HTML document. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_body)( + struct _cef_domdocument_t* self); + + /// + // Returns the HEAD node of an HTML document. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_head)( + struct _cef_domdocument_t* self); + + /// + // Returns the title of an HTML document. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_title)( + struct _cef_domdocument_t* self); + + /// + // Returns the document element with the specified ID value. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_element_by_id)( + struct _cef_domdocument_t* self, const cef_string_t* id); + + /// + // Returns the node that currently has keyboard focus. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_focused_node)( + struct _cef_domdocument_t* self); + + /// + // Returns true (1) if a portion of the document is selected. + /// + int (CEF_CALLBACK *has_selection)(struct _cef_domdocument_t* self); + + /// + // Returns the selection start node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_selection_start_node)( + struct _cef_domdocument_t* self); + + /// + // Returns the selection offset within the start node. + /// + int (CEF_CALLBACK *get_selection_start_offset)( + struct _cef_domdocument_t* self); + + /// + // Returns the selection end node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_selection_end_node)( + struct _cef_domdocument_t* self); + + /// + // Returns the selection offset within the end node. + /// + int (CEF_CALLBACK *get_selection_end_offset)(struct _cef_domdocument_t* self); + + /// + // Returns the contents of this selection as markup. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_selection_as_markup)( + struct _cef_domdocument_t* self); + + /// + // Returns the contents of this selection as text. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_selection_as_text)( + struct _cef_domdocument_t* self); + + /// + // Returns the base URL for the document. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_base_url)( + struct _cef_domdocument_t* self); + + /// + // Returns a complete URL based on the document base URL and the specified + // partial URL. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_complete_url)( + struct _cef_domdocument_t* self, const cef_string_t* partialURL); +} cef_domdocument_t; + + +/// +// Structure used to represent a DOM node. The functions of this structure +// should only be called on the render process main thread. +/// +typedef struct _cef_domnode_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the type for this node. + /// + cef_dom_node_type_t (CEF_CALLBACK *get_type)(struct _cef_domnode_t* self); + + /// + // Returns true (1) if this is a text node. + /// + int (CEF_CALLBACK *is_text)(struct _cef_domnode_t* self); + + /// + // Returns true (1) if this is an element node. + /// + int (CEF_CALLBACK *is_element)(struct _cef_domnode_t* self); + + /// + // Returns true (1) if this is an editable node. + /// + int (CEF_CALLBACK *is_editable)(struct _cef_domnode_t* self); + + /// + // Returns true (1) if this is a form control element node. + /// + int (CEF_CALLBACK *is_form_control_element)(struct _cef_domnode_t* self); + + /// + // Returns the type of this form control element node. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_form_control_element_type)( + struct _cef_domnode_t* self); + + /// + // Returns true (1) if this object is pointing to the same handle as |that| + // object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_domnode_t* self, + struct _cef_domnode_t* that); + + /// + // Returns the name of this node. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_name)(struct _cef_domnode_t* self); + + /// + // Returns the value of this node. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_value)(struct _cef_domnode_t* self); + + /// + // Set the value of this node. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_value)(struct _cef_domnode_t* self, + const cef_string_t* value); + + /// + // Returns the contents of this node as markup. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_as_markup)( + struct _cef_domnode_t* self); + + /// + // Returns the document associated with this node. + /// + struct _cef_domdocument_t* (CEF_CALLBACK *get_document)( + struct _cef_domnode_t* self); + + /// + // Returns the parent node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_parent)( + struct _cef_domnode_t* self); + + /// + // Returns the previous sibling node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_previous_sibling)( + struct _cef_domnode_t* self); + + /// + // Returns the next sibling node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_next_sibling)( + struct _cef_domnode_t* self); + + /// + // Returns true (1) if this node has child nodes. + /// + int (CEF_CALLBACK *has_children)(struct _cef_domnode_t* self); + + /// + // Return the first child node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_first_child)( + struct _cef_domnode_t* self); + + /// + // Returns the last child node. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_last_child)( + struct _cef_domnode_t* self); + + /// + // Add an event listener to this node for the specified event type. If + // |useCapture| is true (1) then this listener will be considered a capturing + // listener. Capturing listeners will recieve all events of the specified type + // before the events are dispatched to any other event targets beneath the + // current node in the tree. Events which are bubbling upwards through the + // tree will not trigger a capturing listener. Separate calls to this function + // can be used to register the same listener with and without capture. See + // WebCore/dom/EventNames.h for the list of supported event types. + /// + void (CEF_CALLBACK *add_event_listener)(struct _cef_domnode_t* self, + const cef_string_t* eventType, struct _cef_domevent_listener_t* listener, + int useCapture); + + + // The following functions are valid only for element nodes. + + /// + // Returns the tag name of this element. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_element_tag_name)( + struct _cef_domnode_t* self); + + /// + // Returns true (1) if this element has attributes. + /// + int (CEF_CALLBACK *has_element_attributes)(struct _cef_domnode_t* self); + + /// + // Returns true (1) if this element has an attribute named |attrName|. + /// + int (CEF_CALLBACK *has_element_attribute)(struct _cef_domnode_t* self, + const cef_string_t* attrName); + + /// + // Returns the element attribute named |attrName|. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_element_attribute)( + struct _cef_domnode_t* self, const cef_string_t* attrName); + + /// + // Returns a map of all element attributes. + /// + void (CEF_CALLBACK *get_element_attributes)(struct _cef_domnode_t* self, + cef_string_map_t attrMap); + + /// + // Set the value for the element attribute named |attrName|. Returns true (1) + // on success. + /// + int (CEF_CALLBACK *set_element_attribute)(struct _cef_domnode_t* self, + const cef_string_t* attrName, const cef_string_t* value); + + /// + // Returns the inner text of the element. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_element_inner_text)( + struct _cef_domnode_t* self); +} cef_domnode_t; + + +/// +// Structure used to represent a DOM event. The functions of this structure +// should only be called on the render process main thread. +/// +typedef struct _cef_domevent_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the event type. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_type)(struct _cef_domevent_t* self); + + /// + // Returns the event category. + /// + cef_dom_event_category_t (CEF_CALLBACK *get_category)( + struct _cef_domevent_t* self); + + /// + // Returns the event processing phase. + /// + cef_dom_event_phase_t (CEF_CALLBACK *get_phase)(struct _cef_domevent_t* self); + + /// + // Returns true (1) if the event can bubble up the tree. + /// + int (CEF_CALLBACK *can_bubble)(struct _cef_domevent_t* self); + + /// + // Returns true (1) if the event can be canceled. + /// + int (CEF_CALLBACK *can_cancel)(struct _cef_domevent_t* self); + + /// + // Returns the document associated with this event. + /// + struct _cef_domdocument_t* (CEF_CALLBACK *get_document)( + struct _cef_domevent_t* self); + + /// + // Returns the target of the event. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_target)( + struct _cef_domevent_t* self); + + /// + // Returns the current target of the event. + /// + struct _cef_domnode_t* (CEF_CALLBACK *get_current_target)( + struct _cef_domevent_t* self); +} cef_domevent_t; + + +/// +// Structure to implement for handling DOM events. The functions of this +// structure will be called on the render process main thread. +/// +typedef struct _cef_domevent_listener_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when an event is received. The event object passed to this function + // contains a snapshot of the DOM at the time this function is executed. DOM + // objects are only valid for the scope of this function. Do not keep + // references to or attempt to access any DOM objects outside the scope of + // this function. + /// + void (CEF_CALLBACK *handle_event)(struct _cef_domevent_listener_t* self, + struct _cef_domevent_t* event); +} cef_domevent_listener_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DOM_CAPI_H_ diff --git a/include/capi/cef_download_handler_capi.h b/include/capi/cef_download_handler_capi.h new file mode 100644 index 000000000..9886b1945 --- /dev/null +++ b/include/capi/cef_download_handler_capi.h @@ -0,0 +1,127 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_download_item_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure used to asynchronously continue a download. +/// +typedef struct _cef_before_download_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Call to continue the download. Set |download_path| to the full file path + // for the download including the file name or leave blank to use the + // suggested name and the default temp directory. Set |show_dialog| to true + // (1) if you do wish to show the default "Save As" dialog. + /// + void (CEF_CALLBACK *cont)(struct _cef_before_download_callback_t* self, + const cef_string_t* download_path, int show_dialog); +} cef_before_download_callback_t; + + +/// +// Callback structure used to asynchronously cancel a download. +/// +typedef struct _cef_download_item_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Call to cancel the download. + /// + void (CEF_CALLBACK *cancel)(struct _cef_download_item_callback_t* self); +} cef_download_item_callback_t; + + +/// +// Structure used to handle file downloads. The functions of this structure will +// called on the browser process UI thread. +/// +typedef struct _cef_download_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called before a download begins. |suggested_name| is the suggested name for + // the download file. By default the download will be canceled. Execute + // |callback| either asynchronously or in this function to continue the + // download if desired. Do not keep a reference to |download_item| outside of + // this function. + /// + void (CEF_CALLBACK *on_before_download)(struct _cef_download_handler_t* self, + struct _cef_browser_t* browser, + struct _cef_download_item_t* download_item, + const cef_string_t* suggested_name, + struct _cef_before_download_callback_t* callback); + + /// + // Called when a download's status or progress information has been updated. + // This may be called multiple times before and after on_before_download(). + // Execute |callback| either asynchronously or in this function to cancel the + // download if desired. Do not keep a reference to |download_item| outside of + // this function. + /// + void (CEF_CALLBACK *on_download_updated)(struct _cef_download_handler_t* self, + struct _cef_browser_t* browser, + struct _cef_download_item_t* download_item, + struct _cef_download_item_callback_t* callback); +} cef_download_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DOWNLOAD_HANDLER_CAPI_H_ diff --git a/include/capi/cef_download_item_capi.h b/include/capi/cef_download_item_capi.h new file mode 100644 index 000000000..ef5a1575d --- /dev/null +++ b/include/capi/cef_download_item_capi.h @@ -0,0 +1,155 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DOWNLOAD_ITEM_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DOWNLOAD_ITEM_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to represent a download item. +/// +typedef struct _cef_download_item_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_download_item_t* self); + + /// + // Returns true (1) if the download is in progress. + /// + int (CEF_CALLBACK *is_in_progress)(struct _cef_download_item_t* self); + + /// + // Returns true (1) if the download is complete. + /// + int (CEF_CALLBACK *is_complete)(struct _cef_download_item_t* self); + + /// + // Returns true (1) if the download has been canceled or interrupted. + /// + int (CEF_CALLBACK *is_canceled)(struct _cef_download_item_t* self); + + /// + // Returns a simple speed estimate in bytes/s. + /// + int64 (CEF_CALLBACK *get_current_speed)(struct _cef_download_item_t* self); + + /// + // Returns the rough percent complete or -1 if the receive total size is + // unknown. + /// + int (CEF_CALLBACK *get_percent_complete)(struct _cef_download_item_t* self); + + /// + // Returns the total number of bytes. + /// + int64 (CEF_CALLBACK *get_total_bytes)(struct _cef_download_item_t* self); + + /// + // Returns the number of received bytes. + /// + int64 (CEF_CALLBACK *get_received_bytes)(struct _cef_download_item_t* self); + + /// + // Returns the time that the download started. + /// + cef_time_t (CEF_CALLBACK *get_start_time)(struct _cef_download_item_t* self); + + /// + // Returns the time that the download ended. + /// + cef_time_t (CEF_CALLBACK *get_end_time)(struct _cef_download_item_t* self); + + /// + // Returns the full path to the downloaded or downloading file. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_full_path)( + struct _cef_download_item_t* self); + + /// + // Returns the unique identifier for this download. + /// + uint32 (CEF_CALLBACK *get_id)(struct _cef_download_item_t* self); + + /// + // Returns the URL. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_url)( + struct _cef_download_item_t* self); + + /// + // Returns the suggested file name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_suggested_file_name)( + struct _cef_download_item_t* self); + + /// + // Returns the content disposition. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_content_disposition)( + struct _cef_download_item_t* self); + + /// + // Returns the mime type. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_mime_type)( + struct _cef_download_item_t* self); +} cef_download_item_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DOWNLOAD_ITEM_CAPI_H_ diff --git a/include/capi/cef_drag_data_capi.h b/include/capi/cef_drag_data_capi.h new file mode 100644 index 000000000..383c67bd0 --- /dev/null +++ b/include/capi/cef_drag_data_capi.h @@ -0,0 +1,211 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DRAG_DATA_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DRAG_DATA_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_stream_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to represent drag data. The functions of this structure may be +// called on any thread. +/// +typedef struct _cef_drag_data_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns a copy of the current object. + /// + struct _cef_drag_data_t* (CEF_CALLBACK *clone)(struct _cef_drag_data_t* self); + + /// + // Returns true (1) if this object is read-only. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_drag_data_t* self); + + /// + // Returns true (1) if the drag data is a link. + /// + int (CEF_CALLBACK *is_link)(struct _cef_drag_data_t* self); + + /// + // Returns true (1) if the drag data is a text or html fragment. + /// + int (CEF_CALLBACK *is_fragment)(struct _cef_drag_data_t* self); + + /// + // Returns true (1) if the drag data is a file. + /// + int (CEF_CALLBACK *is_file)(struct _cef_drag_data_t* self); + + /// + // Return the link URL that is being dragged. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_link_url)( + struct _cef_drag_data_t* self); + + /// + // Return the title associated with the link being dragged. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_link_title)( + struct _cef_drag_data_t* self); + + /// + // Return the metadata, if any, associated with the link being dragged. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_link_metadata)( + struct _cef_drag_data_t* self); + + /// + // Return the plain text fragment that is being dragged. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_fragment_text)( + struct _cef_drag_data_t* self); + + /// + // Return the text/html fragment that is being dragged. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_fragment_html)( + struct _cef_drag_data_t* self); + + /// + // Return the base URL that the fragment came from. This value is used for + // resolving relative URLs and may be NULL. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_fragment_base_url)( + struct _cef_drag_data_t* self); + + /// + // Return the name of the file being dragged out of the browser window. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_file_name)( + struct _cef_drag_data_t* self); + + /// + // Write the contents of the file being dragged out of the web view into + // |writer|. Returns the number of bytes sent to |writer|. If |writer| is NULL + // this function will return the size of the file contents in bytes. Call + // get_file_name() to get a suggested name for the file. + /// + size_t (CEF_CALLBACK *get_file_contents)(struct _cef_drag_data_t* self, + struct _cef_stream_writer_t* writer); + + /// + // Retrieve the list of file names that are being dragged into the browser + // window. + /// + int (CEF_CALLBACK *get_file_names)(struct _cef_drag_data_t* self, + cef_string_list_t names); + + /// + // Set the link URL that is being dragged. + /// + void (CEF_CALLBACK *set_link_url)(struct _cef_drag_data_t* self, + const cef_string_t* url); + + /// + // Set the title associated with the link being dragged. + /// + void (CEF_CALLBACK *set_link_title)(struct _cef_drag_data_t* self, + const cef_string_t* title); + + /// + // Set the metadata associated with the link being dragged. + /// + void (CEF_CALLBACK *set_link_metadata)(struct _cef_drag_data_t* self, + const cef_string_t* data); + + /// + // Set the plain text fragment that is being dragged. + /// + void (CEF_CALLBACK *set_fragment_text)(struct _cef_drag_data_t* self, + const cef_string_t* text); + + /// + // Set the text/html fragment that is being dragged. + /// + void (CEF_CALLBACK *set_fragment_html)(struct _cef_drag_data_t* self, + const cef_string_t* html); + + /// + // Set the base URL that the fragment came from. + /// + void (CEF_CALLBACK *set_fragment_base_url)(struct _cef_drag_data_t* self, + const cef_string_t* base_url); + + /// + // Reset the file contents. You should do this before calling + // cef_browser_host_t::DragTargetDragEnter as the web view does not allow us + // to drag in this kind of data. + /// + void (CEF_CALLBACK *reset_file_contents)(struct _cef_drag_data_t* self); + + /// + // Add a file that is being dragged into the webview. + /// + void (CEF_CALLBACK *add_file)(struct _cef_drag_data_t* self, + const cef_string_t* path, const cef_string_t* display_name); +} cef_drag_data_t; + + +/// +// Create a new cef_drag_data_t object. +/// +CEF_EXPORT cef_drag_data_t* cef_drag_data_create(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DRAG_DATA_CAPI_H_ diff --git a/include/capi/cef_drag_handler_capi.h b/include/capi/cef_drag_handler_capi.h new file mode 100644 index 000000000..a148270da --- /dev/null +++ b/include/capi/cef_drag_handler_capi.h @@ -0,0 +1,76 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_DRAG_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_DRAG_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_drag_data_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events related to dragging. The functions +// of this structure will be called on the UI thread. +/// +typedef struct _cef_drag_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when an external drag event enters the browser window. |dragData| + // contains the drag event data and |mask| represents the type of drag + // operation. Return false (0) for default drag handling behavior or true (1) + // to cancel the drag event. + /// + int (CEF_CALLBACK *on_drag_enter)(struct _cef_drag_handler_t* self, + struct _cef_browser_t* browser, struct _cef_drag_data_t* dragData, + cef_drag_operations_mask_t mask); +} cef_drag_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_DRAG_HANDLER_CAPI_H_ diff --git a/include/capi/cef_focus_handler_capi.h b/include/capi/cef_focus_handler_capi.h new file mode 100644 index 000000000..61938779e --- /dev/null +++ b/include/capi/cef_focus_handler_capi.h @@ -0,0 +1,90 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_FOCUS_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_FOCUS_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_dom_capi.h" +#include "include/capi/cef_frame_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events related to focus. The functions of +// this structure will be called on the UI thread. +/// +typedef struct _cef_focus_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when the browser component is about to loose focus. For instance, if + // focus was on the last HTML element and the user pressed the TAB key. |next| + // will be true (1) if the browser is giving focus to the next component and + // false (0) if the browser is giving focus to the previous component. + /// + void (CEF_CALLBACK *on_take_focus)(struct _cef_focus_handler_t* self, + struct _cef_browser_t* browser, int next); + + /// + // Called when the browser component is requesting focus. |source| indicates + // where the focus request is originating from. Return false (0) to allow the + // focus to be set or true (1) to cancel setting the focus. + /// + int (CEF_CALLBACK *on_set_focus)(struct _cef_focus_handler_t* self, + struct _cef_browser_t* browser, cef_focus_source_t source); + + /// + // Called when the browser component has received focus. + /// + void (CEF_CALLBACK *on_got_focus)(struct _cef_focus_handler_t* self, + struct _cef_browser_t* browser); +} cef_focus_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_FOCUS_HANDLER_CAPI_H_ diff --git a/include/capi/cef_frame_capi.h b/include/capi/cef_frame_capi.h new file mode 100644 index 000000000..25c18102d --- /dev/null +++ b/include/capi/cef_frame_capi.h @@ -0,0 +1,220 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_FRAME_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_FRAME_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_dom_capi.h" +#include "include/capi/cef_request_capi.h" +#include "include/capi/cef_stream_capi.h" +#include "include/capi/cef_string_visitor_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_browser_t; +struct _cef_v8context_t; + +/// +// Structure used to represent a frame in the browser window. When used in the +// browser process the functions of this structure may be called on any thread +// unless otherwise indicated in the comments. When used in the render process +// the functions of this structure may only be called on the main thread. +/// +typedef struct _cef_frame_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // True if this object is currently attached to a valid frame. + /// + int (CEF_CALLBACK *is_valid)(struct _cef_frame_t* self); + + /// + // Execute undo in this frame. + /// + void (CEF_CALLBACK *undo)(struct _cef_frame_t* self); + + /// + // Execute redo in this frame. + /// + void (CEF_CALLBACK *redo)(struct _cef_frame_t* self); + + /// + // Execute cut in this frame. + /// + void (CEF_CALLBACK *cut)(struct _cef_frame_t* self); + + /// + // Execute copy in this frame. + /// + void (CEF_CALLBACK *copy)(struct _cef_frame_t* self); + + /// + // Execute paste in this frame. + /// + void (CEF_CALLBACK *paste)(struct _cef_frame_t* self); + + /// + // Execute delete in this frame. + /// + void (CEF_CALLBACK *del)(struct _cef_frame_t* self); + + /// + // Execute select all in this frame. + /// + void (CEF_CALLBACK *select_all)(struct _cef_frame_t* self); + + /// + // Save this frame's HTML source to a temporary file and open it in the + // default text viewing application. This function can only be called from the + // browser process. + /// + void (CEF_CALLBACK *view_source)(struct _cef_frame_t* self); + + /// + // Retrieve this frame's HTML source as a string sent to the specified + // visitor. + /// + void (CEF_CALLBACK *get_source)(struct _cef_frame_t* self, + struct _cef_string_visitor_t* visitor); + + /// + // Retrieve this frame's display text as a string sent to the specified + // visitor. + /// + void (CEF_CALLBACK *get_text)(struct _cef_frame_t* self, + struct _cef_string_visitor_t* visitor); + + /// + // Load the request represented by the |request| object. + /// + void (CEF_CALLBACK *load_request)(struct _cef_frame_t* self, + struct _cef_request_t* request); + + /// + // Load the specified |url|. + /// + void (CEF_CALLBACK *load_url)(struct _cef_frame_t* self, + const cef_string_t* url); + + /// + // Load the contents of |string_val| with the specified dummy |url|. |url| + // should have a standard scheme (for example, http scheme) or behaviors like + // link clicks and web security restrictions may not behave as expected. + /// + void (CEF_CALLBACK *load_string)(struct _cef_frame_t* self, + const cef_string_t* string_val, const cef_string_t* url); + + /// + // Execute a string of JavaScript code in this frame. The |script_url| + // parameter is the URL where the script in question can be found, if any. The + // renderer may request this URL to show the developer the source of the + // error. The |start_line| parameter is the base line number to use for error + // reporting. + /// + void (CEF_CALLBACK *execute_java_script)(struct _cef_frame_t* self, + const cef_string_t* code, const cef_string_t* script_url, + int start_line); + + /// + // Returns true (1) if this is the main (top-level) frame. + /// + int (CEF_CALLBACK *is_main)(struct _cef_frame_t* self); + + /// + // Returns true (1) if this is the focused frame. + /// + int (CEF_CALLBACK *is_focused)(struct _cef_frame_t* self); + + /// + // Returns the name for this frame. If the frame has an assigned name (for + // example, set via the iframe "name" attribute) then that value will be + // returned. Otherwise a unique name will be constructed based on the frame + // parent hierarchy. The main (top-level) frame will always have an NULL name + // value. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_name)(struct _cef_frame_t* self); + + /// + // Returns the globally unique identifier for this frame. + /// + int64 (CEF_CALLBACK *get_identifier)(struct _cef_frame_t* self); + + /// + // Returns the parent of this frame or NULL if this is the main (top-level) + // frame. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_parent)(struct _cef_frame_t* self); + + /// + // Returns the URL currently loaded in this frame. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_url)(struct _cef_frame_t* self); + + /// + // Returns the browser that this frame belongs to. + /// + struct _cef_browser_t* (CEF_CALLBACK *get_browser)(struct _cef_frame_t* self); + + /// + // Get the V8 context associated with the frame. This function can only be + // called from the render process. + /// + struct _cef_v8context_t* (CEF_CALLBACK *get_v8context)( + struct _cef_frame_t* self); + + /// + // Visit the DOM document. This function can only be called from the render + // process. + /// + void (CEF_CALLBACK *visit_dom)(struct _cef_frame_t* self, + struct _cef_domvisitor_t* visitor); +} cef_frame_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_FRAME_CAPI_H_ diff --git a/include/capi/cef_geolocation_capi.h b/include/capi/cef_geolocation_capi.h new file mode 100644 index 000000000..926cc3c9b --- /dev/null +++ b/include/capi/cef_geolocation_capi.h @@ -0,0 +1,79 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_GEOLOCATION_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_GEOLOCATION_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to receive geolocation updates. The functions of +// this structure will be called on the browser process UI thread. +/// +typedef struct _cef_get_geolocation_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called with the 'best available' location information or, if the location + // update failed, with error information. + /// + void (CEF_CALLBACK *on_location_update)( + struct _cef_get_geolocation_callback_t* self, + const struct _cef_geoposition_t* position); +} cef_get_geolocation_callback_t; + + +/// +// Request a one-time geolocation update. This function bypasses any user +// permission checks so should only be used by code that is allowed to access +// location information. +/// +CEF_EXPORT int cef_get_geolocation(cef_get_geolocation_callback_t* callback); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_GEOLOCATION_CAPI_H_ diff --git a/include/capi/cef_geolocation_handler_capi.h b/include/capi/cef_geolocation_handler_capi.h new file mode 100644 index 000000000..12df10ab9 --- /dev/null +++ b/include/capi/cef_geolocation_handler_capi.h @@ -0,0 +1,106 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_GEOLOCATION_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_GEOLOCATION_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure used for asynchronous continuation of geolocation +// permission requests. +/// +typedef struct _cef_geolocation_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Call to allow or deny geolocation access. + /// + void (CEF_CALLBACK *cont)(struct _cef_geolocation_callback_t* self, + int allow); +} cef_geolocation_callback_t; + + +/// +// Implement this structure to handle events related to geolocation permission +// requests. The functions of this structure will be called on the browser +// process UI thread. +/// +typedef struct _cef_geolocation_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when a page requests permission to access geolocation information. + // |requesting_url| is the URL requesting permission and |request_id| is the + // unique ID for the permission request. Return true (1) and call + // cef_geolocation_callback_t::cont() either in this function or at a later + // time to continue or cancel the request. Return false (0) to cancel the + // request immediately. + /// + int (CEF_CALLBACK *on_request_geolocation_permission)( + struct _cef_geolocation_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* requesting_url, int request_id, + struct _cef_geolocation_callback_t* callback); + + /// + // Called when a geolocation access request is canceled. |requesting_url| is + // the URL that originally requested permission and |request_id| is the unique + // ID for the permission request. + /// + void (CEF_CALLBACK *on_cancel_geolocation_permission)( + struct _cef_geolocation_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* requesting_url, int request_id); +} cef_geolocation_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_GEOLOCATION_HANDLER_CAPI_H_ diff --git a/include/capi/cef_jsdialog_handler_capi.h b/include/capi/cef_jsdialog_handler_capi.h new file mode 100644 index 000000000..c141a0ef3 --- /dev/null +++ b/include/capi/cef_jsdialog_handler_capi.h @@ -0,0 +1,133 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure used for asynchronous continuation of JavaScript dialog +// requests. +/// +typedef struct _cef_jsdialog_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the JS dialog request. Set |success| to true (1) if the OK button + // was pressed. The |user_input| value should be specified for prompt dialogs. + /// + void (CEF_CALLBACK *cont)(struct _cef_jsdialog_callback_t* self, int success, + const cef_string_t* user_input); +} cef_jsdialog_callback_t; + + +/// +// Implement this structure to handle events related to JavaScript dialogs. The +// functions of this structure will be called on the UI thread. +/// +typedef struct _cef_jsdialog_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called to run a JavaScript dialog. The |default_prompt_text| value will be + // specified for prompt dialogs only. Set |suppress_message| to true (1) and + // return false (0) to suppress the message (suppressing messages is + // preferable to immediately executing the callback as this is used to detect + // presumably malicious behavior like spamming alert messages in + // onbeforeunload). Set |suppress_message| to false (0) and return false (0) + // to use the default implementation (the default implementation will show one + // modal dialog at a time and suppress any additional dialog requests until + // the displayed dialog is dismissed). Return true (1) if the application will + // use a custom dialog or if the callback has been executed immediately. + // Custom dialogs may be either modal or modeless. If a custom dialog is used + // the application must execute |callback| once the custom dialog is + // dismissed. + /// + int (CEF_CALLBACK *on_jsdialog)(struct _cef_jsdialog_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* origin_url, + const cef_string_t* accept_lang, cef_jsdialog_type_t dialog_type, + const cef_string_t* message_text, + const cef_string_t* default_prompt_text, + struct _cef_jsdialog_callback_t* callback, int* suppress_message); + + /// + // Called to run a dialog asking the user if they want to leave a page. Return + // false (0) to use the default dialog implementation. Return true (1) if the + // application will use a custom dialog or if the callback has been executed + // immediately. Custom dialogs may be either modal or modeless. If a custom + // dialog is used the application must execute |callback| once the custom + // dialog is dismissed. + /// + int (CEF_CALLBACK *on_before_unload_dialog)( + struct _cef_jsdialog_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* message_text, int is_reload, + struct _cef_jsdialog_callback_t* callback); + + /// + // Called to cancel any pending dialogs and reset any saved dialog state. Will + // be called due to events like page navigation irregardless of whether any + // dialogs are currently pending. + /// + void (CEF_CALLBACK *on_reset_dialog_state)( + struct _cef_jsdialog_handler_t* self, struct _cef_browser_t* browser); + + /// + // Called when the default implementation dialog is closed. + /// + void (CEF_CALLBACK *on_dialog_closed)(struct _cef_jsdialog_handler_t* self, + struct _cef_browser_t* browser); +} cef_jsdialog_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ diff --git a/include/capi/cef_keyboard_handler_capi.h b/include/capi/cef_keyboard_handler_capi.h new file mode 100644 index 000000000..d56b57bef --- /dev/null +++ b/include/capi/cef_keyboard_handler_capi.h @@ -0,0 +1,84 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_KEYBOARD_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_KEYBOARD_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events related to keyboard input. The +// functions of this structure will be called on the UI thread. +/// +typedef struct _cef_keyboard_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + // Called before a keyboard event is sent to the renderer. |event| contains + // information about the keyboard event. |os_event| is the operating system + // event message, if any. Return true (1) if the event was handled or false + // (0) otherwise. If the event will be handled in on_key_event() as a keyboard + // shortcut set |is_keyboard_shortcut| to true (1) and return false (0). + int (CEF_CALLBACK *on_pre_key_event)(struct _cef_keyboard_handler_t* self, + struct _cef_browser_t* browser, const struct _cef_key_event_t* event, + cef_event_handle_t os_event, int* is_keyboard_shortcut); + + /// + // Called after the renderer and JavaScript in the page has had a chance to + // handle the event. |event| contains information about the keyboard event. + // |os_event| is the operating system event message, if any. Return true (1) + // if the keyboard event was handled or false (0) otherwise. + /// + int (CEF_CALLBACK *on_key_event)(struct _cef_keyboard_handler_t* self, + struct _cef_browser_t* browser, const struct _cef_key_event_t* event, + cef_event_handle_t os_event); +} cef_keyboard_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_KEYBOARD_HANDLER_CAPI_H_ diff --git a/include/capi/cef_life_span_handler_capi.h b/include/capi/cef_life_span_handler_capi.h new file mode 100644 index 000000000..d1c2a2e16 --- /dev/null +++ b/include/capi/cef_life_span_handler_capi.h @@ -0,0 +1,171 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_client_t; + +/// +// Implement this structure to handle events related to browser life span. The +// functions of this structure will be called on the UI thread unless otherwise +// indicated. +/// +typedef struct _cef_life_span_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called on the IO thread before a new popup window is created. The |browser| + // and |frame| parameters represent the source of the popup request. The + // |target_url| and |target_frame_name| values may be NULL if none were + // specified with the request. The |popupFeatures| structure contains + // information about the requested popup window. To allow creation of the + // popup window optionally modify |windowInfo|, |client|, |settings| and + // |no_javascript_access| and return false (0). To cancel creation of the + // popup window return true (1). The |client| and |settings| values will + // default to the source browser's values. The |no_javascript_access| value + // indicates whether the new browser window should be scriptable and in the + // same process as the source browser. + int (CEF_CALLBACK *on_before_popup)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + const cef_string_t* target_url, const cef_string_t* target_frame_name, + const struct _cef_popup_features_t* popupFeatures, + struct _cef_window_info_t* windowInfo, struct _cef_client_t** client, + struct _cef_browser_settings_t* settings, int* no_javascript_access); + + /// + // Called after a new browser is created. + /// + void (CEF_CALLBACK *on_after_created)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Called when a modal window is about to display and the modal loop should + // begin running. Return false (0) to use the default modal loop + // implementation or true (1) to use a custom implementation. + /// + int (CEF_CALLBACK *run_modal)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Called when a browser has recieved a request to close. This may result + // directly from a call to cef_browser_host_t::close_browser() or indirectly + // if the browser is a top-level OS window created by CEF and the user + // attempts to close the window. This function will be called after the + // JavaScript 'onunload' event has been fired. It will not be called for + // browsers after the associated OS window has been destroyed (for those + // browsers it is no longer possible to cancel the close). + // + // If CEF created an OS window for the browser returning false (0) will send + // an OS close notification to the browser window's top-level owner (e.g. + // WM_CLOSE on Windows, performClose: on OS-X and "delete_event" on Linux). If + // no OS window exists (window rendering disabled) returning false (0) will + // cause the browser object to be destroyed immediately. Return true (1) if + // the browser is parented to another window and that other window needs to + // receive close notification via some non-standard technique. + // + // If an application provides its own top-level window it should handle OS + // close notifications by calling cef_browser_host_t::CloseBrowser(false (0)) + // instead of immediately closing (see the example below). This gives CEF an + // opportunity to process the 'onbeforeunload' event and optionally cancel the + // close before do_close() is called. + // + // The cef_life_span_handler_t::on_before_close() function will be called + // immediately before the browser object is destroyed. The application should + // only exit after on_before_close() has been called for all existing + // browsers. + // + // If the browser represents a modal window and a custom modal loop + // implementation was provided in cef_life_span_handler_t::run_modal() this + // callback should be used to restore the opener window to a usable state. + // + // By way of example consider what should happen during window close when the + // browser is parented to an application-provided top-level OS window. 1. + // User clicks the window close button which sends an OS close + // notification (e.g. WM_CLOSE on Windows, performClose: on OS-X and + // "delete_event" on Linux). + // 2. Application's top-level window receives the close notification and: + // A. Calls CefBrowserHost::CloseBrowser(false). + // B. Cancels the window close. + // 3. JavaScript 'onbeforeunload' handler executes and shows the close + // confirmation dialog (which can be overridden via + // CefJSDialogHandler::OnBeforeUnloadDialog()). + // 4. User approves the close. 5. JavaScript 'onunload' handler executes. 6. + // Application's do_close() handler is called. Application will: + // A. Set a flag to indicate that the next close attempt will be allowed. + // B. Return false. + // 7. CEF sends an OS close notification. 8. Application's top-level window + // receives the OS close notification and + // allows the window to close based on the flag from #6B. + // 9. Browser OS window is destroyed. 10. Application's + // cef_life_span_handler_t::on_before_close() handler is called and + // the browser object is destroyed. + // 11. Application exits by calling cef_quit_message_loop() if no other + // browsers + // exist. + /// + int (CEF_CALLBACK *do_close)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Called just before a browser is destroyed. Release all references to the + // browser object and do not attempt to execute any functions on the browser + // object after this callback returns. If this is a modal window and a custom + // modal loop implementation was provided in run_modal() this callback should + // be used to exit the custom modal loop. See do_close() documentation for + // additional usage information. + /// + void (CEF_CALLBACK *on_before_close)(struct _cef_life_span_handler_t* self, + struct _cef_browser_t* browser); +} cef_life_span_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_ diff --git a/include/capi/cef_load_handler_capi.h b/include/capi/cef_load_handler_capi.h new file mode 100644 index 000000000..2ce5d092b --- /dev/null +++ b/include/capi/cef_load_handler_capi.h @@ -0,0 +1,112 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_LOAD_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_LOAD_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events related to browser load status. The +// functions of this structure will be called on the browser process UI thread +// or render process main thread (TID_RENDERER). +/// +typedef struct _cef_load_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called when the loading state has changed. This callback will be executed + // twice -- once when loading is initiated either programmatically or by user + // action, and once when loading is terminated due to completion, cancellation + // of failure. + /// + void (CEF_CALLBACK *on_loading_state_change)(struct _cef_load_handler_t* self, + struct _cef_browser_t* browser, int isLoading, int canGoBack, + int canGoForward); + + /// + // Called when the browser begins loading a frame. The |frame| value will + // never be NULL -- call the is_main() function to check if this frame is the + // main frame. Multiple frames may be loading at the same time. Sub-frames may + // start or continue loading after the main frame load has ended. This + // function may not be called for a particular frame if the load request for + // that frame fails. For notification of overall browser load status use + // OnLoadingStateChange instead. + /// + void (CEF_CALLBACK *on_load_start)(struct _cef_load_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame); + + /// + // Called when the browser is done loading a frame. The |frame| value will + // never be NULL -- call the is_main() function to check if this frame is the + // main frame. Multiple frames may be loading at the same time. Sub-frames may + // start or continue loading after the main frame load has ended. This + // function will always be called for all frames irrespective of whether the + // request completes successfully. + /// + void (CEF_CALLBACK *on_load_end)(struct _cef_load_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + int httpStatusCode); + + /// + // Called when the resource load for a navigation fails or is canceled. + // |errorCode| is the error code number, |errorText| is the error text and + // |failedUrl| is the URL that failed to load. See net\base\net_error_list.h + // for complete descriptions of the error codes. + /// + void (CEF_CALLBACK *on_load_error)(struct _cef_load_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + cef_errorcode_t errorCode, const cef_string_t* errorText, + const cef_string_t* failedUrl); +} cef_load_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_LOAD_HANDLER_CAPI_H_ diff --git a/include/capi/cef_menu_model_capi.h b/include/capi/cef_menu_model_capi.h new file mode 100644 index 000000000..00f809677 --- /dev/null +++ b/include/capi/cef_menu_model_capi.h @@ -0,0 +1,388 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_MENU_MODEL_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_MENU_MODEL_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Supports creation and modification of menus. See cef_menu_id_t for the +// command ids that have default implementations. All user-defined command ids +// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The functions of +// this structure can only be accessed on the browser process the UI thread. +/// +typedef struct _cef_menu_model_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Clears the menu. Returns true (1) on success. + /// + int (CEF_CALLBACK *clear)(struct _cef_menu_model_t* self); + + /// + // Returns the number of items in this menu. + /// + int (CEF_CALLBACK *get_count)(struct _cef_menu_model_t* self); + + // + // Add a separator to the menu. Returns true (1) on success. + /// + int (CEF_CALLBACK *add_separator)(struct _cef_menu_model_t* self); + + // + // Add an item to the menu. Returns true (1) on success. + /// + int (CEF_CALLBACK *add_item)(struct _cef_menu_model_t* self, int command_id, + const cef_string_t* label); + + // + // Add a check item to the menu. Returns true (1) on success. + /// + int (CEF_CALLBACK *add_check_item)(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label); + + // + // Add a radio item to the menu. Only a single item with the specified + // |group_id| can be checked at a time. Returns true (1) on success. + /// + int (CEF_CALLBACK *add_radio_item)(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label, int group_id); + + // + // Add a sub-menu to the menu. The new sub-menu is returned. + /// + struct _cef_menu_model_t* (CEF_CALLBACK *add_sub_menu)( + struct _cef_menu_model_t* self, int command_id, + const cef_string_t* label); + + // + // Insert a separator in the menu at the specified |index|. Returns true (1) + // on success. + /// + int (CEF_CALLBACK *insert_separator_at)(struct _cef_menu_model_t* self, + int index); + + // + // Insert an item in the menu at the specified |index|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *insert_item_at)(struct _cef_menu_model_t* self, int index, + int command_id, const cef_string_t* label); + + // + // Insert a check item in the menu at the specified |index|. Returns true (1) + // on success. + /// + int (CEF_CALLBACK *insert_check_item_at)(struct _cef_menu_model_t* self, + int index, int command_id, const cef_string_t* label); + + // + // Insert a radio item in the menu at the specified |index|. Only a single + // item with the specified |group_id| can be checked at a time. Returns true + // (1) on success. + /// + int (CEF_CALLBACK *insert_radio_item_at)(struct _cef_menu_model_t* self, + int index, int command_id, const cef_string_t* label, int group_id); + + // + // Insert a sub-menu in the menu at the specified |index|. The new sub-menu is + // returned. + /// + struct _cef_menu_model_t* (CEF_CALLBACK *insert_sub_menu_at)( + struct _cef_menu_model_t* self, int index, int command_id, + const cef_string_t* label); + + /// + // Removes the item with the specified |command_id|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *remove)(struct _cef_menu_model_t* self, int command_id); + + /// + // Removes the item at the specified |index|. Returns true (1) on success. + /// + int (CEF_CALLBACK *remove_at)(struct _cef_menu_model_t* self, int index); + + /// + // Returns the index associated with the specified |command_id| or -1 if not + // found due to the command id not existing in the menu. + /// + int (CEF_CALLBACK *get_index_of)(struct _cef_menu_model_t* self, + int command_id); + + /// + // Returns the command id at the specified |index| or -1 if not found due to + // invalid range or the index being a separator. + /// + int (CEF_CALLBACK *get_command_id_at)(struct _cef_menu_model_t* self, + int index); + + /// + // Sets the command id at the specified |index|. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_command_id_at)(struct _cef_menu_model_t* self, + int index, int command_id); + + /// + // Returns the label for the specified |command_id| or NULL if not found. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_label)( + struct _cef_menu_model_t* self, int command_id); + + /// + // Returns the label at the specified |index| or NULL if not found due to + // invalid range or the index being a separator. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_label_at)( + struct _cef_menu_model_t* self, int index); + + /// + // Sets the label for the specified |command_id|. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_label)(struct _cef_menu_model_t* self, int command_id, + const cef_string_t* label); + + /// + // Set the label at the specified |index|. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_label_at)(struct _cef_menu_model_t* self, int index, + const cef_string_t* label); + + /// + // Returns the item type for the specified |command_id|. + /// + cef_menu_item_type_t (CEF_CALLBACK *get_type)(struct _cef_menu_model_t* self, + int command_id); + + /// + // Returns the item type at the specified |index|. + /// + cef_menu_item_type_t (CEF_CALLBACK *get_type_at)( + struct _cef_menu_model_t* self, int index); + + /// + // Returns the group id for the specified |command_id| or -1 if invalid. + /// + int (CEF_CALLBACK *get_group_id)(struct _cef_menu_model_t* self, + int command_id); + + /// + // Returns the group id at the specified |index| or -1 if invalid. + /// + int (CEF_CALLBACK *get_group_id_at)(struct _cef_menu_model_t* self, + int index); + + /// + // Sets the group id for the specified |command_id|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *set_group_id)(struct _cef_menu_model_t* self, + int command_id, int group_id); + + /// + // Sets the group id at the specified |index|. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_group_id_at)(struct _cef_menu_model_t* self, int index, + int group_id); + + /// + // Returns the submenu for the specified |command_id| or NULL if invalid. + /// + struct _cef_menu_model_t* (CEF_CALLBACK *get_sub_menu)( + struct _cef_menu_model_t* self, int command_id); + + /// + // Returns the submenu at the specified |index| or NULL if invalid. + /// + struct _cef_menu_model_t* (CEF_CALLBACK *get_sub_menu_at)( + struct _cef_menu_model_t* self, int index); + + // + // Returns true (1) if the specified |command_id| is visible. + /// + int (CEF_CALLBACK *is_visible)(struct _cef_menu_model_t* self, + int command_id); + + // + // Returns true (1) if the specified |index| is visible. + /// + int (CEF_CALLBACK *is_visible_at)(struct _cef_menu_model_t* self, int index); + + // + // Change the visibility of the specified |command_id|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *set_visible)(struct _cef_menu_model_t* self, + int command_id, int visible); + + // + // Change the visibility at the specified |index|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *set_visible_at)(struct _cef_menu_model_t* self, int index, + int visible); + + // + // Returns true (1) if the specified |command_id| is enabled. + /// + int (CEF_CALLBACK *is_enabled)(struct _cef_menu_model_t* self, + int command_id); + + // + // Returns true (1) if the specified |index| is enabled. + /// + int (CEF_CALLBACK *is_enabled_at)(struct _cef_menu_model_t* self, int index); + + // + // Change the enabled status of the specified |command_id|. Returns true (1) + // on success. + /// + int (CEF_CALLBACK *set_enabled)(struct _cef_menu_model_t* self, + int command_id, int enabled); + + // + // Change the enabled status at the specified |index|. Returns true (1) on + // success. + /// + int (CEF_CALLBACK *set_enabled_at)(struct _cef_menu_model_t* self, int index, + int enabled); + + // + // Returns true (1) if the specified |command_id| is checked. Only applies to + // check and radio items. + /// + int (CEF_CALLBACK *is_checked)(struct _cef_menu_model_t* self, + int command_id); + + // + // Returns true (1) if the specified |index| is checked. Only applies to check + // and radio items. + /// + int (CEF_CALLBACK *is_checked_at)(struct _cef_menu_model_t* self, int index); + + // + // Check the specified |command_id|. Only applies to check and radio items. + // Returns true (1) on success. + /// + int (CEF_CALLBACK *set_checked)(struct _cef_menu_model_t* self, + int command_id, int checked); + + // + // Check the specified |index|. Only applies to check and radio items. Returns + // true (1) on success. + /// + int (CEF_CALLBACK *set_checked_at)(struct _cef_menu_model_t* self, int index, + int checked); + + // + // Returns true (1) if the specified |command_id| has a keyboard accelerator + // assigned. + /// + int (CEF_CALLBACK *has_accelerator)(struct _cef_menu_model_t* self, + int command_id); + + // + // Returns true (1) if the specified |index| has a keyboard accelerator + // assigned. + /// + int (CEF_CALLBACK *has_accelerator_at)(struct _cef_menu_model_t* self, + int index); + + // + // Set the keyboard accelerator for the specified |command_id|. |key_code| can + // be any virtual key or character value. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_accelerator)(struct _cef_menu_model_t* self, + int command_id, int key_code, int shift_pressed, int ctrl_pressed, + int alt_pressed); + + // + // Set the keyboard accelerator at the specified |index|. |key_code| can be + // any virtual key or character value. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_accelerator_at)(struct _cef_menu_model_t* self, + int index, int key_code, int shift_pressed, int ctrl_pressed, + int alt_pressed); + + // + // Remove the keyboard accelerator for the specified |command_id|. Returns + // true (1) on success. + /// + int (CEF_CALLBACK *remove_accelerator)(struct _cef_menu_model_t* self, + int command_id); + + // + // Remove the keyboard accelerator at the specified |index|. Returns true (1) + // on success. + /// + int (CEF_CALLBACK *remove_accelerator_at)(struct _cef_menu_model_t* self, + int index); + + // + // Retrieves the keyboard accelerator for the specified |command_id|. Returns + // true (1) on success. + /// + int (CEF_CALLBACK *get_accelerator)(struct _cef_menu_model_t* self, + int command_id, int* key_code, int* shift_pressed, int* ctrl_pressed, + int* alt_pressed); + + // + // Retrieves the keyboard accelerator for the specified |index|. Returns true + // (1) on success. + /// + int (CEF_CALLBACK *get_accelerator_at)(struct _cef_menu_model_t* self, + int index, int* key_code, int* shift_pressed, int* ctrl_pressed, + int* alt_pressed); +} cef_menu_model_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_MENU_MODEL_CAPI_H_ diff --git a/include/capi/cef_origin_whitelist_capi.h b/include/capi/cef_origin_whitelist_capi.h new file mode 100644 index 000000000..00ed36133 --- /dev/null +++ b/include/capi/cef_origin_whitelist_capi.h @@ -0,0 +1,106 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_ORIGIN_WHITELIST_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_ORIGIN_WHITELIST_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Add an entry to the cross-origin access whitelist. +// +// The same-origin policy restricts how scripts hosted from different origins +// (scheme + domain + port) can communicate. By default, scripts can only access +// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes +// (but no other schemes) can use the "Access-Control-Allow-Origin" header to +// allow cross-origin requests. For example, https://source.example.com can make +// XMLHttpRequest requests on http://target.example.com if the +// http://target.example.com request returns an "Access-Control-Allow-Origin: +// https://source.example.com" response header. +// +// Scripts in separate frames or iframes and hosted from the same protocol and +// domain suffix can execute cross-origin JavaScript if both pages set the +// document.domain value to the same domain suffix. For example, +// scheme://foo.example.com and scheme://bar.example.com can communicate using +// JavaScript if both domains set document.domain="example.com". +// +// This function is used to allow access to origins that would otherwise violate +// the same-origin policy. Scripts hosted underneath the fully qualified +// |source_origin| URL (like http://www.example.com) will be allowed access to +// all resources hosted on the specified |target_protocol| and |target_domain|. +// If |target_domain| is non-NULL and |allow_target_subdomains| if false (0) +// only exact domain matches will be allowed. If |target_domain| contains a top- +// level domain component (like "example.com") and |allow_target_subdomains| is +// true (1) sub-domain matches will be allowed. If |target_domain| is NULL and +// |allow_target_subdomains| if true (1) all domains and IP addresses will be +// allowed. +// +// This function cannot be used to bypass the restrictions on local or display +// isolated schemes. See the comments on CefRegisterCustomScheme for more +// information. +// +// This function may be called on any thread. Returns false (0) if +// |source_origin| is invalid or the whitelist cannot be accessed. +/// +CEF_EXPORT int cef_add_cross_origin_whitelist_entry( + const cef_string_t* source_origin, const cef_string_t* target_protocol, + const cef_string_t* target_domain, int allow_target_subdomains); + +/// +// Remove an entry from the cross-origin access whitelist. Returns false (0) if +// |source_origin| is invalid or the whitelist cannot be accessed. +/// +CEF_EXPORT int cef_remove_cross_origin_whitelist_entry( + const cef_string_t* source_origin, const cef_string_t* target_protocol, + const cef_string_t* target_domain, int allow_target_subdomains); + +/// +// Remove all entries from the cross-origin access whitelist. Returns false (0) +// if the whitelist cannot be accessed. +/// +CEF_EXPORT int cef_clear_cross_origin_whitelist(); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_ORIGIN_WHITELIST_CAPI_H_ diff --git a/include/capi/cef_path_util_capi.h b/include/capi/cef_path_util_capi.h new file mode 100644 index 000000000..a81f897f8 --- /dev/null +++ b/include/capi/cef_path_util_capi.h @@ -0,0 +1,58 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_PATH_UTIL_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_PATH_UTIL_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Retrieve the path associated with the specified |key|. Returns true (1) on +// success. Can be called on any thread in the browser process. +/// +CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_PATH_UTIL_CAPI_H_ diff --git a/include/capi/cef_print_handler_capi.h b/include/capi/cef_print_handler_capi.h new file mode 100644 index 000000000..4e12aeb57 --- /dev/null +++ b/include/capi/cef_print_handler_capi.h @@ -0,0 +1,134 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_PRINT_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_PRINT_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_print_settings_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure for asynchronous continuation of print dialog requests. +/// +typedef struct _cef_print_dialog_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue printing with the specified |settings|. + /// + void (CEF_CALLBACK *cont)(struct _cef_print_dialog_callback_t* self, + struct _cef_print_settings_t* settings); + + /// + // Cancel the printing. + /// + void (CEF_CALLBACK *cancel)(struct _cef_print_dialog_callback_t* self); +} cef_print_dialog_callback_t; + + +/// +// Callback structure for asynchronous continuation of print job requests. +/// +typedef struct _cef_print_job_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Indicate completion of the print job. + /// + void (CEF_CALLBACK *cont)(struct _cef_print_job_callback_t* self); +} cef_print_job_callback_t; + + +/// +// Implement this structure to handle printing on Linux. The functions of this +// structure will be called on the browser process UI thread. +/// +typedef struct _cef_print_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Synchronize |settings| with client state. If |get_defaults| is true (1) + // then populate |settings| with the default print settings. Do not keep a + // reference to |settings| outside of this callback. + /// + void (CEF_CALLBACK *on_print_settings)(struct _cef_print_handler_t* self, + struct _cef_print_settings_t* settings, int get_defaults); + + /// + // Show the print dialog. Execute |callback| once the dialog is dismissed. + // Return true (1) if the dialog will be displayed or false (0) to cancel the + // printing immediately. + /// + int (CEF_CALLBACK *on_print_dialog)(struct _cef_print_handler_t* self, + int has_selection, struct _cef_print_dialog_callback_t* callback); + + /// + // Send the print job to the printer. Execute |callback| once the job is + // completed. Return true (1) if the job will proceed or false (0) to cancel + // the job immediately. + /// + int (CEF_CALLBACK *on_print_job)(struct _cef_print_handler_t* self, + const cef_string_t* document_name, const cef_string_t* pdf_file_path, + struct _cef_print_job_callback_t* callback); + + /// + // Reset client state related to printing. + /// + void (CEF_CALLBACK *on_print_reset)(struct _cef_print_handler_t* self); +} cef_print_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_PRINT_HANDLER_CAPI_H_ diff --git a/include/capi/cef_print_settings_capi.h b/include/capi/cef_print_settings_capi.h new file mode 100644 index 000000000..e38da68e5 --- /dev/null +++ b/include/capi/cef_print_settings_capi.h @@ -0,0 +1,207 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_PRINT_SETTINGS_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_PRINT_SETTINGS_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure representing print settings. +/// +typedef struct _cef_print_settings_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_print_settings_t* self); + + /// + // Returns true (1) if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_print_settings_t* self); + + /// + // Returns a writable copy of this object. + /// + struct _cef_print_settings_t* (CEF_CALLBACK *copy)( + struct _cef_print_settings_t* self); + + /// + // Set the page orientation. + /// + void (CEF_CALLBACK *set_orientation)(struct _cef_print_settings_t* self, + int landscape); + + /// + // Returns true (1) if the orientation is landscape. + /// + int (CEF_CALLBACK *is_landscape)(struct _cef_print_settings_t* self); + + /// + // Set the printer printable area in device units. Some platforms already + // provide flipped area. Set |landscape_needs_flip| to false (0) on those + // platforms to avoid double flipping. + /// + void (CEF_CALLBACK *set_printer_printable_area)( + struct _cef_print_settings_t* self, + const cef_size_t* physical_size_device_units, + const cef_rect_t* printable_area_device_units, + int landscape_needs_flip); + + /// + // Set the device name. + /// + void (CEF_CALLBACK *set_device_name)(struct _cef_print_settings_t* self, + const cef_string_t* name); + + /// + // Get the device name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_device_name)( + struct _cef_print_settings_t* self); + + /// + // Set the DPI (dots per inch). + /// + void (CEF_CALLBACK *set_dpi)(struct _cef_print_settings_t* self, int dpi); + + /// + // Get the DPI (dots per inch). + /// + int (CEF_CALLBACK *get_dpi)(struct _cef_print_settings_t* self); + + /// + // Set the page ranges. + /// + void (CEF_CALLBACK *set_page_ranges)(struct _cef_print_settings_t* self, + size_t rangesCount, cef_page_range_t const* ranges); + + /// + // Returns the number of page ranges that currently exist. + /// + size_t (CEF_CALLBACK *get_page_ranges_count)( + struct _cef_print_settings_t* self); + + /// + // Retrieve the page ranges. + /// + void (CEF_CALLBACK *get_page_ranges)(struct _cef_print_settings_t* self, + size_t* rangesCount, cef_page_range_t* ranges); + + /// + // Set whether only the selection will be printed. + /// + void (CEF_CALLBACK *set_selection_only)(struct _cef_print_settings_t* self, + int selection_only); + + /// + // Returns true (1) if only the selection will be printed. + /// + int (CEF_CALLBACK *is_selection_only)(struct _cef_print_settings_t* self); + + /// + // Set whether pages will be collated. + /// + void (CEF_CALLBACK *set_collate)(struct _cef_print_settings_t* self, + int collate); + + /// + // Returns true (1) if pages will be collated. + /// + int (CEF_CALLBACK *will_collate)(struct _cef_print_settings_t* self); + + /// + // Set the color model. + /// + void (CEF_CALLBACK *set_color_model)(struct _cef_print_settings_t* self, + cef_color_model_t model); + + /// + // Get the color model. + /// + cef_color_model_t (CEF_CALLBACK *get_color_model)( + struct _cef_print_settings_t* self); + + /// + // Set the number of copies. + /// + void (CEF_CALLBACK *set_copies)(struct _cef_print_settings_t* self, + int copies); + + /// + // Get the number of copies. + /// + int (CEF_CALLBACK *get_copies)(struct _cef_print_settings_t* self); + + /// + // Set the duplex mode. + /// + void (CEF_CALLBACK *set_duplex_mode)(struct _cef_print_settings_t* self, + cef_duplex_mode_t mode); + + /// + // Get the duplex mode. + /// + cef_duplex_mode_t (CEF_CALLBACK *get_duplex_mode)( + struct _cef_print_settings_t* self); +} cef_print_settings_t; + + +/// +// Create a new cef_print_settings_t object. +/// +CEF_EXPORT cef_print_settings_t* cef_print_settings_create(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_PRINT_SETTINGS_CAPI_H_ diff --git a/include/capi/cef_process_message_capi.h b/include/capi/cef_process_message_capi.h new file mode 100644 index 000000000..fd35b6b6b --- /dev/null +++ b/include/capi/cef_process_message_capi.h @@ -0,0 +1,102 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_PROCESS_MESSAGE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_PROCESS_MESSAGE_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_values_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure representing a message. Can be used on any process and thread. +/// +typedef struct _cef_process_message_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_process_message_t* self); + + /// + // Returns true (1) if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_process_message_t* self); + + /// + // Returns a writable copy of this object. + /// + struct _cef_process_message_t* (CEF_CALLBACK *copy)( + struct _cef_process_message_t* self); + + /// + // Returns the message name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_name)( + struct _cef_process_message_t* self); + + /// + // Returns the list of arguments. + /// + struct _cef_list_value_t* (CEF_CALLBACK *get_argument_list)( + struct _cef_process_message_t* self); +} cef_process_message_t; + + +/// +// Create a new cef_process_message_t object with the specified name. +/// +CEF_EXPORT cef_process_message_t* cef_process_message_create( + const cef_string_t* name); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_PROCESS_MESSAGE_CAPI_H_ diff --git a/include/capi/cef_process_util_capi.h b/include/capi/cef_process_util_capi.h new file mode 100644 index 000000000..2d90d30ac --- /dev/null +++ b/include/capi/cef_process_util_capi.h @@ -0,0 +1,64 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_PROCESS_UTIL_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_PROCESS_UTIL_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Launches the process specified via |command_line|. Returns true (1) upon +// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread. +// +// Unix-specific notes: - All file descriptors open in the parent process will +// be closed in the +// child process except for stdin, stdout, and stderr. +// - If the first argument on the command line does not contain a slash, +// PATH will be searched. (See man execvp.) +/// +CEF_EXPORT int cef_launch_process(struct _cef_command_line_t* command_line); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_PROCESS_UTIL_CAPI_H_ diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h new file mode 100644 index 000000000..151292c8e --- /dev/null +++ b/include/capi/cef_render_handler_capi.h @@ -0,0 +1,163 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_drag_data_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to handle events when window rendering is disabled. +// The functions of this structure will be called on the UI thread. +/// +typedef struct _cef_render_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called to retrieve the root window rectangle in screen coordinates. Return + // true (1) if the rectangle was provided. + /// + int (CEF_CALLBACK *get_root_screen_rect)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, cef_rect_t* rect); + + /// + // Called to retrieve the view rectangle which is relative to screen + // coordinates. Return true (1) if the rectangle was provided. + /// + int (CEF_CALLBACK *get_view_rect)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, cef_rect_t* rect); + + /// + // Called to retrieve the translation from view coordinates to actual screen + // coordinates. Return true (1) if the screen coordinates were provided. + /// + int (CEF_CALLBACK *get_screen_point)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, int viewX, int viewY, int* screenX, + int* screenY); + + /// + // Called to allow the client to fill in the CefScreenInfo object with + // appropriate values. Return true (1) if the |screen_info| structure has been + // modified. + // + // If the screen info rectangle is left NULL the rectangle from GetViewRect + // will be used. If the rectangle is still NULL or invalid popups may not be + // drawn correctly. + /// + int (CEF_CALLBACK *get_screen_info)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, struct _cef_screen_info_t* screen_info); + + /// + // Called when the browser wants to show or hide the popup widget. The popup + // should be shown if |show| is true (1) and hidden if |show| is false (0). + /// + void (CEF_CALLBACK *on_popup_show)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, int show); + + /// + // Called when the browser wants to move or resize the popup widget. |rect| + // contains the new location and size. + /// + void (CEF_CALLBACK *on_popup_size)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, const cef_rect_t* rect); + + /// + // Called when an element should be painted. |type| indicates whether the + // element is the view or the popup widget. |buffer| contains the pixel data + // for the whole image. |dirtyRects| contains the set of rectangles that need + // to be repainted. On Windows |buffer| will be |width|*|height|*4 bytes in + // size and represents a BGRA image with an upper-left origin. + /// + void (CEF_CALLBACK *on_paint)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, cef_paint_element_type_t type, + size_t dirtyRectsCount, cef_rect_t const* dirtyRects, const void* buffer, + int width, int height); + + /// + // Called when the browser window's cursor has changed. + /// + void (CEF_CALLBACK *on_cursor_change)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, cef_cursor_handle_t cursor); + + /// + // Called when the user starts dragging content in the web view. Contextual + // information about the dragged content is supplied by |drag_data|. OS APIs + // that run a system message loop may be used within the StartDragging call. + // + // Return false (0) to abort the drag operation. Don't call any of + // cef_browser_host_t::DragSource*Ended* functions after returning false (0). + // + // Return true (1) to handle the drag operation. Call + // cef_browser_host_t::DragSourceEndedAt and DragSourceSystemDragEnded either + // synchronously or asynchronously to inform the web view that the drag + // operation has ended. + /// + int (CEF_CALLBACK *start_dragging)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, struct _cef_drag_data_t* drag_data, + cef_drag_operations_mask_t allowed_ops, int x, int y); + + /// + // Called when the web view wants to update the mouse cursor during a drag & + // drop operation. |operation| describes the allowed operation (none, move, + // copy, link). + /// + void (CEF_CALLBACK *update_drag_cursor)(struct _cef_render_handler_t* self, + struct _cef_browser_t* browser, cef_drag_operations_mask_t operation); + + /// + // Called when the scroll offset has changed. + /// + void (CEF_CALLBACK *on_scroll_offset_changed)( + struct _cef_render_handler_t* self, struct _cef_browser_t* browser); +} cef_render_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ diff --git a/include/capi/cef_render_process_handler_capi.h b/include/capi/cef_render_process_handler_capi.h new file mode 100644 index 000000000..6593108e2 --- /dev/null +++ b/include/capi/cef_render_process_handler_capi.h @@ -0,0 +1,177 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_RENDER_PROCESS_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_RENDER_PROCESS_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_dom_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_load_handler_capi.h" +#include "include/capi/cef_process_message_capi.h" +#include "include/capi/cef_v8_capi.h" +#include "include/capi/cef_values_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to implement render process callbacks. The functions of this +// structure will be called on the render process main thread (TID_RENDERER) +// unless otherwise indicated. +/// +typedef struct _cef_render_process_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called after the render process main thread has been created. |extra_info| + // is a read-only value originating from + // cef_browser_process_handler_t::on_render_process_thread_created(). Do not + // keep a reference to |extra_info| outside of this function. + /// + void (CEF_CALLBACK *on_render_thread_created)( + struct _cef_render_process_handler_t* self, + struct _cef_list_value_t* extra_info); + + /// + // Called after WebKit has been initialized. + /// + void (CEF_CALLBACK *on_web_kit_initialized)( + struct _cef_render_process_handler_t* self); + + /// + // Called after a browser has been created. When browsing cross-origin a new + // browser will be created before the old browser with the same identifier is + // destroyed. + /// + void (CEF_CALLBACK *on_browser_created)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Called before a browser is destroyed. + /// + void (CEF_CALLBACK *on_browser_destroyed)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser); + + /// + // Return the handler for browser load status events. + /// + struct _cef_load_handler_t* (CEF_CALLBACK *get_load_handler)( + struct _cef_render_process_handler_t* self); + + /// + // Called before browser navigation. Return true (1) to cancel the navigation + // or false (0) to allow the navigation to proceed. The |request| object + // cannot be modified in this callback. + /// + int (CEF_CALLBACK *on_before_navigation)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_request_t* request, cef_navigation_type_t navigation_type, + int is_redirect); + + /// + // Called immediately after the V8 context for a frame has been created. To + // retrieve the JavaScript 'window' object use the + // cef_v8context_t::get_global() function. V8 handles can only be accessed + // from the thread on which they are created. A task runner for posting tasks + // on the associated thread can be retrieved via the + // cef_v8context_t::get_task_runner() function. + /// + void (CEF_CALLBACK *on_context_created)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_v8context_t* context); + + /// + // Called immediately before the V8 context for a frame is released. No + // references to the context should be kept after this function is called. + /// + void (CEF_CALLBACK *on_context_released)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_v8context_t* context); + + /// + // Called for global uncaught exceptions in a frame. Execution of this + // callback is disabled by default. To enable set + // CefSettings.uncaught_exception_stack_size > 0. + /// + void (CEF_CALLBACK *on_uncaught_exception)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_v8context_t* context, struct _cef_v8exception_t* exception, + struct _cef_v8stack_trace_t* stackTrace); + + /// + // Called when a new node in the the browser gets focus. The |node| value may + // be NULL if no specific node has gained focus. The node object passed to + // this function represents a snapshot of the DOM at the time this function is + // executed. DOM objects are only valid for the scope of this function. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this function. + /// + void (CEF_CALLBACK *on_focused_node_changed)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_domnode_t* node); + + /// + // Called when a new message is received from a different process. Return true + // (1) if the message was handled or false (0) otherwise. Do not keep a + // reference to or attempt to access the message outside of this callback. + /// + int (CEF_CALLBACK *on_process_message_received)( + struct _cef_render_process_handler_t* self, + struct _cef_browser_t* browser, cef_process_id_t source_process, + struct _cef_process_message_t* message); +} cef_render_process_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_RENDER_PROCESS_HANDLER_CAPI_H_ diff --git a/include/capi/cef_request_capi.h b/include/capi/cef_request_capi.h new file mode 100644 index 000000000..3af22a8c7 --- /dev/null +++ b/include/capi/cef_request_capi.h @@ -0,0 +1,293 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_REQUEST_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_post_data_element_t; +struct _cef_post_data_t; + +/// +// Structure used to represent a web request. The functions of this structure +// may be called on any thread. +/// +typedef struct _cef_request_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is read-only. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_request_t* self); + + /// + // Get the fully qualified URL. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_url)(struct _cef_request_t* self); + + /// + // Set the fully qualified URL. + /// + void (CEF_CALLBACK *set_url)(struct _cef_request_t* self, + const cef_string_t* url); + + /// + // Get the request function type. The value will default to POST if post data + // is provided and GET otherwise. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_method)(struct _cef_request_t* self); + + /// + // Set the request function type. + /// + void (CEF_CALLBACK *set_method)(struct _cef_request_t* self, + const cef_string_t* method); + + /// + // Get the post data. + /// + struct _cef_post_data_t* (CEF_CALLBACK *get_post_data)( + struct _cef_request_t* self); + + /// + // Set the post data. + /// + void (CEF_CALLBACK *set_post_data)(struct _cef_request_t* self, + struct _cef_post_data_t* postData); + + /// + // Get the header values. + /// + void (CEF_CALLBACK *get_header_map)(struct _cef_request_t* self, + cef_string_multimap_t headerMap); + + /// + // Set the header values. + /// + void (CEF_CALLBACK *set_header_map)(struct _cef_request_t* self, + cef_string_multimap_t headerMap); + + /// + // Set all values at one time. + /// + void (CEF_CALLBACK *set)(struct _cef_request_t* self, const cef_string_t* url, + const cef_string_t* method, struct _cef_post_data_t* postData, + cef_string_multimap_t headerMap); + + /// + // Get the flags used in combination with cef_urlrequest_t. See + // cef_urlrequest_flags_t for supported values. + /// + int (CEF_CALLBACK *get_flags)(struct _cef_request_t* self); + + /// + // Set the flags used in combination with cef_urlrequest_t. See + // cef_urlrequest_flags_t for supported values. + /// + void (CEF_CALLBACK *set_flags)(struct _cef_request_t* self, int flags); + + /// + // Set the URL to the first party for cookies used in combination with + // cef_urlrequest_t. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_first_party_for_cookies)( + struct _cef_request_t* self); + + /// + // Get the URL to the first party for cookies used in combination with + // cef_urlrequest_t. + /// + void (CEF_CALLBACK *set_first_party_for_cookies)(struct _cef_request_t* self, + const cef_string_t* url); + + /// + // Get the resource type for this request. Accurate resource type information + // may only be available in the browser process. + /// + cef_resource_type_t (CEF_CALLBACK *get_resource_type)( + struct _cef_request_t* self); + + /// + // Get the transition type for this request. Only available in the browser + // process and only applies to requests that represent a main frame or sub- + // frame navigation. + /// + cef_transition_type_t (CEF_CALLBACK *get_transition_type)( + struct _cef_request_t* self); +} cef_request_t; + + +/// +// Create a new cef_request_t object. +/// +CEF_EXPORT cef_request_t* cef_request_create(); + + +/// +// Structure used to represent post data for a web request. The functions of +// this structure may be called on any thread. +/// +typedef struct _cef_post_data_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is read-only. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_post_data_t* self); + + /// + // Returns the number of existing post data elements. + /// + size_t (CEF_CALLBACK *get_element_count)(struct _cef_post_data_t* self); + + /// + // Retrieve the post data elements. + /// + void (CEF_CALLBACK *get_elements)(struct _cef_post_data_t* self, + size_t* elementsCount, struct _cef_post_data_element_t** elements); + + /// + // Remove the specified post data element. Returns true (1) if the removal + // succeeds. + /// + int (CEF_CALLBACK *remove_element)(struct _cef_post_data_t* self, + struct _cef_post_data_element_t* element); + + /// + // Add the specified post data element. Returns true (1) if the add succeeds. + /// + int (CEF_CALLBACK *add_element)(struct _cef_post_data_t* self, + struct _cef_post_data_element_t* element); + + /// + // Remove all existing post data elements. + /// + void (CEF_CALLBACK *remove_elements)(struct _cef_post_data_t* self); +} cef_post_data_t; + + +/// +// Create a new cef_post_data_t object. +/// +CEF_EXPORT cef_post_data_t* cef_post_data_create(); + + +/// +// Structure used to represent a single element in the request post data. The +// functions of this structure may be called on any thread. +/// +typedef struct _cef_post_data_element_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is read-only. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_post_data_element_t* self); + + /// + // Remove all contents from the post data element. + /// + void (CEF_CALLBACK *set_to_empty)(struct _cef_post_data_element_t* self); + + /// + // The post data element will represent a file. + /// + void (CEF_CALLBACK *set_to_file)(struct _cef_post_data_element_t* self, + const cef_string_t* fileName); + + /// + // The post data element will represent bytes. The bytes passed in will be + // copied. + /// + void (CEF_CALLBACK *set_to_bytes)(struct _cef_post_data_element_t* self, + size_t size, const void* bytes); + + /// + // Return the type of this post data element. + /// + cef_postdataelement_type_t (CEF_CALLBACK *get_type)( + struct _cef_post_data_element_t* self); + + /// + // Return the file name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_file)( + struct _cef_post_data_element_t* self); + + /// + // Return the number of bytes. + /// + size_t (CEF_CALLBACK *get_bytes_count)(struct _cef_post_data_element_t* self); + + /// + // Read up to |size| bytes into |bytes| and return the number of bytes + // actually read. + /// + size_t (CEF_CALLBACK *get_bytes)(struct _cef_post_data_element_t* self, + size_t size, void* bytes); +} cef_post_data_element_t; + + +/// +// Create a new cef_post_data_element_t object. +/// +CEF_EXPORT cef_post_data_element_t* cef_post_data_element_create(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_REQUEST_CAPI_H_ diff --git a/include/capi/cef_request_context_capi.h b/include/capi/cef_request_context_capi.h new file mode 100644 index 000000000..e6c40d040 --- /dev/null +++ b/include/capi/cef_request_context_capi.h @@ -0,0 +1,105 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_ +#pragma once + +#include "include/capi/cef_request_context_handler_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// A request context provides request handling for a set of related browser +// objects. A request context is specified when creating a new browser object +// via the cef_browser_host_t static factory functions. Browser objects with +// different request contexts will never be hosted in the same render process. +// Browser objects with the same request context may or may not be hosted in the +// same render process depending on the process model. Browser objects created +// indirectly via the JavaScript window.open function or targeted links will +// share the same render process and the same request context as the source +// browser. When running in single-process mode there is only a single render +// process (the main process) and so all browsers created in single-process mode +// will share the same request context. This will be the first request context +// passed into a cef_browser_host_t static factory function and all other +// request context objects will be ignored. +/// +typedef struct _cef_request_context_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is pointing to the same context as |that| + // object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_request_context_t* self, + struct _cef_request_context_t* other); + + /// + // Returns true (1) if this object is the global context. + /// + int (CEF_CALLBACK *is_global)(struct _cef_request_context_t* self); + + /// + // Returns the handler for this context if any. + /// + struct _cef_request_context_handler_t* (CEF_CALLBACK *get_handler)( + struct _cef_request_context_t* self); +} cef_request_context_t; + + +/// +// Returns the global context object. +/// +CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context(); + +/// +// Creates a new context object with the specified handler. +/// +CEF_EXPORT cef_request_context_t* cef_request_context_create_context( + struct _cef_request_context_handler_t* handler); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_ diff --git a/include/capi/cef_request_context_handler_capi.h b/include/capi/cef_request_context_handler_capi.h new file mode 100644 index 000000000..326701ae7 --- /dev/null +++ b/include/capi/cef_request_context_handler_capi.h @@ -0,0 +1,71 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_cookie_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to provide handler implementations. +/// +typedef struct _cef_request_context_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called on the IO thread to retrieve the cookie manager. The global cookie + // manager will be used if this function returns NULL. + /// + struct _cef_cookie_manager_t* (CEF_CALLBACK *get_cookie_manager)( + struct _cef_request_context_handler_t* self); +} cef_request_context_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_HANDLER_CAPI_H_ diff --git a/include/capi/cef_request_handler_capi.h b/include/capi/cef_request_handler_capi.h new file mode 100644 index 000000000..bdd5da0c7 --- /dev/null +++ b/include/capi/cef_request_handler_capi.h @@ -0,0 +1,226 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_auth_callback_capi.h" +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_request_capi.h" +#include "include/capi/cef_resource_handler_capi.h" +#include "include/capi/cef_response_capi.h" +#include "include/capi/cef_web_plugin_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Callback structure used for asynchronous continuation of quota requests. +/// +typedef struct _cef_quota_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the quota request. If |allow| is true (1) the request will be + // allowed. Otherwise, the request will be denied. + /// + void (CEF_CALLBACK *cont)(struct _cef_quota_callback_t* self, int allow); + + /// + // Cancel the quota request. + /// + void (CEF_CALLBACK *cancel)(struct _cef_quota_callback_t* self); +} cef_quota_callback_t; + + +/// +// Callback structure used for asynchronous continuation of url requests when +// invalid SSL certificates are encountered. +/// +typedef struct _cef_allow_certificate_error_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the url request. If |allow| is true (1) the request will be + // continued. Otherwise, the request will be canceled. + /// + void (CEF_CALLBACK *cont)( + struct _cef_allow_certificate_error_callback_t* self, int allow); +} cef_allow_certificate_error_callback_t; + + +/// +// Implement this structure to handle events related to browser requests. The +// functions of this structure will be called on the thread indicated. +/// +typedef struct _cef_request_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called on the UI thread before browser navigation. Return true (1) to + // cancel the navigation or false (0) to allow the navigation to proceed. The + // |request| object cannot be modified in this callback. + // cef_load_handler_t::OnLoadingStateChange will be called twice in all cases. + // If the navigation is allowed cef_load_handler_t::OnLoadStart and + // cef_load_handler_t::OnLoadEnd will be called. If the navigation is canceled + // cef_load_handler_t::OnLoadError will be called with an |errorCode| value of + // ERR_ABORTED. + /// + int (CEF_CALLBACK *on_before_browse)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + struct _cef_request_t* request, int is_redirect); + + /// + // Called on the IO thread before a resource request is loaded. The |request| + // object may be modified. To cancel the request return true (1) otherwise + // return false (0). + /// + int (CEF_CALLBACK *on_before_resource_load)( + struct _cef_request_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_request_t* request); + + /// + // Called on the IO thread before a resource is loaded. To allow the resource + // to load normally return NULL. To specify a handler for the resource return + // a cef_resource_handler_t object. The |request| object should not be + // modified in this callback. + /// + struct _cef_resource_handler_t* (CEF_CALLBACK *get_resource_handler)( + struct _cef_request_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_request_t* request); + + /// + // Called on the IO thread when a resource load is redirected. The |old_url| + // parameter will contain the old URL. The |new_url| parameter will contain + // the new URL and can be changed if desired. + /// + void (CEF_CALLBACK *on_resource_redirect)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + const cef_string_t* old_url, cef_string_t* new_url); + + /// + // Called on the IO thread when the browser needs credentials from the user. + // |isProxy| indicates whether the host is a proxy server. |host| contains the + // hostname and |port| contains the port number. Return true (1) to continue + // the request and call cef_auth_callback_t::cont() when the authentication + // information is available. Return false (0) to cancel the request. + /// + int (CEF_CALLBACK *get_auth_credentials)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, int isProxy, + const cef_string_t* host, int port, const cef_string_t* realm, + const cef_string_t* scheme, struct _cef_auth_callback_t* callback); + + /// + // Called on the IO thread when JavaScript requests a specific storage quota + // size via the webkitStorageInfo.requestQuota function. |origin_url| is the + // origin of the page making the request. |new_size| is the requested quota + // size in bytes. Return true (1) and call cef_quota_callback_t::cont() either + // in this function or at a later time to grant or deny the request. Return + // false (0) to cancel the request. + /// + int (CEF_CALLBACK *on_quota_request)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* origin_url, + int64 new_size, struct _cef_quota_callback_t* callback); + + /// + // Called on the UI thread to handle requests for URLs with an unknown + // protocol component. Set |allow_os_execution| to true (1) to attempt + // execution via the registered OS protocol handler, if any. SECURITY WARNING: + // YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED ON SCHEME, HOST OR + // OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION. + /// + void (CEF_CALLBACK *on_protocol_execution)( + struct _cef_request_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* url, int* allow_os_execution); + + /// + // Called on the UI thread to handle requests for URLs with an invalid SSL + // certificate. Return true (1) and call + // cef_allow_certificate_error_callback_t:: cont() either in this function or + // at a later time to continue or cancel the request. Return false (0) to + // cancel the request immediately. If |callback| is NULL the error cannot be + // recovered from and the request will be canceled automatically. If + // CefSettings.ignore_certificate_errors is set all invalid certificates will + // be accepted without calling this function. + /// + int (CEF_CALLBACK *on_certificate_error)(struct _cef_request_handler_t* self, + cef_errorcode_t cert_error, const cef_string_t* request_url, + struct _cef_allow_certificate_error_callback_t* callback); + + /// + // Called on the browser process IO thread before a plugin is loaded. Return + // true (1) to block loading of the plugin. + /// + int (CEF_CALLBACK *on_before_plugin_load)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* url, + const cef_string_t* policy_url, struct _cef_web_plugin_info_t* info); + + /// + // Called on the browser process UI thread when a plugin has crashed. + // |plugin_path| is the path of the plugin that crashed. + /// + void (CEF_CALLBACK *on_plugin_crashed)(struct _cef_request_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* plugin_path); + + /// + // Called on the browser process UI thread when the render process terminates + // unexpectedly. |status| indicates how the process terminated. + /// + void (CEF_CALLBACK *on_render_process_terminated)( + struct _cef_request_handler_t* self, struct _cef_browser_t* browser, + cef_termination_status_t status); +} cef_request_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_ diff --git a/include/capi/cef_resource_bundle_handler_capi.h b/include/capi/cef_resource_bundle_handler_capi.h new file mode 100644 index 000000000..e0ea76bc6 --- /dev/null +++ b/include/capi/cef_resource_bundle_handler_capi.h @@ -0,0 +1,86 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_BUNDLE_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_RESOURCE_BUNDLE_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to implement a custom resource bundle structure. The functions +// of this structure may be called on multiple threads. +/// +typedef struct _cef_resource_bundle_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called to retrieve a localized translation for the string specified by + // |message_id|. To provide the translation set |string| to the translation + // string and return true (1). To use the default translation return false + // (0). Supported message IDs are listed in cef_pack_strings.h. + /// + int (CEF_CALLBACK *get_localized_string)( + struct _cef_resource_bundle_handler_t* self, int message_id, + cef_string_t* string); + + /// + // Called to retrieve data for the resource specified by |resource_id|. To + // provide the resource data set |data| and |data_size| to the data pointer + // and size respectively and return true (1). To use the default resource data + // return false (0). The resource data will not be copied and must remain + // resident in memory. Supported resource IDs are listed in + // cef_pack_resources.h. + /// + int (CEF_CALLBACK *get_data_resource)( + struct _cef_resource_bundle_handler_t* self, int resource_id, void** data, + size_t* data_size); +} cef_resource_bundle_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_RESOURCE_BUNDLE_HANDLER_CAPI_H_ diff --git a/include/capi/cef_resource_handler_capi.h b/include/capi/cef_resource_handler_capi.h new file mode 100644 index 000000000..24bba9b41 --- /dev/null +++ b/include/capi/cef_resource_handler_capi.h @@ -0,0 +1,124 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_RESOURCE_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_RESOURCE_HANDLER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_callback_capi.h" +#include "include/capi/cef_cookie_capi.h" +#include "include/capi/cef_request_capi.h" +#include "include/capi/cef_response_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to implement a custom request handler structure. The functions +// of this structure will always be called on the IO thread. +/// +typedef struct _cef_resource_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Begin processing the request. To handle the request return true (1) and + // call cef_callback_t::cont() once the response header information is + // available (cef_callback_t::cont() can also be called from inside this + // function if header information is available immediately). To cancel the + // request return false (0). + /// + int (CEF_CALLBACK *process_request)(struct _cef_resource_handler_t* self, + struct _cef_request_t* request, struct _cef_callback_t* callback); + + /// + // Retrieve response header information. If the response length is not known + // set |response_length| to -1 and read_response() will be called until it + // returns false (0). If the response length is known set |response_length| to + // a positive value and read_response() will be called until it returns false + // (0) or the specified number of bytes have been read. Use the |response| + // object to set the mime type, http status code and other optional header + // values. To redirect the request to a new URL set |redirectUrl| to the new + // URL. + /// + void (CEF_CALLBACK *get_response_headers)( + struct _cef_resource_handler_t* self, struct _cef_response_t* response, + int64* response_length, cef_string_t* redirectUrl); + + /// + // Read response data. If data is available immediately copy up to + // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of + // bytes copied, and return true (1). To read the data at a later time set + // |bytes_read| to 0, return true (1) and call cef_callback_t::cont() when the + // data is available. To indicate response completion return false (0). + /// + int (CEF_CALLBACK *read_response)(struct _cef_resource_handler_t* self, + void* data_out, int bytes_to_read, int* bytes_read, + struct _cef_callback_t* callback); + + /// + // Return true (1) if the specified cookie can be sent with the request or + // false (0) otherwise. If false (0) is returned for any cookie then no + // cookies will be sent with the request. + /// + int (CEF_CALLBACK *can_get_cookie)(struct _cef_resource_handler_t* self, + const struct _cef_cookie_t* cookie); + + /// + // Return true (1) if the specified cookie returned with the response can be + // set or false (0) otherwise. + /// + int (CEF_CALLBACK *can_set_cookie)(struct _cef_resource_handler_t* self, + const struct _cef_cookie_t* cookie); + + /// + // Request processing has been canceled. + /// + void (CEF_CALLBACK *cancel)(struct _cef_resource_handler_t* self); +} cef_resource_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_RESOURCE_HANDLER_CAPI_H_ diff --git a/include/capi/cef_response_capi.h b/include/capi/cef_response_capi.h new file mode 100644 index 000000000..30b3c945c --- /dev/null +++ b/include/capi/cef_response_capi.h @@ -0,0 +1,130 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_RESPONSE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_RESPONSE_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure used to represent a web response. The functions of this structure +// may be called on any thread. +/// +typedef struct _cef_response_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is read-only. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_response_t* self); + + /// + // Get the response status code. + /// + int (CEF_CALLBACK *get_status)(struct _cef_response_t* self); + + /// + // Set the response status code. + /// + void (CEF_CALLBACK *set_status)(struct _cef_response_t* self, int status); + + /// + // Get the response status text. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_status_text)( + struct _cef_response_t* self); + + /// + // Set the response status text. + /// + void (CEF_CALLBACK *set_status_text)(struct _cef_response_t* self, + const cef_string_t* statusText); + + /// + // Get the response mime type. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_mime_type)( + struct _cef_response_t* self); + + /// + // Set the response mime type. + /// + void (CEF_CALLBACK *set_mime_type)(struct _cef_response_t* self, + const cef_string_t* mimeType); + + /// + // Get the value for the specified response header field. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_header)(struct _cef_response_t* self, + const cef_string_t* name); + + /// + // Get all response header fields. + /// + void (CEF_CALLBACK *get_header_map)(struct _cef_response_t* self, + cef_string_multimap_t headerMap); + + /// + // Set all response header fields. + /// + void (CEF_CALLBACK *set_header_map)(struct _cef_response_t* self, + cef_string_multimap_t headerMap); +} cef_response_t; + + +/// +// Create a new cef_response_t object. +/// +CEF_EXPORT cef_response_t* cef_response_create(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_RESPONSE_CAPI_H_ diff --git a/include/capi/cef_scheme_capi.h b/include/capi/cef_scheme_capi.h new file mode 100644 index 000000000..e993be243 --- /dev/null +++ b/include/capi/cef_scheme_capi.h @@ -0,0 +1,168 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_SCHEME_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_SCHEME_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_request_capi.h" +#include "include/capi/cef_resource_handler_capi.h" +#include "include/capi/cef_response_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_scheme_handler_factory_t; + +/// +// Structure that manages custom scheme registrations. +/// +typedef struct _cef_scheme_registrar_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Register a custom scheme. This function should not be called for the built- + // in HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes. + // + // If |is_standard| is true (1) the scheme will be treated as a standard + // scheme. Standard schemes are subject to URL canonicalization and parsing + // rules as defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 + // available at http://www.ietf.org/rfc/rfc1738.txt + // + // In particular, the syntax for standard scheme URLs must be of the form: + //
+  //  [scheme]://[username]:[password]@[host]:[port]/[url-path]
+  // 
Standard scheme URLs must have a host component that is a fully + // qualified domain name as defined in Section 3.5 of RFC 1034 [13] and + // Section 2.1 of RFC 1123. These URLs will be canonicalized to + // "scheme://host/path" in the simplest case and + // "scheme://username:password@host:port/path" in the most explicit case. For + // example, "scheme:host/path" and "scheme:///host/path" will both be + // canonicalized to "scheme://host/path". The origin of a standard scheme URL + // is the combination of scheme, host and port (i.e., "scheme://host:port" in + // the most explicit case). + // + // For non-standard scheme URLs only the "scheme:" component is parsed and + // canonicalized. The remainder of the URL will be passed to the handler as- + // is. For example, "scheme:///some%20text" will remain the same. Non-standard + // scheme URLs cannot be used as a target for form submission. + // + // If |is_local| is true (1) the scheme will be treated as local (i.e., with + // the same security rules as those applied to "file" URLs). Normal pages + // cannot link to or access local URLs. Also, by default, local URLs can only + // perform XMLHttpRequest calls to the same URL (origin + path) that + // originated the request. To allow XMLHttpRequest calls from a local URL to + // other URLs with the same origin set the + // CefSettings.file_access_from_file_urls_allowed value to true (1). To allow + // XMLHttpRequest calls from a local URL to all origins set the + // CefSettings.universal_access_from_file_urls_allowed value to true (1). + // + // If |is_display_isolated| is true (1) the scheme will be treated as display- + // isolated. This means that pages cannot display these URLs unless they are + // from the same scheme. For example, pages in another origin cannot create + // iframes or hyperlinks to URLs with this scheme. + // + // This function may be called on any thread. It should only be called once + // per unique |scheme_name| value. If |scheme_name| is already registered or + // if an error occurs this function will return false (0). + /// + int (CEF_CALLBACK *add_custom_scheme)(struct _cef_scheme_registrar_t* self, + const cef_string_t* scheme_name, int is_standard, int is_local, + int is_display_isolated); +} cef_scheme_registrar_t; + + +/// +// Structure that creates cef_resource_handler_t instances for handling scheme +// requests. The functions of this structure will always be called on the IO +// thread. +/// +typedef struct _cef_scheme_handler_factory_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Return a new resource handler instance to handle the request or an NULL + // reference to allow default handling of the request. |browser| and |frame| + // will be the browser window and frame respectively that originated the + // request or NULL if the request did not originate from a browser window (for + // example, if the request came from cef_urlrequest_t). The |request| object + // passed to this function will not contain cookie data. + /// + struct _cef_resource_handler_t* (CEF_CALLBACK *create)( + struct _cef_scheme_handler_factory_t* self, + struct _cef_browser_t* browser, struct _cef_frame_t* frame, + const cef_string_t* scheme_name, struct _cef_request_t* request); +} cef_scheme_handler_factory_t; + + +/// +// Register a scheme handler factory for the specified |scheme_name| and +// optional |domain_name|. An NULL |domain_name| value for a standard scheme +// will cause the factory to match all domain names. The |domain_name| value +// will be ignored for non-standard schemes. If |scheme_name| is a built-in +// scheme and no handler is returned by |factory| then the built-in scheme +// handler factory will be called. If |scheme_name| is a custom scheme then also +// implement the cef_app_t::on_register_custom_schemes() function in all +// processes. This function may be called multiple times to change or remove the +// factory that matches the specified |scheme_name| and optional |domain_name|. +// Returns false (0) if an error occurs. This function may be called on any +// thread in the browser process. +/// +CEF_EXPORT int cef_register_scheme_handler_factory( + const cef_string_t* scheme_name, const cef_string_t* domain_name, + cef_scheme_handler_factory_t* factory); + +/// +// Clear all registered scheme handler factories. Returns false (0) on error. +// This function may be called on any thread in the browser process. +/// +CEF_EXPORT int cef_clear_scheme_handler_factories(); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_SCHEME_CAPI_H_ diff --git a/include/capi/cef_stream_capi.h b/include/capi/cef_stream_capi.h new file mode 100644 index 000000000..8e393b3b2 --- /dev/null +++ b/include/capi/cef_stream_capi.h @@ -0,0 +1,252 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_STREAM_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_STREAM_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure the client can implement to provide a custom stream reader. The +// functions of this structure may be called on any thread. +/// +typedef struct _cef_read_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Read raw binary data. + /// + size_t (CEF_CALLBACK *read)(struct _cef_read_handler_t* self, void* ptr, + size_t size, size_t n); + + /// + // Seek to the specified offset position. |whence| may be any one of SEEK_CUR, + // SEEK_END or SEEK_SET. Return zero on success and non-zero on failure. + /// + int (CEF_CALLBACK *seek)(struct _cef_read_handler_t* self, int64 offset, + int whence); + + /// + // Return the current offset position. + /// + int64 (CEF_CALLBACK *tell)(struct _cef_read_handler_t* self); + + /// + // Return non-zero if at end of file. + /// + int (CEF_CALLBACK *eof)(struct _cef_read_handler_t* self); + + /// + // Return true (1) if this handler performs work like accessing the file + // system which may block. Used as a hint for determining the thread to access + // the handler from. + /// + int (CEF_CALLBACK *may_block)(struct _cef_read_handler_t* self); +} cef_read_handler_t; + + +/// +// Structure used to read data from a stream. The functions of this structure +// may be called on any thread. +/// +typedef struct _cef_stream_reader_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Read raw binary data. + /// + size_t (CEF_CALLBACK *read)(struct _cef_stream_reader_t* self, void* ptr, + size_t size, size_t n); + + /// + // Seek to the specified offset position. |whence| may be any one of SEEK_CUR, + // SEEK_END or SEEK_SET. Returns zero on success and non-zero on failure. + /// + int (CEF_CALLBACK *seek)(struct _cef_stream_reader_t* self, int64 offset, + int whence); + + /// + // Return the current offset position. + /// + int64 (CEF_CALLBACK *tell)(struct _cef_stream_reader_t* self); + + /// + // Return non-zero if at end of file. + /// + int (CEF_CALLBACK *eof)(struct _cef_stream_reader_t* self); + + /// + // Returns true (1) if this reader performs work like accessing the file + // system which may block. Used as a hint for determining the thread to access + // the reader from. + /// + int (CEF_CALLBACK *may_block)(struct _cef_stream_reader_t* self); +} cef_stream_reader_t; + + +/// +// Create a new cef_stream_reader_t object from a file. +/// +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_file( + const cef_string_t* fileName); + +/// +// Create a new cef_stream_reader_t object from data. +/// +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_data(void* data, + size_t size); + +/// +// Create a new cef_stream_reader_t object from a custom handler. +/// +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_handler( + cef_read_handler_t* handler); + + +/// +// Structure the client can implement to provide a custom stream writer. The +// functions of this structure may be called on any thread. +/// +typedef struct _cef_write_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Write raw binary data. + /// + size_t (CEF_CALLBACK *write)(struct _cef_write_handler_t* self, + const void* ptr, size_t size, size_t n); + + /// + // Seek to the specified offset position. |whence| may be any one of SEEK_CUR, + // SEEK_END or SEEK_SET. Return zero on success and non-zero on failure. + /// + int (CEF_CALLBACK *seek)(struct _cef_write_handler_t* self, int64 offset, + int whence); + + /// + // Return the current offset position. + /// + int64 (CEF_CALLBACK *tell)(struct _cef_write_handler_t* self); + + /// + // Flush the stream. + /// + int (CEF_CALLBACK *flush)(struct _cef_write_handler_t* self); + + /// + // Return true (1) if this handler performs work like accessing the file + // system which may block. Used as a hint for determining the thread to access + // the handler from. + /// + int (CEF_CALLBACK *may_block)(struct _cef_write_handler_t* self); +} cef_write_handler_t; + + +/// +// Structure used to write data to a stream. The functions of this structure may +// be called on any thread. +/// +typedef struct _cef_stream_writer_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Write raw binary data. + /// + size_t (CEF_CALLBACK *write)(struct _cef_stream_writer_t* self, + const void* ptr, size_t size, size_t n); + + /// + // Seek to the specified offset position. |whence| may be any one of SEEK_CUR, + // SEEK_END or SEEK_SET. Returns zero on success and non-zero on failure. + /// + int (CEF_CALLBACK *seek)(struct _cef_stream_writer_t* self, int64 offset, + int whence); + + /// + // Return the current offset position. + /// + int64 (CEF_CALLBACK *tell)(struct _cef_stream_writer_t* self); + + /// + // Flush the stream. + /// + int (CEF_CALLBACK *flush)(struct _cef_stream_writer_t* self); + + /// + // Returns true (1) if this writer performs work like accessing the file + // system which may block. Used as a hint for determining the thread to access + // the writer from. + /// + int (CEF_CALLBACK *may_block)(struct _cef_stream_writer_t* self); +} cef_stream_writer_t; + + +/// +// Create a new cef_stream_writer_t object for a file. +/// +CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_file( + const cef_string_t* fileName); + +/// +// Create a new cef_stream_writer_t object for a custom handler. +/// +CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_handler( + cef_write_handler_t* handler); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_STREAM_CAPI_H_ diff --git a/include/capi/cef_string_visitor_capi.h b/include/capi/cef_string_visitor_capi.h new file mode 100644 index 000000000..f047ffe5a --- /dev/null +++ b/include/capi/cef_string_visitor_capi.h @@ -0,0 +1,69 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_STRING_VISITOR_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_STRING_VISITOR_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to receive string values asynchronously. +/// +typedef struct _cef_string_visitor_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be executed. + /// + void (CEF_CALLBACK *visit)(struct _cef_string_visitor_t* self, + const cef_string_t* string); +} cef_string_visitor_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_STRING_VISITOR_CAPI_H_ diff --git a/include/capi/cef_task_capi.h b/include/capi/cef_task_capi.h new file mode 100644 index 000000000..2c803348f --- /dev/null +++ b/include/capi/cef_task_capi.h @@ -0,0 +1,159 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_TASK_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_TASK_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure for asynchronous task execution. If the task is +// posted successfully and if the associated message loop is still running then +// the execute() function will be called on the target thread. If the task fails +// to post then the task object may be destroyed on the source thread instead of +// the target thread. For this reason be cautious when performing work in the +// task object destructor. +/// +typedef struct _cef_task_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be executed on the target thread. + /// + void (CEF_CALLBACK *execute)(struct _cef_task_t* self); +} cef_task_t; + + +/// +// Structure that asynchronously executes tasks on the associated thread. It is +// safe to call the functions of this structure on any thread. +// +// CEF maintains multiple internal threads that are used for handling different +// types of tasks in different processes. The cef_thread_id_t definitions in +// cef_types.h list the common CEF threads. Task runners are also available for +// other CEF threads as appropriate (for example, V8 WebWorker threads). +/// +typedef struct _cef_task_runner_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is pointing to the same task runner as + // |that| object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_task_runner_t* self, + struct _cef_task_runner_t* that); + + /// + // Returns true (1) if this task runner belongs to the current thread. + /// + int (CEF_CALLBACK *belongs_to_current_thread)( + struct _cef_task_runner_t* self); + + /// + // Returns true (1) if this task runner is for the specified CEF thread. + /// + int (CEF_CALLBACK *belongs_to_thread)(struct _cef_task_runner_t* self, + cef_thread_id_t threadId); + + /// + // Post a task for execution on the thread associated with this task runner. + // Execution will occur asynchronously. + /// + int (CEF_CALLBACK *post_task)(struct _cef_task_runner_t* self, + struct _cef_task_t* task); + + /// + // Post a task for delayed execution on the thread associated with this task + // runner. Execution will occur asynchronously. Delayed tasks are not + // supported on V8 WebWorker threads and will be executed without the + // specified delay. + /// + int (CEF_CALLBACK *post_delayed_task)(struct _cef_task_runner_t* self, + struct _cef_task_t* task, int64 delay_ms); +} cef_task_runner_t; + + +/// +// Returns the task runner for the current thread. Only CEF threads will have +// task runners. An NULL reference will be returned if this function is called +// on an invalid thread. +/// +CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread(); + +/// +// Returns the task runner for the specified CEF thread. +/// +CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_thread( + cef_thread_id_t threadId); + + +/// +// Returns true (1) if called on the specified thread. Equivalent to using +// cef_task_tRunner::GetForThread(threadId)->belongs_to_current_thread(). +/// +CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId); + +/// +// Post a task for execution on the specified thread. Equivalent to using +// cef_task_tRunner::GetForThread(threadId)->PostTask(task). +/// +CEF_EXPORT int cef_post_task(cef_thread_id_t threadId, cef_task_t* task); + +/// +// Post a task for delayed execution on the specified thread. Equivalent to +// using cef_task_tRunner::GetForThread(threadId)->PostDelayedTask(task, +// delay_ms). +/// +CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId, cef_task_t* task, + int64 delay_ms); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_TASK_CAPI_H_ diff --git a/include/capi/cef_trace_capi.h b/include/capi/cef_trace_capi.h new file mode 100644 index 000000000..d298ad96f --- /dev/null +++ b/include/capi/cef_trace_capi.h @@ -0,0 +1,118 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_TRACE_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_TRACE_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_callback_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Implement this structure to receive notification when tracing has completed. +// The functions of this structure will be called on the browser process UI +// thread. +/// +typedef struct _cef_end_tracing_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called after all processes have sent their trace data. |tracing_file| is + // the path at which tracing data was written. The client is responsible for + // deleting |tracing_file|. + /// + void (CEF_CALLBACK *on_end_tracing_complete)( + struct _cef_end_tracing_callback_t* self, + const cef_string_t* tracing_file); +} cef_end_tracing_callback_t; + + +/// +// Start tracing events on all processes. Tracing is initialized asynchronously +// and |callback| will be executed on the UI thread after initialization is +// complete. +// +// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is +// pending, CefBeginTracing will fail and return false (0). +// +// |categories| is a comma-delimited list of category wildcards. A category can +// have an optional '-' prefix to make it an excluded category. Having both +// included and excluded categories in the same list is not supported. +// +// Example: "test_MyTest*" Example: "test_MyTest*,test_OtherStuff" Example: +// "-excluded_category1,-excluded_category2" +// +// This function must be called on the browser process UI thread. +/// +CEF_EXPORT int cef_begin_tracing(const cef_string_t* categories, + struct _cef_completion_callback_t* callback); + +/// +// Stop tracing events on all processes. +// +// This function will fail and return false (0) if a previous call to +// CefEndTracingAsync is already pending or if CefBeginTracing was not called. +// +// |tracing_file| is the path at which tracing data will be written and +// |callback| is the callback that will be executed once all processes have sent +// their trace data. If |tracing_file| is NULL a new temporary file path will be +// used. If |callback| is NULL no trace data will be written. +// +// This function must be called on the browser process UI thread. +/// +CEF_EXPORT int cef_end_tracing(const cef_string_t* tracing_file, + cef_end_tracing_callback_t* callback); + +/// +// Returns the current system trace time or, if none is defined, the current +// high-res time. Can be used by clients to synchronize with the time +// information in trace events. +/// +CEF_EXPORT int64 cef_now_from_system_trace_time(); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_TRACE_CAPI_H_ diff --git a/include/capi/cef_url_capi.h b/include/capi/cef_url_capi.h new file mode 100644 index 000000000..c9e22aad7 --- /dev/null +++ b/include/capi/cef_url_capi.h @@ -0,0 +1,82 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_URL_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_URL_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Parse the specified |url| into its component parts. Returns false (0) if the +// URL is NULL or invalid. +/// +CEF_EXPORT int cef_parse_url(const cef_string_t* url, + struct _cef_urlparts_t* parts); + +/// +// Creates a URL from the specified |parts|, which must contain a non-NULL spec +// or a non-NULL host and path (at a minimum), but not both. Returns false (0) +// if |parts| isn't initialized as described. +/// +CEF_EXPORT int cef_create_url(const struct _cef_urlparts_t* parts, + cef_string_t* url); + +/// +// Returns the mime type for the specified file extension or an NULL string if +// unknown. +/// +// The resulting string must be freed by calling cef_string_userfree_free(). +CEF_EXPORT cef_string_userfree_t cef_get_mime_type( + const cef_string_t* extension); + +// Get the extensions associated with the given mime type. This should be passed +// in lower case. There could be multiple extensions for a given mime type, like +// "html,htm" for "text/html", or "txt,text,html,..." for "text/*". Any existing +// elements in the provided vector will not be erased. +CEF_EXPORT void cef_get_extensions_for_mime_type(const cef_string_t* mime_type, + cef_string_list_t extensions); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_URL_CAPI_H_ diff --git a/include/capi/cef_urlrequest_capi.h b/include/capi/cef_urlrequest_capi.h new file mode 100644 index 000000000..b396aa67d --- /dev/null +++ b/include/capi/cef_urlrequest_capi.h @@ -0,0 +1,189 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_ +#pragma once + +#include "include/capi/cef_auth_callback_capi.h" +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_request_capi.h" +#include "include/capi/cef_response_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_urlrequest_client_t; + +/// +// Structure used to make a URL request. URL requests are not associated with a +// browser instance so no cef_client_t callbacks will be executed. URL requests +// can be created on any valid CEF thread in either the browser or render +// process. Once created the functions of the URL request object must be +// accessed on the same thread that created it. +/// +typedef struct _cef_urlrequest_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the request object used to create this URL request. The returned + // object is read-only and should not be modified. + /// + struct _cef_request_t* (CEF_CALLBACK *get_request)( + struct _cef_urlrequest_t* self); + + /// + // Returns the client. + /// + struct _cef_urlrequest_client_t* (CEF_CALLBACK *get_client)( + struct _cef_urlrequest_t* self); + + /// + // Returns the request status. + /// + cef_urlrequest_status_t (CEF_CALLBACK *get_request_status)( + struct _cef_urlrequest_t* self); + + /// + // Returns the request error if status is UR_CANCELED or UR_FAILED, or 0 + // otherwise. + /// + cef_errorcode_t (CEF_CALLBACK *get_request_error)( + struct _cef_urlrequest_t* self); + + /// + // Returns the response, or NULL if no response information is available. + // Response information will only be available after the upload has completed. + // The returned object is read-only and should not be modified. + /// + struct _cef_response_t* (CEF_CALLBACK *get_response)( + struct _cef_urlrequest_t* self); + + /// + // Cancel the request. + /// + void (CEF_CALLBACK *cancel)(struct _cef_urlrequest_t* self); +} cef_urlrequest_t; + + +/// +// Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request +// functions are supported. Multiple post data elements are not supported and +// elements of type PDE_TYPE_FILE are only supported for requests originating +// from the browser process. Requests originating from the render process will +// receive the same handling as requests originating from Web content -- if the +// response contains Content-Disposition or Mime-Type header values that would +// not normally be rendered then the response may receive special handling +// inside the browser (for example, via the file download code path instead of +// the URL request code path). The |request| object will be marked as read-only +// after calling this function. +/// +CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create( + struct _cef_request_t* request, struct _cef_urlrequest_client_t* client); + + +/// +// Structure that should be implemented by the cef_urlrequest_t client. The +// functions of this structure will be called on the same thread that created +// the request unless otherwise documented. +/// +typedef struct _cef_urlrequest_client_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Notifies the client that the request has completed. Use the + // cef_urlrequest_t::GetRequestStatus function to determine if the request was + // successful or not. + /// + void (CEF_CALLBACK *on_request_complete)( + struct _cef_urlrequest_client_t* self, + struct _cef_urlrequest_t* request); + + /// + // Notifies the client of upload progress. |current| denotes the number of + // bytes sent so far and |total| is the total size of uploading data (or -1 if + // chunked upload is enabled). This function will only be called if the + // UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request. + /// + void (CEF_CALLBACK *on_upload_progress)(struct _cef_urlrequest_client_t* self, + struct _cef_urlrequest_t* request, uint64 current, uint64 total); + + /// + // Notifies the client of download progress. |current| denotes the number of + // bytes received up to the call and |total| is the expected total size of the + // response (or -1 if not determined). + /// + void (CEF_CALLBACK *on_download_progress)( + struct _cef_urlrequest_client_t* self, struct _cef_urlrequest_t* request, + uint64 current, uint64 total); + + /// + // Called when some part of the response is read. |data| contains the current + // bytes received since the last call. This function will not be called if the + // UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request. + /// + void (CEF_CALLBACK *on_download_data)(struct _cef_urlrequest_client_t* self, + struct _cef_urlrequest_t* request, const void* data, + size_t data_length); + + /// + // Called on the IO thread when the browser needs credentials from the user. + // |isProxy| indicates whether the host is a proxy server. |host| contains the + // hostname and |port| contains the port number. Return true (1) to continue + // the request and call cef_auth_callback_t::cont() when the authentication + // information is available. Return false (0) to cancel the request. This + // function will only be called for requests initiated from the browser + // process. + /// + int (CEF_CALLBACK *get_auth_credentials)( + struct _cef_urlrequest_client_t* self, int isProxy, + const cef_string_t* host, int port, const cef_string_t* realm, + const cef_string_t* scheme, struct _cef_auth_callback_t* callback); +} cef_urlrequest_client_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_URLREQUEST_CAPI_H_ diff --git a/include/capi/cef_v8_capi.h b/include/capi/cef_v8_capi.h new file mode 100644 index 000000000..4953be31e --- /dev/null +++ b/include/capi/cef_v8_capi.h @@ -0,0 +1,851 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" +#include "include/capi/cef_frame_capi.h" +#include "include/capi/cef_task_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_v8exception_t; +struct _cef_v8handler_t; +struct _cef_v8stack_frame_t; +struct _cef_v8value_t; + +/// +// Structure representing a V8 context handle. V8 handles can only be accessed +// from the thread on which they are created. Valid threads for creating a V8 +// handle include the render process main thread (TID_RENDERER) and WebWorker +// threads. A task runner for posting tasks on the associated thread can be +// retrieved via the cef_v8context_t::get_task_runner() function. +/// +typedef struct _cef_v8context_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the task runner associated with this context. V8 handles can only + // be accessed from the thread on which they are created. This function can be + // called on any render process thread. + /// + struct _cef_task_runner_t* (CEF_CALLBACK *get_task_runner)( + struct _cef_v8context_t* self); + + /// + // Returns true (1) if the underlying handle is valid and it can be accessed + // on the current thread. Do not call any other functions if this function + // returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_v8context_t* self); + + /// + // Returns the browser for this context. This function will return an NULL + // reference for WebWorker contexts. + /// + struct _cef_browser_t* (CEF_CALLBACK *get_browser)( + struct _cef_v8context_t* self); + + /// + // Returns the frame for this context. This function will return an NULL + // reference for WebWorker contexts. + /// + struct _cef_frame_t* (CEF_CALLBACK *get_frame)(struct _cef_v8context_t* self); + + /// + // Returns the global object for this context. The context must be entered + // before calling this function. + /// + struct _cef_v8value_t* (CEF_CALLBACK *get_global)( + struct _cef_v8context_t* self); + + /// + // Enter this context. A context must be explicitly entered before creating a + // V8 Object, Array, Function or Date asynchronously. exit() must be called + // the same number of times as enter() before releasing this context. V8 + // objects belong to the context in which they are created. Returns true (1) + // if the scope was entered successfully. + /// + int (CEF_CALLBACK *enter)(struct _cef_v8context_t* self); + + /// + // Exit this context. Call this function only after calling enter(). Returns + // true (1) if the scope was exited successfully. + /// + int (CEF_CALLBACK *exit)(struct _cef_v8context_t* self); + + /// + // Returns true (1) if this object is pointing to the same handle as |that| + // object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_v8context_t* self, + struct _cef_v8context_t* that); + + /// + // Evaluates the specified JavaScript code using this context's global object. + // On success |retval| will be set to the return value, if any, and the + // function will return true (1). On failure |exception| will be set to the + // exception, if any, and the function will return false (0). + /// + int (CEF_CALLBACK *eval)(struct _cef_v8context_t* self, + const cef_string_t* code, struct _cef_v8value_t** retval, + struct _cef_v8exception_t** exception); +} cef_v8context_t; + + +/// +// Returns the current (top) context object in the V8 context stack. +/// +CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context(); + +/// +// Returns the entered (bottom) context object in the V8 context stack. +/// +CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context(); + +/// +// Returns true (1) if V8 is currently inside a context. +/// +CEF_EXPORT int cef_v8context_in_context(); + + +/// +// Structure that should be implemented to handle V8 function calls. The +// functions of this structure will be called on the thread associated with the +// V8 function. +/// +typedef struct _cef_v8handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Handle execution of the function identified by |name|. |object| is the + // receiver ('this' object) of the function. |arguments| is the list of + // arguments passed to the function. If execution succeeds set |retval| to the + // function return value. If execution fails set |exception| to the exception + // that will be thrown. Return true (1) if execution was handled. + /// + int (CEF_CALLBACK *execute)(struct _cef_v8handler_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + size_t argumentsCount, struct _cef_v8value_t* const* arguments, + struct _cef_v8value_t** retval, cef_string_t* exception); +} cef_v8handler_t; + + +/// +// Structure that should be implemented to handle V8 accessor calls. Accessor +// identifiers are registered by calling cef_v8value_t::set_value_byaccessor(). +// The functions of this structure will be called on the thread associated with +// the V8 accessor. +/// +typedef struct _cef_v8accessor_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Handle retrieval the accessor value identified by |name|. |object| is the + // receiver ('this' object) of the accessor. If retrieval succeeds set + // |retval| to the return value. If retrieval fails set |exception| to the + // exception that will be thrown. Return true (1) if accessor retrieval was + // handled. + /// + int (CEF_CALLBACK *get)(struct _cef_v8accessor_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + struct _cef_v8value_t** retval, cef_string_t* exception); + + /// + // Handle assignment of the accessor value identified by |name|. |object| is + // the receiver ('this' object) of the accessor. |value| is the new value + // being assigned to the accessor. If assignment fails set |exception| to the + // exception that will be thrown. Return true (1) if accessor assignment was + // handled. + /// + int (CEF_CALLBACK *set)(struct _cef_v8accessor_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + struct _cef_v8value_t* value, cef_string_t* exception); +} cef_v8accessor_t; + + +/// +// Structure representing a V8 exception. The functions of this structure may be +// called on any render process thread. +/// +typedef struct _cef_v8exception_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the exception message. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_message)( + struct _cef_v8exception_t* self); + + /// + // Returns the line of source code that the exception occurred within. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_source_line)( + struct _cef_v8exception_t* self); + + /// + // Returns the resource name for the script from where the function causing + // the error originates. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_script_resource_name)( + struct _cef_v8exception_t* self); + + /// + // Returns the 1-based number of the line where the error occurred or 0 if the + // line number is unknown. + /// + int (CEF_CALLBACK *get_line_number)(struct _cef_v8exception_t* self); + + /// + // Returns the index within the script of the first character where the error + // occurred. + /// + int (CEF_CALLBACK *get_start_position)(struct _cef_v8exception_t* self); + + /// + // Returns the index within the script of the last character where the error + // occurred. + /// + int (CEF_CALLBACK *get_end_position)(struct _cef_v8exception_t* self); + + /// + // Returns the index within the line of the first character where the error + // occurred. + /// + int (CEF_CALLBACK *get_start_column)(struct _cef_v8exception_t* self); + + /// + // Returns the index within the line of the last character where the error + // occurred. + /// + int (CEF_CALLBACK *get_end_column)(struct _cef_v8exception_t* self); +} cef_v8exception_t; + + +/// +// Structure representing a V8 value handle. V8 handles can only be accessed +// from the thread on which they are created. Valid threads for creating a V8 +// handle include the render process main thread (TID_RENDERER) and WebWorker +// threads. A task runner for posting tasks on the associated thread can be +// retrieved via the cef_v8context_t::get_task_runner() function. +/// +typedef struct _cef_v8value_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if the underlying handle is valid and it can be accessed + // on the current thread. Do not call any other functions if this function + // returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_v8value_t* self); + + /// + // True if the value type is undefined. + /// + int (CEF_CALLBACK *is_undefined)(struct _cef_v8value_t* self); + + /// + // True if the value type is null. + /// + int (CEF_CALLBACK *is_null)(struct _cef_v8value_t* self); + + /// + // True if the value type is bool. + /// + int (CEF_CALLBACK *is_bool)(struct _cef_v8value_t* self); + + /// + // True if the value type is int. + /// + int (CEF_CALLBACK *is_int)(struct _cef_v8value_t* self); + + /// + // True if the value type is unsigned int. + /// + int (CEF_CALLBACK *is_uint)(struct _cef_v8value_t* self); + + /// + // True if the value type is double. + /// + int (CEF_CALLBACK *is_double)(struct _cef_v8value_t* self); + + /// + // True if the value type is Date. + /// + int (CEF_CALLBACK *is_date)(struct _cef_v8value_t* self); + + /// + // True if the value type is string. + /// + int (CEF_CALLBACK *is_string)(struct _cef_v8value_t* self); + + /// + // True if the value type is object. + /// + int (CEF_CALLBACK *is_object)(struct _cef_v8value_t* self); + + /// + // True if the value type is array. + /// + int (CEF_CALLBACK *is_array)(struct _cef_v8value_t* self); + + /// + // True if the value type is function. + /// + int (CEF_CALLBACK *is_function)(struct _cef_v8value_t* self); + + /// + // Returns true (1) if this object is pointing to the same handle as |that| + // object. + /// + int (CEF_CALLBACK *is_same)(struct _cef_v8value_t* self, + struct _cef_v8value_t* that); + + /// + // Return a bool value. The underlying data will be converted to if + // necessary. + /// + int (CEF_CALLBACK *get_bool_value)(struct _cef_v8value_t* self); + + /// + // Return an int value. The underlying data will be converted to if + // necessary. + /// + int32 (CEF_CALLBACK *get_int_value)(struct _cef_v8value_t* self); + + /// + // Return an unisgned int value. The underlying data will be converted to if + // necessary. + /// + uint32 (CEF_CALLBACK *get_uint_value)(struct _cef_v8value_t* self); + + /// + // Return a double value. The underlying data will be converted to if + // necessary. + /// + double (CEF_CALLBACK *get_double_value)(struct _cef_v8value_t* self); + + /// + // Return a Date value. The underlying data will be converted to if + // necessary. + /// + cef_time_t (CEF_CALLBACK *get_date_value)(struct _cef_v8value_t* self); + + /// + // Return a string value. The underlying data will be converted to if + // necessary. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_string_value)( + struct _cef_v8value_t* self); + + + // OBJECT METHODS - These functions are only available on objects. Arrays and + // functions are also objects. String- and integer-based keys can be used + // interchangably with the framework converting between them as necessary. + + /// + // Returns true (1) if this is a user created object. + /// + int (CEF_CALLBACK *is_user_created)(struct _cef_v8value_t* self); + + /// + // Returns true (1) if the last function call resulted in an exception. This + // attribute exists only in the scope of the current CEF value object. + /// + int (CEF_CALLBACK *has_exception)(struct _cef_v8value_t* self); + + /// + // Returns the exception resulting from the last function call. This attribute + // exists only in the scope of the current CEF value object. + /// + struct _cef_v8exception_t* (CEF_CALLBACK *get_exception)( + struct _cef_v8value_t* self); + + /// + // Clears the last exception and returns true (1) on success. + /// + int (CEF_CALLBACK *clear_exception)(struct _cef_v8value_t* self); + + /// + // Returns true (1) if this object will re-throw future exceptions. This + // attribute exists only in the scope of the current CEF value object. + /// + int (CEF_CALLBACK *will_rethrow_exceptions)(struct _cef_v8value_t* self); + + /// + // Set whether this object will re-throw future exceptions. By default + // exceptions are not re-thrown. If a exception is re-thrown the current + // context should not be accessed again until after the exception has been + // caught and not re-thrown. Returns true (1) on success. This attribute + // exists only in the scope of the current CEF value object. + /// + int (CEF_CALLBACK *set_rethrow_exceptions)(struct _cef_v8value_t* self, + int rethrow); + + /// + // Returns true (1) if the object has a value with the specified identifier. + /// + int (CEF_CALLBACK *has_value_bykey)(struct _cef_v8value_t* self, + const cef_string_t* key); + + /// + // Returns true (1) if the object has a value with the specified identifier. + /// + int (CEF_CALLBACK *has_value_byindex)(struct _cef_v8value_t* self, int index); + + /// + // Deletes the value with the specified identifier and returns true (1) on + // success. Returns false (0) if this function is called incorrectly or an + // exception is thrown. For read-only and don't-delete values this function + // will return true (1) even though deletion failed. + /// + int (CEF_CALLBACK *delete_value_bykey)(struct _cef_v8value_t* self, + const cef_string_t* key); + + /// + // Deletes the value with the specified identifier and returns true (1) on + // success. Returns false (0) if this function is called incorrectly, deletion + // fails or an exception is thrown. For read-only and don't-delete values this + // function will return true (1) even though deletion failed. + /// + int (CEF_CALLBACK *delete_value_byindex)(struct _cef_v8value_t* self, + int index); + + /// + // Returns the value with the specified identifier on success. Returns NULL if + // this function is called incorrectly or an exception is thrown. + /// + struct _cef_v8value_t* (CEF_CALLBACK *get_value_bykey)( + struct _cef_v8value_t* self, const cef_string_t* key); + + /// + // Returns the value with the specified identifier on success. Returns NULL if + // this function is called incorrectly or an exception is thrown. + /// + struct _cef_v8value_t* (CEF_CALLBACK *get_value_byindex)( + struct _cef_v8value_t* self, int index); + + /// + // Associates a value with the specified identifier and returns true (1) on + // success. Returns false (0) if this function is called incorrectly or an + // exception is thrown. For read-only values this function will return true + // (1) even though assignment failed. + /// + int (CEF_CALLBACK *set_value_bykey)(struct _cef_v8value_t* self, + const cef_string_t* key, struct _cef_v8value_t* value, + cef_v8_propertyattribute_t attribute); + + /// + // Associates a value with the specified identifier and returns true (1) on + // success. Returns false (0) if this function is called incorrectly or an + // exception is thrown. For read-only values this function will return true + // (1) even though assignment failed. + /// + int (CEF_CALLBACK *set_value_byindex)(struct _cef_v8value_t* self, int index, + struct _cef_v8value_t* value); + + /// + // Registers an identifier and returns true (1) on success. Access to the + // identifier will be forwarded to the cef_v8accessor_t instance passed to + // cef_v8value_t::cef_v8value_create_object(). Returns false (0) if this + // function is called incorrectly or an exception is thrown. For read-only + // values this function will return true (1) even though assignment failed. + /// + int (CEF_CALLBACK *set_value_byaccessor)(struct _cef_v8value_t* self, + const cef_string_t* key, cef_v8_accesscontrol_t settings, + cef_v8_propertyattribute_t attribute); + + /// + // Read the keys for the object's values into the specified vector. Integer- + // based keys will also be returned as strings. + /// + int (CEF_CALLBACK *get_keys)(struct _cef_v8value_t* self, + cef_string_list_t keys); + + /// + // Sets the user data for this object and returns true (1) on success. Returns + // false (0) if this function is called incorrectly. This function can only be + // called on user created objects. + /// + int (CEF_CALLBACK *set_user_data)(struct _cef_v8value_t* self, + struct _cef_base_t* user_data); + + /// + // Returns the user data, if any, assigned to this object. + /// + struct _cef_base_t* (CEF_CALLBACK *get_user_data)( + struct _cef_v8value_t* self); + + /// + // Returns the amount of externally allocated memory registered for the + // object. + /// + int (CEF_CALLBACK *get_externally_allocated_memory)( + struct _cef_v8value_t* self); + + /// + // Adjusts the amount of registered external memory for the object. Used to + // give V8 an indication of the amount of externally allocated memory that is + // kept alive by JavaScript objects. V8 uses this information to decide when + // to perform global garbage collection. Each cef_v8value_t tracks the amount + // of external memory associated with it and automatically decreases the + // global total by the appropriate amount on its destruction. + // |change_in_bytes| specifies the number of bytes to adjust by. This function + // returns the number of bytes associated with the object after the + // adjustment. This function can only be called on user created objects. + /// + int (CEF_CALLBACK *adjust_externally_allocated_memory)( + struct _cef_v8value_t* self, int change_in_bytes); + + + // ARRAY METHODS - These functions are only available on arrays. + + /// + // Returns the number of elements in the array. + /// + int (CEF_CALLBACK *get_array_length)(struct _cef_v8value_t* self); + + + // FUNCTION METHODS - These functions are only available on functions. + + /// + // Returns the function name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_function_name)( + struct _cef_v8value_t* self); + + /// + // Returns the function handler or NULL if not a CEF-created function. + /// + struct _cef_v8handler_t* (CEF_CALLBACK *get_function_handler)( + struct _cef_v8value_t* self); + + /// + // Execute the function using the current V8 context. This function should + // only be called from within the scope of a cef_v8handler_t or + // cef_v8accessor_t callback, or in combination with calling enter() and + // exit() on a stored cef_v8context_t reference. |object| is the receiver + // ('this' object) of the function. If |object| is NULL the current context's + // global object will be used. |arguments| is the list of arguments that will + // be passed to the function. Returns the function return value on success. + // Returns NULL if this function is called incorrectly or an exception is + // thrown. + /// + struct _cef_v8value_t* (CEF_CALLBACK *execute_function)( + struct _cef_v8value_t* self, struct _cef_v8value_t* object, + size_t argumentsCount, struct _cef_v8value_t* const* arguments); + + /// + // Execute the function using the specified V8 context. |object| is the + // receiver ('this' object) of the function. If |object| is NULL the specified + // context's global object will be used. |arguments| is the list of arguments + // that will be passed to the function. Returns the function return value on + // success. Returns NULL if this function is called incorrectly or an + // exception is thrown. + /// + struct _cef_v8value_t* (CEF_CALLBACK *execute_function_with_context)( + struct _cef_v8value_t* self, struct _cef_v8context_t* context, + struct _cef_v8value_t* object, size_t argumentsCount, + struct _cef_v8value_t* const* arguments); +} cef_v8value_t; + + +/// +// Create a new cef_v8value_t object of type undefined. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_undefined(); + +/// +// Create a new cef_v8value_t object of type null. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_null(); + +/// +// Create a new cef_v8value_t object of type bool. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_bool(int value); + +/// +// Create a new cef_v8value_t object of type int. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32 value); + +/// +// Create a new cef_v8value_t object of type unsigned int. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32 value); + +/// +// Create a new cef_v8value_t object of type double. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_double(double value); + +/// +// Create a new cef_v8value_t object of type Date. This function should only be +// called from within the scope of a cef_v8context_tHandler, cef_v8handler_t or +// cef_v8accessor_t callback, or in combination with calling enter() and exit() +// on a stored cef_v8context_t reference. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date); + +/// +// Create a new cef_v8value_t object of type string. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value); + +/// +// Create a new cef_v8value_t object of type object with optional accessor. This +// function should only be called from within the scope of a +// cef_v8context_tHandler, cef_v8handler_t or cef_v8accessor_t callback, or in +// combination with calling enter() and exit() on a stored cef_v8context_t +// reference. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_object(cef_v8accessor_t* accessor); + +/// +// Create a new cef_v8value_t object of type array with the specified |length|. +// If |length| is negative the returned array will have length 0. This function +// should only be called from within the scope of a cef_v8context_tHandler, +// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling +// enter() and exit() on a stored cef_v8context_t reference. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_array(int length); + +/// +// Create a new cef_v8value_t object of type function. This function should only +// be called from within the scope of a cef_v8context_tHandler, cef_v8handler_t +// or cef_v8accessor_t callback, or in combination with calling enter() and +// exit() on a stored cef_v8context_t reference. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name, + cef_v8handler_t* handler); + + +/// +// Structure representing a V8 stack trace handle. V8 handles can only be +// accessed from the thread on which they are created. Valid threads for +// creating a V8 handle include the render process main thread (TID_RENDERER) +// and WebWorker threads. A task runner for posting tasks on the associated +// thread can be retrieved via the cef_v8context_t::get_task_runner() function. +/// +typedef struct _cef_v8stack_trace_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if the underlying handle is valid and it can be accessed + // on the current thread. Do not call any other functions if this function + // returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_v8stack_trace_t* self); + + /// + // Returns the number of stack frames. + /// + int (CEF_CALLBACK *get_frame_count)(struct _cef_v8stack_trace_t* self); + + /// + // Returns the stack frame at the specified 0-based index. + /// + struct _cef_v8stack_frame_t* (CEF_CALLBACK *get_frame)( + struct _cef_v8stack_trace_t* self, int index); +} cef_v8stack_trace_t; + + +/// +// Returns the stack trace for the currently active context. |frame_limit| is +// the maximum number of frames that will be captured. +/// +CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit); + + +/// +// Structure representing a V8 stack frame handle. V8 handles can only be +// accessed from the thread on which they are created. Valid threads for +// creating a V8 handle include the render process main thread (TID_RENDERER) +// and WebWorker threads. A task runner for posting tasks on the associated +// thread can be retrieved via the cef_v8context_t::get_task_runner() function. +/// +typedef struct _cef_v8stack_frame_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if the underlying handle is valid and it can be accessed + // on the current thread. Do not call any other functions if this function + // returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_v8stack_frame_t* self); + + /// + // Returns the name of the resource script that contains the function. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_script_name)( + struct _cef_v8stack_frame_t* self); + + /// + // Returns the name of the resource script that contains the function or the + // sourceURL value if the script name is undefined and its source ends with a + // "//@ sourceURL=..." string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_script_name_or_source_url)( + struct _cef_v8stack_frame_t* self); + + /// + // Returns the name of the function. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_function_name)( + struct _cef_v8stack_frame_t* self); + + /// + // Returns the 1-based line number for the function call or 0 if unknown. + /// + int (CEF_CALLBACK *get_line_number)(struct _cef_v8stack_frame_t* self); + + /// + // Returns the 1-based column offset on the line for the function call or 0 if + // unknown. + /// + int (CEF_CALLBACK *get_column)(struct _cef_v8stack_frame_t* self); + + /// + // Returns true (1) if the function was compiled using eval(). + /// + int (CEF_CALLBACK *is_eval)(struct _cef_v8stack_frame_t* self); + + /// + // Returns true (1) if the function was called as a constructor via "new". + /// + int (CEF_CALLBACK *is_constructor)(struct _cef_v8stack_frame_t* self); +} cef_v8stack_frame_t; + + +/// +// Register a new V8 extension with the specified JavaScript extension code and +// handler. Functions implemented by the handler are prototyped using the +// keyword 'native'. The calling of a native function is restricted to the scope +// in which the prototype of the native function is defined. This function may +// only be called on the render process main thread. +// +// Example JavaScript extension code:
+//   // create the 'example' global object if it doesn't already exist.
+//   if (!example)
+//     example = {};
+//   // create the 'example.test' global object if it doesn't already exist.
+//   if (!example.test)
+//     example.test = {};
+//   (function() {
+//     // Define the function 'example.test.myfunction'.
+//     example.test.myfunction = function() {
+//       // Call CefV8Handler::Execute() with the function name 'MyFunction'
+//       // and no arguments.
+//       native function MyFunction();
+//       return MyFunction();
+//     };
+//     // Define the getter function for parameter 'example.test.myparam'.
+//     example.test.__defineGetter__('myparam', function() {
+//       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
+//       // and no arguments.
+//       native function GetMyParam();
+//       return GetMyParam();
+//     });
+//     // Define the setter function for parameter 'example.test.myparam'.
+//     example.test.__defineSetter__('myparam', function(b) {
+//       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
+//       // and a single argument.
+//       native function SetMyParam();
+//       if(b) SetMyParam(b);
+//     });
+//
+//     // Extension definitions can also contain normal JavaScript variables
+//     // and functions.
+//     var myint = 0;
+//     example.test.increment = function() {
+//       myint += 1;
+//       return myint;
+//     };
+//   })();
+// 
Example usage in the page:
+//   // Call the function.
+//   example.test.myfunction();
+//   // Set the parameter.
+//   example.test.myparam = value;
+//   // Get the parameter.
+//   value = example.test.myparam;
+//   // Call another function.
+//   example.test.increment();
+// 
+/// +CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name, + const cef_string_t* javascript_code, cef_v8handler_t* handler); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_ diff --git a/include/capi/cef_values_capi.h b/include/capi/cef_values_capi.h new file mode 100644 index 000000000..0fd96fd3a --- /dev/null +++ b/include/capi/cef_values_capi.h @@ -0,0 +1,463 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_VALUES_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_VALUES_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _cef_dictionary_value_t; +struct _cef_list_value_t; + +/// +// Structure representing a binary value. Can be used on any process and thread. +/// +typedef struct _cef_binary_value_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_binary_value_t* self); + + /// + // Returns true (1) if this object is currently owned by another object. + /// + int (CEF_CALLBACK *is_owned)(struct _cef_binary_value_t* self); + + /// + // Returns a copy of this object. The data in this object will also be copied. + /// + struct _cef_binary_value_t* (CEF_CALLBACK *copy)( + struct _cef_binary_value_t* self); + + /// + // Returns the data size. + /// + size_t (CEF_CALLBACK *get_size)(struct _cef_binary_value_t* self); + + /// + // Read up to |buffer_size| number of bytes into |buffer|. Reading begins at + // the specified byte |data_offset|. Returns the number of bytes read. + /// + size_t (CEF_CALLBACK *get_data)(struct _cef_binary_value_t* self, + void* buffer, size_t buffer_size, size_t data_offset); +} cef_binary_value_t; + + +/// +// Creates a new object that is not owned by any other object. The specified +// |data| will be copied. +/// +CEF_EXPORT cef_binary_value_t* cef_binary_value_create(const void* data, + size_t data_size); + + +/// +// Structure representing a dictionary value. Can be used on any process and +// thread. +/// +typedef struct _cef_dictionary_value_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_dictionary_value_t* self); + + /// + // Returns true (1) if this object is currently owned by another object. + /// + int (CEF_CALLBACK *is_owned)(struct _cef_dictionary_value_t* self); + + /// + // Returns true (1) if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_dictionary_value_t* self); + + /// + // Returns a writable copy of this object. If |exclude_NULL_children| is true + // (1) any NULL dictionaries or lists will be excluded from the copy. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK *copy)( + struct _cef_dictionary_value_t* self, int exclude_empty_children); + + /// + // Returns the number of values. + /// + size_t (CEF_CALLBACK *get_size)(struct _cef_dictionary_value_t* self); + + /// + // Removes all values. Returns true (1) on success. + /// + int (CEF_CALLBACK *clear)(struct _cef_dictionary_value_t* self); + + /// + // Returns true (1) if the current dictionary has a value for the given key. + /// + int (CEF_CALLBACK *has_key)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Reads all keys for this dictionary into the specified vector. + /// + int (CEF_CALLBACK *get_keys)(struct _cef_dictionary_value_t* self, + cef_string_list_t keys); + + /// + // Removes the value at the specified key. Returns true (1) is the value was + // removed successfully. + /// + int (CEF_CALLBACK *remove)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Returns the value type for the specified key. + /// + cef_value_type_t (CEF_CALLBACK *get_type)( + struct _cef_dictionary_value_t* self, const cef_string_t* key); + + /// + // Returns the value at the specified key as type bool. + /// + int (CEF_CALLBACK *get_bool)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Returns the value at the specified key as type int. + /// + int (CEF_CALLBACK *get_int)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Returns the value at the specified key as type double. + /// + double (CEF_CALLBACK *get_double)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Returns the value at the specified key as type string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_string)( + struct _cef_dictionary_value_t* self, const cef_string_t* key); + + /// + // Returns the value at the specified key as type binary. + /// + struct _cef_binary_value_t* (CEF_CALLBACK *get_binary)( + struct _cef_dictionary_value_t* self, const cef_string_t* key); + + /// + // Returns the value at the specified key as type dictionary. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK *get_dictionary)( + struct _cef_dictionary_value_t* self, const cef_string_t* key); + + /// + // Returns the value at the specified key as type list. + /// + struct _cef_list_value_t* (CEF_CALLBACK *get_list)( + struct _cef_dictionary_value_t* self, const cef_string_t* key); + + /// + // Sets the value at the specified key as type null. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_null)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + // Sets the value at the specified key as type bool. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_bool)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, int value); + + /// + // Sets the value at the specified key as type int. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_int)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, int value); + + /// + // Sets the value at the specified key as type double. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_double)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, double value); + + /// + // Sets the value at the specified key as type string. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_string)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, const cef_string_t* value); + + /// + // Sets the value at the specified key as type binary. Returns true (1) if the + // value was set successfully. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + int (CEF_CALLBACK *set_binary)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, struct _cef_binary_value_t* value); + + /// + // Sets the value at the specified key as type dict. Returns true (1) if the + // value was set successfully. After calling this function the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + int (CEF_CALLBACK *set_dictionary)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, struct _cef_dictionary_value_t* value); + + /// + // Sets the value at the specified key as type list. Returns true (1) if the + // value was set successfully. After calling this function the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + int (CEF_CALLBACK *set_list)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, struct _cef_list_value_t* value); +} cef_dictionary_value_t; + + +/// +// Creates a new object that is not owned by any other object. +/// +CEF_EXPORT cef_dictionary_value_t* cef_dictionary_value_create(); + + +/// +// Structure representing a list value. Can be used on any process and thread. +/// +typedef struct _cef_list_value_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns true (1) if this object is valid. Do not call any other functions + // if this function returns false (0). + /// + int (CEF_CALLBACK *is_valid)(struct _cef_list_value_t* self); + + /// + // Returns true (1) if this object is currently owned by another object. + /// + int (CEF_CALLBACK *is_owned)(struct _cef_list_value_t* self); + + /// + // Returns true (1) if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + int (CEF_CALLBACK *is_read_only)(struct _cef_list_value_t* self); + + /// + // Returns a writable copy of this object. + /// + struct _cef_list_value_t* (CEF_CALLBACK *copy)( + struct _cef_list_value_t* self); + + /// + // Sets the number of values. If the number of values is expanded all new + // value slots will default to type null. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_size)(struct _cef_list_value_t* self, size_t size); + + /// + // Returns the number of values. + /// + size_t (CEF_CALLBACK *get_size)(struct _cef_list_value_t* self); + + /// + // Removes all values. Returns true (1) on success. + /// + int (CEF_CALLBACK *clear)(struct _cef_list_value_t* self); + + /// + // Removes the value at the specified index. + /// + int (CEF_CALLBACK *remove)(struct _cef_list_value_t* self, int index); + + /// + // Returns the value type at the specified index. + /// + cef_value_type_t (CEF_CALLBACK *get_type)(struct _cef_list_value_t* self, + int index); + + /// + // Returns the value at the specified index as type bool. + /// + int (CEF_CALLBACK *get_bool)(struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type int. + /// + int (CEF_CALLBACK *get_int)(struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type double. + /// + double (CEF_CALLBACK *get_double)(struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_string)( + struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type binary. + /// + struct _cef_binary_value_t* (CEF_CALLBACK *get_binary)( + struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type dictionary. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK *get_dictionary)( + struct _cef_list_value_t* self, int index); + + /// + // Returns the value at the specified index as type list. + /// + struct _cef_list_value_t* (CEF_CALLBACK *get_list)( + struct _cef_list_value_t* self, int index); + + /// + // Sets the value at the specified index as type null. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_null)(struct _cef_list_value_t* self, int index); + + /// + // Sets the value at the specified index as type bool. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_bool)(struct _cef_list_value_t* self, int index, + int value); + + /// + // Sets the value at the specified index as type int. Returns true (1) if the + // value was set successfully. + /// + int (CEF_CALLBACK *set_int)(struct _cef_list_value_t* self, int index, + int value); + + /// + // Sets the value at the specified index as type double. Returns true (1) if + // the value was set successfully. + /// + int (CEF_CALLBACK *set_double)(struct _cef_list_value_t* self, int index, + double value); + + /// + // Sets the value at the specified index as type string. Returns true (1) if + // the value was set successfully. + /// + int (CEF_CALLBACK *set_string)(struct _cef_list_value_t* self, int index, + const cef_string_t* value); + + /// + // Sets the value at the specified index as type binary. Returns true (1) if + // the value was set successfully. After calling this function the |value| + // object will no longer be valid. If |value| is currently owned by another + // object then the value will be copied and the |value| reference will not + // change. Otherwise, ownership will be transferred to this object and the + // |value| reference will be invalidated. + /// + int (CEF_CALLBACK *set_binary)(struct _cef_list_value_t* self, int index, + struct _cef_binary_value_t* value); + + /// + // Sets the value at the specified index as type dict. Returns true (1) if the + // value was set successfully. After calling this function the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + int (CEF_CALLBACK *set_dictionary)(struct _cef_list_value_t* self, int index, + struct _cef_dictionary_value_t* value); + + /// + // Sets the value at the specified index as type list. Returns true (1) if the + // value was set successfully. After calling this function the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + int (CEF_CALLBACK *set_list)(struct _cef_list_value_t* self, int index, + struct _cef_list_value_t* value); +} cef_list_value_t; + + +/// +// Creates a new object that is not owned by any other object. +/// +CEF_EXPORT cef_list_value_t* cef_list_value_create(); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_VALUES_CAPI_H_ diff --git a/include/capi/cef_web_plugin_capi.h b/include/capi/cef_web_plugin_capi.h new file mode 100644 index 000000000..a9d089b77 --- /dev/null +++ b/include/capi/cef_web_plugin_capi.h @@ -0,0 +1,195 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_browser_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Information about a specific web plugin. +/// +typedef struct _cef_web_plugin_info_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Returns the plugin name (i.e. Flash). + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_name)( + struct _cef_web_plugin_info_t* self); + + /// + // Returns the plugin file path (DLL/bundle/library). + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_path)( + struct _cef_web_plugin_info_t* self); + + /// + // Returns the version of the plugin (may be OS-specific). + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_version)( + struct _cef_web_plugin_info_t* self); + + /// + // Returns a description of the plugin from the version information. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_description)( + struct _cef_web_plugin_info_t* self); +} cef_web_plugin_info_t; + + +/// +// Structure to implement for visiting web plugin information. The functions of +// this structure will be called on the browser process UI thread. +/// +typedef struct _cef_web_plugin_info_visitor_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called once for each plugin. |count| is the 0-based + // index for the current plugin. |total| is the total number of plugins. + // Return false (0) to stop visiting plugins. This function may never be + // called if no plugins are found. + /// + int (CEF_CALLBACK *visit)(struct _cef_web_plugin_info_visitor_t* self, + struct _cef_web_plugin_info_t* info, int count, int total); +} cef_web_plugin_info_visitor_t; + + +/// +// Structure to implement for receiving unstable plugin information. The +// functions of this structure will be called on the browser process IO thread. +/// +typedef struct _cef_web_plugin_unstable_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called for the requested plugin. |unstable| will be + // true (1) if the plugin has reached the crash count threshold of 3 times in + // 120 seconds. + /// + void (CEF_CALLBACK *is_unstable)( + struct _cef_web_plugin_unstable_callback_t* self, + const cef_string_t* path, int unstable); +} cef_web_plugin_unstable_callback_t; + + +/// +// Visit web plugin information. Can be called on any thread in the browser +// process. +/// +CEF_EXPORT void cef_visit_web_plugin_info( + cef_web_plugin_info_visitor_t* visitor); + +/// +// Cause the plugin list to refresh the next time it is accessed regardless of +// whether it has already been loaded. Can be called on any thread in the +// browser process. +/// +CEF_EXPORT void cef_refresh_web_plugins(); + +/// +// Add a plugin path (directory + file). This change may not take affect until +// after cef_refresh_web_plugins() is called. Can be called on any thread in the +// browser process. +/// +CEF_EXPORT void cef_add_web_plugin_path(const cef_string_t* path); + +/// +// Add a plugin directory. This change may not take affect until after +// cef_refresh_web_plugins() is called. Can be called on any thread in the +// browser process. +/// +CEF_EXPORT void cef_add_web_plugin_directory(const cef_string_t* dir); + +/// +// Remove a plugin path (directory + file). This change may not take affect +// until after cef_refresh_web_plugins() is called. Can be called on any thread +// in the browser process. +/// +CEF_EXPORT void cef_remove_web_plugin_path(const cef_string_t* path); + +/// +// Unregister an internal plugin. This may be undone the next time +// cef_refresh_web_plugins() is called. Can be called on any thread in the +// browser process. +/// +CEF_EXPORT void cef_unregister_internal_web_plugin(const cef_string_t* path); + +/// +// Force a plugin to shutdown. Can be called on any thread in the browser +// process but will be executed on the IO thread. +/// +CEF_EXPORT void cef_force_web_plugin_shutdown(const cef_string_t* path); + +/// +// Register a plugin crash. Can be called on any thread in the browser process +// but will be executed on the IO thread. +/// +CEF_EXPORT void cef_register_web_plugin_crash(const cef_string_t* path); + +/// +// Query if a plugin is unstable. Can be called on any thread in the browser +// process. +/// +CEF_EXPORT void cef_is_web_plugin_unstable(const cef_string_t* path, + cef_web_plugin_unstable_callback_t* callback); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_WEB_PLUGIN_CAPI_H_ diff --git a/include/capi/cef_xml_reader_capi.h b/include/capi/cef_xml_reader_capi.h new file mode 100644 index 000000000..1a7bd2104 --- /dev/null +++ b/include/capi/cef_xml_reader_capi.h @@ -0,0 +1,278 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_XML_READER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_XML_READER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_stream_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure that supports the reading of XML data via the libxml streaming API. +// The functions of this structure should only be called on the thread that +// creates the object. +/// +typedef struct _cef_xml_reader_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Moves the cursor to the next node in the document. This function must be + // called at least once to set the current cursor position. Returns true (1) + // if the cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_next_node)(struct _cef_xml_reader_t* self); + + /// + // Close the document. This should be called directly to ensure that cleanup + // occurs on the correct thread. + /// + int (CEF_CALLBACK *close)(struct _cef_xml_reader_t* self); + + /// + // Returns true (1) if an error has been reported by the XML parser. + /// + int (CEF_CALLBACK *has_error)(struct _cef_xml_reader_t* self); + + /// + // Returns the error string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_error)( + struct _cef_xml_reader_t* self); + + + // The below functions retrieve data for the node at the current cursor + // position. + + /// + // Returns the node type. + /// + cef_xml_node_type_t (CEF_CALLBACK *get_type)(struct _cef_xml_reader_t* self); + + /// + // Returns the node depth. Depth starts at 0 for the root node. + /// + int (CEF_CALLBACK *get_depth)(struct _cef_xml_reader_t* self); + + /// + // Returns the local name. See http://www.w3.org/TR/REC-xml-names/#NT- + // LocalPart for additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_local_name)( + struct _cef_xml_reader_t* self); + + /// + // Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for + // additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_prefix)( + struct _cef_xml_reader_t* self); + + /// + // Returns the qualified name, equal to (Prefix:)LocalName. See + // http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_qualified_name)( + struct _cef_xml_reader_t* self); + + /// + // Returns the URI defining the namespace associated with the node. See + // http://www.w3.org/TR/REC-xml-names/ for additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_namespace_uri)( + struct _cef_xml_reader_t* self); + + /// + // Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for + // additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_base_uri)( + struct _cef_xml_reader_t* self); + + /// + // Returns the xml:lang scope within which the node resides. See + // http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_xml_lang)( + struct _cef_xml_reader_t* self); + + /// + // Returns true (1) if the node represents an NULL element.
is considered + // NULL but is not. + /// + int (CEF_CALLBACK *is_empty_element)(struct _cef_xml_reader_t* self); + + /// + // Returns true (1) if the node has a text value. + /// + int (CEF_CALLBACK *has_value)(struct _cef_xml_reader_t* self); + + /// + // Returns the text value. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_value)( + struct _cef_xml_reader_t* self); + + /// + // Returns true (1) if the node has attributes. + /// + int (CEF_CALLBACK *has_attributes)(struct _cef_xml_reader_t* self); + + /// + // Returns the number of attributes. + /// + size_t (CEF_CALLBACK *get_attribute_count)(struct _cef_xml_reader_t* self); + + /// + // Returns the value of the attribute at the specified 0-based index. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_attribute_byindex)( + struct _cef_xml_reader_t* self, int index); + + /// + // Returns the value of the attribute with the specified qualified name. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_attribute_byqname)( + struct _cef_xml_reader_t* self, const cef_string_t* qualifiedName); + + /// + // Returns the value of the attribute with the specified local name and + // namespace URI. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_attribute_bylname)( + struct _cef_xml_reader_t* self, const cef_string_t* localName, + const cef_string_t* namespaceURI); + + /// + // Returns an XML representation of the current node's children. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_inner_xml)( + struct _cef_xml_reader_t* self); + + /// + // Returns an XML representation of the current node including its children. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_outer_xml)( + struct _cef_xml_reader_t* self); + + /// + // Returns the line number for the current node. + /// + int (CEF_CALLBACK *get_line_number)(struct _cef_xml_reader_t* self); + + + // Attribute nodes are not traversed by default. The below functions can be + // used to move the cursor to an attribute node. move_to_carrying_element() + // can be called afterwards to return the cursor to the carrying element. The + // depth of an attribute node will be 1 + the depth of the carrying element. + + /// + // Moves the cursor to the attribute at the specified 0-based index. Returns + // true (1) if the cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_attribute_byindex)(struct _cef_xml_reader_t* self, + int index); + + /// + // Moves the cursor to the attribute with the specified qualified name. + // Returns true (1) if the cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_attribute_byqname)(struct _cef_xml_reader_t* self, + const cef_string_t* qualifiedName); + + /// + // Moves the cursor to the attribute with the specified local name and + // namespace URI. Returns true (1) if the cursor position was set + // successfully. + /// + int (CEF_CALLBACK *move_to_attribute_bylname)(struct _cef_xml_reader_t* self, + const cef_string_t* localName, const cef_string_t* namespaceURI); + + /// + // Moves the cursor to the first attribute in the current element. Returns + // true (1) if the cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_first_attribute)(struct _cef_xml_reader_t* self); + + /// + // Moves the cursor to the next attribute in the current element. Returns true + // (1) if the cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_next_attribute)(struct _cef_xml_reader_t* self); + + /// + // Moves the cursor back to the carrying element. Returns true (1) if the + // cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_carrying_element)(struct _cef_xml_reader_t* self); +} cef_xml_reader_t; + + +/// +// Create a new cef_xml_reader_t object. The returned object's functions can +// only be called from the thread that created the object. +/// +CEF_EXPORT cef_xml_reader_t* cef_xml_reader_create( + struct _cef_stream_reader_t* stream, cef_xml_encoding_type_t encodingType, + const cef_string_t* URI); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_XML_READER_CAPI_H_ diff --git a/include/capi/cef_zip_reader_capi.h b/include/capi/cef_zip_reader_capi.h new file mode 100644 index 000000000..b9a5094e8 --- /dev/null +++ b/include/capi/cef_zip_reader_capi.h @@ -0,0 +1,149 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_ZIP_READER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_ZIP_READER_CAPI_H_ +#pragma once + +#include "include/capi/cef_base_capi.h" +#include "include/capi/cef_stream_capi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +// Structure that supports the reading of zip archives via the zlib unzip API. +// The functions of this structure should only be called on the thread that +// creates the object. +/// +typedef struct _cef_zip_reader_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Moves the cursor to the first file in the archive. Returns true (1) if the + // cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_first_file)(struct _cef_zip_reader_t* self); + + /// + // Moves the cursor to the next file in the archive. Returns true (1) if the + // cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_next_file)(struct _cef_zip_reader_t* self); + + /// + // Moves the cursor to the specified file in the archive. If |caseSensitive| + // is true (1) then the search will be case sensitive. Returns true (1) if the + // cursor position was set successfully. + /// + int (CEF_CALLBACK *move_to_file)(struct _cef_zip_reader_t* self, + const cef_string_t* fileName, int caseSensitive); + + /// + // Closes the archive. This should be called directly to ensure that cleanup + // occurs on the correct thread. + /// + int (CEF_CALLBACK *close)(struct _cef_zip_reader_t* self); + + + // The below functions act on the file at the current cursor position. + + /// + // Returns the name of the file. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_file_name)( + struct _cef_zip_reader_t* self); + + /// + // Returns the uncompressed size of the file. + /// + int64 (CEF_CALLBACK *get_file_size)(struct _cef_zip_reader_t* self); + + /// + // Returns the last modified timestamp for the file. + /// + time_t (CEF_CALLBACK *get_file_last_modified)(struct _cef_zip_reader_t* self); + + /// + // Opens the file for reading of uncompressed data. A read password may + // optionally be specified. + /// + int (CEF_CALLBACK *open_file)(struct _cef_zip_reader_t* self, + const cef_string_t* password); + + /// + // Closes the file. + /// + int (CEF_CALLBACK *close_file)(struct _cef_zip_reader_t* self); + + /// + // Read uncompressed file contents into the specified buffer. Returns < 0 if + // an error occurred, 0 if at the end of file, or the number of bytes read. + /// + int (CEF_CALLBACK *read_file)(struct _cef_zip_reader_t* self, void* buffer, + size_t bufferSize); + + /// + // Returns the current offset in the uncompressed file contents. + /// + int64 (CEF_CALLBACK *tell)(struct _cef_zip_reader_t* self); + + /// + // Returns true (1) if at end of the file contents. + /// + int (CEF_CALLBACK *eof)(struct _cef_zip_reader_t* self); +} cef_zip_reader_t; + + +/// +// Create a new cef_zip_reader_t object. The returned object's functions can +// only be called from the thread that created the object. +/// +CEF_EXPORT cef_zip_reader_t* cef_zip_reader_create( + struct _cef_stream_reader_t* stream); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_ZIP_READER_CAPI_H_ diff --git a/include/cef_app.h b/include/cef_app.h new file mode 100644 index 000000000..bac622812 --- /dev/null +++ b/include/cef_app.h @@ -0,0 +1,192 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + + +#ifndef CEF_INCLUDE_CEF_APP_H_ +#define CEF_INCLUDE_CEF_APP_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser_process_handler.h" +#include "include/cef_command_line.h" +#include "include/cef_render_process_handler.h" +#include "include/cef_resource_bundle_handler.h" +#include "include/cef_scheme.h" + +class CefApp; + +/// +// This function should be called from the application entry point function to +// execute a secondary process. It can be used to run secondary processes from +// the browser client executable (default behavior) or from a separate +// executable specified by the CefSettings.browser_subprocess_path value. If +// called for the browser process (identified by no "type" command-line value) +// it will return immediately with a value of -1. If called for a recognized +// secondary process it will block until the process should exit and then return +// the process exit code. The |application| parameter may be empty. The +// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see +// cef_sandbox_win.h for details). +/// +/*--cef(api_hash_check,optional_param=application, + optional_param=windows_sandbox_info)--*/ +int CefExecuteProcess(const CefMainArgs& args, + CefRefPtr application, + void* windows_sandbox_info); + +/// +// This function should be called on the main application thread to initialize +// the CEF browser process. The |application| parameter may be empty. A return +// value of true indicates that it succeeded and false indicates that it failed. +// The |windows_sandbox_info| parameter is only used on Windows and may be NULL +// (see cef_sandbox_win.h for details). +/// +/*--cef(api_hash_check,optional_param=application, + optional_param=windows_sandbox_info)--*/ +bool CefInitialize(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application, + void* windows_sandbox_info); + +/// +// This function should be called on the main application thread to shut down +// the CEF browser process before the application exits. +/// +/*--cef()--*/ +void CefShutdown(); + +/// +// Perform a single iteration of CEF message loop processing. This function is +// used to integrate the CEF message loop into an existing application message +// loop. Care must be taken to balance performance against excessive CPU usage. +// This function should only be called on the main application thread and only +// if CefInitialize() is called with a CefSettings.multi_threaded_message_loop +// value of false. This function will not block. +/// +/*--cef()--*/ +void CefDoMessageLoopWork(); + +/// +// Run the CEF message loop. Use this function instead of an application- +// provided message loop to get the best balance between performance and CPU +// usage. This function should only be called on the main application thread and +// only if CefInitialize() is called with a +// CefSettings.multi_threaded_message_loop value of false. This function will +// block until a quit message is received by the system. +/// +/*--cef()--*/ +void CefRunMessageLoop(); + +/// +// Quit the CEF message loop that was started by calling CefRunMessageLoop(). +// This function should only be called on the main application thread and only +// if CefRunMessageLoop() was used. +/// +/*--cef()--*/ +void CefQuitMessageLoop(); + +/// +// Set to true before calling Windows APIs like TrackPopupMenu that enter a +// modal message loop. Set to false after exiting the modal message loop. +/// +/*--cef()--*/ +void CefSetOSModalLoop(bool osModalLoop); + +/// +// Implement this interface to provide handler implementations. Methods will be +// called by the process and/or thread indicated. +/// +/*--cef(source=client,no_debugct_check)--*/ +class CefApp : public virtual CefBase { + public: + /// + // Provides an opportunity to view and/or modify command-line arguments before + // processing by CEF and Chromium. The |process_type| value will be empty for + // the browser process. Do not keep a reference to the CefCommandLine object + // passed to this method. The CefSettings.command_line_args_disabled value + // can be used to start with an empty command-line object. Any values + // specified in CefSettings that equate to command-line arguments will be set + // before this method is called. Be cautious when using this method to modify + // command-line arguments for non-browser processes as this may result in + // undefined behavior including crashes. + /// + /*--cef(optional_param=process_type)--*/ + virtual void OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) { + } + + /// + // Provides an opportunity to register custom schemes. Do not keep a reference + // to the |registrar| object. This method is called on the main thread for + // each process and the registered schemes should be the same across all + // processes. + /// + /*--cef()--*/ + virtual void OnRegisterCustomSchemes( + CefRefPtr registrar) { + } + + /// + // Return the handler for resource bundle events. If + // CefSettings.pack_loading_disabled is true a handler must be returned. If no + // handler is returned resources will be loaded from pack files. This method + // is called by the browser and render processes on multiple threads. + /// + /*--cef()--*/ + virtual CefRefPtr GetResourceBundleHandler() { + return NULL; + } + + /// + // Return the handler for functionality specific to the browser process. This + // method is called on multiple threads in the browser process. + /// + /*--cef()--*/ + virtual CefRefPtr GetBrowserProcessHandler() { + return NULL; + } + + /// + // Return the handler for functionality specific to the render process. This + // method is called on the render process main thread. + /// + /*--cef()--*/ + virtual CefRefPtr GetRenderProcessHandler() { + return NULL; + } +}; + +#endif // CEF_INCLUDE_CEF_APP_H_ diff --git a/include/cef_application_mac.h b/include/cef_application_mac.h new file mode 100644 index 000000000..b4e85db22 --- /dev/null +++ b/include/cef_application_mac.h @@ -0,0 +1,200 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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_CEF_APPLICATION_MAC_H_ +#define CEF_INCLUDE_CEF_APPLICATION_MAC_H_ +#pragma once + +#include "include/cef_base.h" + +#if defined(OS_MACOSX) && defined(__OBJC__) + +#ifdef BUILDING_CEF_SHARED + +// Use the existing CrAppControlProtocol definition. +#import "base/mac/scoped_sending_event.h" + +// Use the existing CrAppProtocol definition. +#import "base/message_loop/message_pump_mac.h" + +// Use the existing UnderlayableSurface definition. +#import "ui/base/cocoa/underlay_opengl_hosting_window.h" + +// Use the existing empty protocol definitions. +#import "base/mac/cocoa_protocols.h" + +// Use the existing empty protocol definitions. +#import "base/mac/sdk_forward_declarations.h" + +#else // BUILDING_CEF_SHARED + +#import +#import + +// Copy of definition from base/message_loop/message_pump_mac.h. +@protocol CrAppProtocol +// Must return true if -[NSApplication sendEvent:] is currently on the stack. +- (BOOL)isHandlingSendEvent; +@end + +// Copy of definition from base/mac/scoped_sending_event.h. +@protocol CrAppControlProtocol +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent; +@end + +// Copy of definition from ui/base/cocoa/underlay_opengl_hosting_window.h. +// Common base class for windows that host a OpenGL surface that renders under +// the window. Contains methods relating to hole punching so that the OpenGL +// surface is visible through the window. +@interface UnderlayOpenGLHostingWindow : NSWindow +@end + +// Copy of definitions from base/mac/sdk_forward_declarations.h. +// Forward declarations for APIs that are part of the 10.7 SDK. This will allow +// using them when building with the 10.6 SDK. + +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + +enum { + NSEventPhaseNone = 0, // event not associated with a phase. + NSEventPhaseBegan = 0x1 << 0, + NSEventPhaseStationary = 0x1 << 1, + NSEventPhaseChanged = 0x1 << 2, + NSEventPhaseEnded = 0x1 << 3, + NSEventPhaseCancelled = 0x1 << 4, +}; +typedef NSUInteger NSEventPhase; + +@interface NSEvent (LionSDK) ++ (BOOL)isSwipeTrackingFromScrollEventsEnabled; + +- (NSEventPhase)phase; +- (CGFloat)scrollingDeltaX; +- (CGFloat)scrollingDeltaY; +- (BOOL)isDirectionInvertedFromDevice; +@end + +@interface NSScreen (LionSDK) +- (CGFloat)backingScaleFactor; +- (NSRect)convertRectToBacking:(NSRect)aRect; +@end + +@interface NSWindow (LionSDK) +- (CGFloat)backingScaleFactor; +@end + +#endif // MAC_OS_X_VERSION_10_7 + +// The Mac OS X 10.6 SDK introduced new protocols used for delegates. These +// protocol defintions were not present in earlier releases of the Mac OS X +// SDK. In order to support building against the new SDK, which requires +// delegates to conform to these protocols, and earlier SDKs, which do not +// define these protocols at all, this file will provide empty protocol +// definitions when used with earlier SDK versions. + +#if !defined(MAC_OS_X_VERSION_10_6) || \ +MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + +#define DEFINE_EMPTY_PROTOCOL(p) \ +@protocol p \ +@end + +DEFINE_EMPTY_PROTOCOL(NSAlertDelegate) +DEFINE_EMPTY_PROTOCOL(NSApplicationDelegate) +DEFINE_EMPTY_PROTOCOL(NSControlTextEditingDelegate) +DEFINE_EMPTY_PROTOCOL(NSMatrixDelegate) +DEFINE_EMPTY_PROTOCOL(NSMenuDelegate) +DEFINE_EMPTY_PROTOCOL(NSOpenSavePanelDelegate) +DEFINE_EMPTY_PROTOCOL(NSOutlineViewDataSource) +DEFINE_EMPTY_PROTOCOL(NSOutlineViewDelegate) +DEFINE_EMPTY_PROTOCOL(NSSpeechSynthesizerDelegate) +DEFINE_EMPTY_PROTOCOL(NSSplitViewDelegate) +DEFINE_EMPTY_PROTOCOL(NSTableViewDataSource) +DEFINE_EMPTY_PROTOCOL(NSTableViewDelegate) +DEFINE_EMPTY_PROTOCOL(NSTextFieldDelegate) +DEFINE_EMPTY_PROTOCOL(NSTextViewDelegate) +DEFINE_EMPTY_PROTOCOL(NSWindowDelegate) + +#undef DEFINE_EMPTY_PROTOCOL + +#endif + +#endif // BUILDING_CEF_SHARED + +// Forward declarations for APIs that are part of the 10.7 SDK. This will allow +// using them when building with the 10.6 SDK. + +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + +@interface NSView (NSOpenGLSurfaceResolutionLionAPI) +- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag; +@end + +@interface NSView (LionAPI) +- (NSSize)convertSizeToBacking:(NSSize)aSize; +- (NSRect)convertRectToBacking:(NSRect)aRect; +- (NSRect)convertRectFromBacking:(NSRect)aRect; +@end + +static NSString* const NSWindowDidChangeBackingPropertiesNotification = + @"NSWindowDidChangeBackingPropertiesNotification"; +static NSString* const NSBackingPropertyOldScaleFactorKey = + @"NSBackingPropertyOldScaleFactorKey"; + +#endif // MAC_OS_X_VERSION_10_7 + +// All CEF client applications must subclass NSApplication and implement this +// protocol. +@protocol CefAppProtocol +@end + +// Controls the state of |isHandlingSendEvent| in the event loop so that it is +// reset properly. +class CefScopedSendingEvent { + public: + CefScopedSendingEvent() + : app_(static_cast*>( + [NSApplication sharedApplication])), + handling_([app_ isHandlingSendEvent]) { + [app_ setHandlingSendEvent:YES]; + } + ~CefScopedSendingEvent() { + [app_ setHandlingSendEvent:handling_]; + } + + private: + NSApplication* app_; + BOOL handling_; +}; + +#endif // defined(OS_MACOSX) && defined(__OBJC__) + +#endif // CEF_INCLUDE_CEF_APPLICATION_MAC_H_ diff --git a/include/cef_auth_callback.h b/include/cef_auth_callback.h new file mode 100644 index 000000000..86d249ad3 --- /dev/null +++ b/include/cef_auth_callback.h @@ -0,0 +1,64 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_AUTH_CALLBACK_H_ +#define CEF_INCLUDE_CEF_AUTH_CALLBACK_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Callback interface used for asynchronous continuation of authentication +// requests. +/// +/*--cef(source=library)--*/ +class CefAuthCallback : public virtual CefBase { + public: + /// + // Continue the authentication request. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(const CefString& username, + const CefString& password) =0; + + /// + // Cancel the authentication request. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + +#endif // CEF_INCLUDE_CEF_AUTH_CALLBACK_H_ diff --git a/include/cef_base.h b/include/cef_base.h new file mode 100644 index 000000000..c237b9e8d --- /dev/null +++ b/include/cef_base.h @@ -0,0 +1,180 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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_CEF_BASE_H_ +#define CEF_INCLUDE_CEF_BASE_H_ +#pragma once + +#include "include/base/cef_atomic_ref_count.h" +#include "include/base/cef_build.h" +#include "include/base/cef_macros.h" + +// Bring in common C++ type definitions used by CEF consumers. +#include "include/internal/cef_ptr.h" +#include "include/internal/cef_types_wrappers.h" +#if defined(OS_WIN) +#include "include/internal/cef_win.h" +#elif defined(OS_MACOSX) +#include "include/internal/cef_mac.h" +#elif defined(OS_LINUX) +#include "include/internal/cef_linux.h" +#endif + +/// +// Interface defining the reference count implementation methods. All framework +// classes must extend the CefBase class. +/// +class CefBase { + public: + /// + // Called to increment the reference count for the object. Should be called + // for every new copy of a pointer to a given object. + /// + virtual void AddRef() const =0; + + /// + // Called to decrement the reference count for the object. Returns true if + // the reference count is 0, in which case the object should self-delete. + /// + virtual bool Release() const =0; + + /// + // Returns true if the reference count is 1. + /// + virtual bool HasOneRef() const =0; + + protected: + virtual ~CefBase() {} +}; + +/// +// Class that implements atomic reference counting. +/// +class CefRefCount { + public: + CefRefCount() : ref_count_(0) {} + + /// + // Increment the reference count. + /// + void AddRef() const { + base::AtomicRefCountInc(&ref_count_); + } + + /// + // Decrement the reference count. Returns true if the reference count is 0. + /// + bool Release() const { + return !base::AtomicRefCountDec(&ref_count_); + } + + /// + // Returns true if the reference count is 1. + /// + bool HasOneRef() const { + return base::AtomicRefCountIsOne(&ref_count_); + } + + private: + mutable base::AtomicRefCount ref_count_; + DISALLOW_COPY_AND_ASSIGN(CefRefCount); +}; + +/// +// Macro that provides a reference counting implementation for classes extending +// CefBase. +/// +#define IMPLEMENT_REFCOUNTING(ClassName) \ + public: \ + void AddRef() const { \ + ref_count_.AddRef(); \ + } \ + bool Release() const { \ + if (ref_count_.Release()) { \ + delete static_cast(this); \ + return true; \ + } \ + return false; \ + } \ + bool HasOneRef() const { \ + return ref_count_.HasOneRef(); \ + } \ + private: \ + CefRefCount ref_count_; + +/// +// Macro that provides a locking implementation. Use the Lock() and Unlock() +// methods to protect a section of code from simultaneous access by multiple +// threads. The AutoLock class is a helper that will hold the lock while in +// scope. +// +// THIS MACRO IS DEPRECATED. Use an explicit base::Lock member variable and +// base::AutoLock instead. For example: +// +// #include "include/base/cef_lock.h" +// +// // Class declaration. +// class MyClass : public CefBase { +// public: +// MyClass() : value_(0) {} +// // Method that may be called on multiple threads. +// void IncrementValue(); +// private: +// // Value that may be accessed on multiple theads. +// int value_; +// // Lock used to protect access to |value_|. +// base::Lock lock_; +// IMPLEMENT_REFCOUNTING(MyClass); +// }; +// +// // Class implementation. +// void MyClass::IncrementValue() { +// // Acquire the lock for the scope of this method. +// base::AutoLock lock_scope(lock_); +// // |value_| can now be modified safely. +// value_++; +// } +/// +#define IMPLEMENT_LOCKING(ClassName) \ + public: \ + class AutoLock { \ + public: \ + explicit AutoLock(ClassName* base) : base_(base) { base_->Lock(); } \ + ~AutoLock() { base_->Unlock(); } \ + private: \ + ClassName* base_; \ + DISALLOW_COPY_AND_ASSIGN(AutoLock); \ + }; \ + void Lock() { lock_.Acquire(); } \ + void Unlock() { lock_.Release(); } \ + private: \ + base::Lock lock_; + +#endif // CEF_INCLUDE_CEF_BASE_H_ diff --git a/include/cef_browser.h b/include/cef_browser.h new file mode 100644 index 000000000..763dfaa36 --- /dev/null +++ b/include/cef_browser.h @@ -0,0 +1,582 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_BROWSER_H_ +#define CEF_INCLUDE_CEF_BROWSER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_drag_data.h" +#include "include/cef_frame.h" +#include "include/cef_process_message.h" +#include "include/cef_request_context.h" +#include + +class CefBrowserHost; +class CefClient; + + +/// +// Class used to represent a browser window. When used in the browser process +// the methods of this class may be called on any thread unless otherwise +// indicated in the comments. When used in the render process the methods of +// this class may only be called on the main thread. +/// +/*--cef(source=library)--*/ +class CefBrowser : public virtual CefBase { + public: + /// + // Returns the browser host object. This method can only be called in the + // browser process. + /// + /*--cef()--*/ + virtual CefRefPtr GetHost() =0; + + /// + // Returns true if the browser can navigate backwards. + /// + /*--cef()--*/ + virtual bool CanGoBack() =0; + + /// + // Navigate backwards. + /// + /*--cef()--*/ + virtual void GoBack() =0; + + /// + // Returns true if the browser can navigate forwards. + /// + /*--cef()--*/ + virtual bool CanGoForward() =0; + + /// + // Navigate forwards. + /// + /*--cef()--*/ + virtual void GoForward() =0; + + /// + // Returns true if the browser is currently loading. + /// + /*--cef()--*/ + virtual bool IsLoading() =0; + + /// + // Reload the current page. + /// + /*--cef()--*/ + virtual void Reload() =0; + + /// + // Reload the current page ignoring any cached data. + /// + /*--cef()--*/ + virtual void ReloadIgnoreCache() =0; + + /// + // Stop loading the page. + /// + /*--cef()--*/ + virtual void StopLoad() =0; + + /// + // Returns the globally unique identifier for this browser. + /// + /*--cef()--*/ + virtual int GetIdentifier() =0; + + /// + // Returns true if this object is pointing to the same handle as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr that) =0; + + /// + // Returns true if the window is a popup window. + /// + /*--cef()--*/ + virtual bool IsPopup() =0; + + /// + // Returns true if a document has been loaded in the browser. + /// + /*--cef()--*/ + virtual bool HasDocument() =0; + + /// + // Returns the main (top-level) frame for the browser window. + /// + /*--cef()--*/ + virtual CefRefPtr GetMainFrame() =0; + + /// + // Returns the focused frame for the browser window. + /// + /*--cef()--*/ + virtual CefRefPtr GetFocusedFrame() =0; + + /// + // Returns the frame with the specified identifier, or NULL if not found. + /// + /*--cef(capi_name=get_frame_byident)--*/ + virtual CefRefPtr GetFrame(int64 identifier) =0; + + /// + // Returns the frame with the specified name, or NULL if not found. + /// + /*--cef()--*/ + virtual CefRefPtr GetFrame(const CefString& name) =0; + + /// + // Returns the number of frames that currently exist. + /// + /*--cef()--*/ + virtual size_t GetFrameCount() =0; + + /// + // Returns the identifiers of all existing frames. + /// + /*--cef(count_func=identifiers:GetFrameCount)--*/ + virtual void GetFrameIdentifiers(std::vector& identifiers) =0; + + /// + // Returns the names of all existing frames. + /// + /*--cef()--*/ + virtual void GetFrameNames(std::vector& names) =0; + + // + // Send a message to the specified |target_process|. Returns true if the + // message was sent successfully. + /// + /*--cef()--*/ + virtual bool SendProcessMessage(CefProcessId target_process, + CefRefPtr message) =0; +}; + + +/// +// Callback interface for CefBrowserHost::RunFileDialog. The methods of this +// class will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefRunFileDialogCallback : public virtual CefBase { + public: + /// + // Called asynchronously after the file dialog is dismissed. If the selection + // was successful |file_paths| will be a single value or a list of values + // depending on the dialog mode. If the selection was cancelled |file_paths| + // will be empty. + /// + /*--cef(capi_name=cont)--*/ + virtual void OnFileDialogDismissed( + CefRefPtr browser_host, + const std::vector& file_paths) =0; +}; + + +/// +// Class used to represent the browser process aspects of a browser window. The +// methods of this class can only be called in the browser process. They may be +// called on any thread in that process unless otherwise indicated in the +// comments. +/// +/*--cef(source=library)--*/ +class CefBrowserHost : public virtual CefBase { + public: + typedef cef_drag_operations_mask_t DragOperationsMask; + typedef cef_file_dialog_mode_t FileDialogMode; + typedef cef_mouse_button_type_t MouseButtonType; + typedef cef_paint_element_type_t PaintElementType; + + /// + // Create a new browser window using the window parameters specified by + // |windowInfo|. All values will be copied internally and the actual window + // will be created on the UI thread. If |request_context| is empty the + // global request context will be used. This method can be called on any + // browser process thread and will not block. + /// + /*--cef(optional_param=client,optional_param=url, + optional_param=request_context)--*/ + static bool CreateBrowser(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context); + + /// + // Create a new browser window using the window parameters specified by + // |windowInfo|. If |request_context| is empty the global request context + // will be used. This method can only be called on the browser process UI + // thread. + /// + /*--cef(optional_param=client,optional_param=url, + optional_param=request_context)--*/ + static CefRefPtr CreateBrowserSync( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context); + + /// + // Returns the hosted browser object. + /// + /*--cef()--*/ + virtual CefRefPtr GetBrowser() =0; + + /// + // Request that the browser close. The JavaScript 'onbeforeunload' event will + // be fired. If |force_close| is false the event handler, if any, will be + // allowed to prompt the user and the user can optionally cancel the close. + // If |force_close| is true the prompt will not be displayed and the close + // will proceed. Results in a call to CefLifeSpanHandler::DoClose() if the + // event handler allows the close or if |force_close| is true. See + // CefLifeSpanHandler::DoClose() documentation for additional usage + // information. + /// + /*--cef()--*/ + virtual void CloseBrowser(bool force_close) =0; + + /// + // Set whether the browser is focused. + /// + /*--cef()--*/ + virtual void SetFocus(bool focus) =0; + + /// + // Set whether the window containing the browser is visible + // (minimized/unminimized, app hidden/unhidden, etc). Only used on Mac OS X. + /// + /*--cef()--*/ + virtual void SetWindowVisibility(bool visible) =0; + + /// + // Retrieve the window handle for this browser. + /// + /*--cef()--*/ + virtual CefWindowHandle GetWindowHandle() =0; + + /// + // Retrieve the window handle of the browser that opened this browser. Will + // return NULL for non-popup windows. This method can be used in combination + // with custom handling of modal windows. + /// + /*--cef()--*/ + virtual CefWindowHandle GetOpenerWindowHandle() =0; + + /// + // Returns the client for this browser. + /// + /*--cef()--*/ + virtual CefRefPtr GetClient() =0; + + /// + // Returns the request context for this browser. + /// + /*--cef()--*/ + virtual CefRefPtr GetRequestContext() =0; + + /// + // Get the current zoom level. The default zoom level is 0.0. This method can + // only be called on the UI thread. + /// + /*--cef()--*/ + virtual double GetZoomLevel() =0; + + /// + // Change the zoom level to the specified value. Specify 0.0 to reset the + // zoom level. If called on the UI thread the change will be applied + // immediately. Otherwise, the change will be applied asynchronously on the + // UI thread. + /// + /*--cef()--*/ + virtual void SetZoomLevel(double zoomLevel) =0; + + /// + // Call to run a file chooser dialog. Only a single file chooser dialog may be + // pending at any given time. |mode| represents the type of dialog to display. + // |title| to the title to be used for the dialog and may be empty to show the + // default title ("Open" or "Save" depending on the mode). |default_file_name| + // is the default file name to select in the dialog. |accept_types| is a list + // of valid lower-cased MIME types or file extensions specified in an input + // element and is used to restrict selectable files to such types. |callback| + // will be executed after the dialog is dismissed or immediately if another + // dialog is already pending. The dialog will be initiated asynchronously on + // the UI thread. + /// + /*--cef(optional_param=title,optional_param=default_file_name, + optional_param=accept_types)--*/ + virtual void RunFileDialog(FileDialogMode mode, + const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) =0; + + /// + // Download the file at |url| using CefDownloadHandler. + /// + /*--cef()--*/ + virtual void StartDownload(const CefString& url) =0; + + /// + // Print the current browser contents. + /// + /*--cef()--*/ + virtual void Print() =0; + + /// + // Search for |searchText|. |identifier| can be used to have multiple searches + // running simultaniously. |forward| indicates whether to search forward or + // backward within the page. |matchCase| indicates whether the search should + // be case-sensitive. |findNext| indicates whether this is the first request + // or a follow-up. + /// + /*--cef()--*/ + virtual void Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) =0; + + /// + // Cancel all searches that are currently going on. + /// + /*--cef()--*/ + virtual void StopFinding(bool clearSelection) =0; + + /// + // Open developer tools in its own window. + /// + /*--cef()--*/ + virtual void ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) =0; + + /// + // Explicitly close the developer tools window if one exists for this browser + // instance. + /// + /*--cef()--*/ + virtual void CloseDevTools() =0; + + /// + // Set whether mouse cursor change is disabled. + /// + /*--cef()--*/ + virtual void SetMouseCursorChangeDisabled(bool disabled) =0; + + /// + // Returns true if mouse cursor change is disabled. + /// + /*--cef()--*/ + virtual bool IsMouseCursorChangeDisabled() =0; + + /// + // Returns true if window rendering is disabled. + /// + /*--cef()--*/ + virtual bool IsWindowRenderingDisabled() =0; + + /// + // Notify the browser that the widget has been resized. The browser will first + // call CefRenderHandler::GetViewRect to get the new size and then call + // CefRenderHandler::OnPaint asynchronously with the updated regions. This + // method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void WasResized() =0; + + /// + // Notify the browser that it has been hidden or shown. Layouting and + // CefRenderHandler::OnPaint notification will stop when the browser is + // hidden. This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void WasHidden(bool hidden) =0; + + /// + // Send a notification to the browser that the screen info has changed. The + // browser will then call CefRenderHandler::GetScreenInfo to update the + // screen information with the new values. This simulates moving the webview + // window from one display to another, or changing the properties of the + // current display. This method is only used when window rendering is + // disabled. + /// + /*--cef()--*/ + virtual void NotifyScreenInfoChanged() =0; + + /// + // Invalidate the view. The browser will call CefRenderHandler::OnPaint + // asynchronously. This method is only used when window rendering is + // disabled. + /// + /*--cef()--*/ + virtual void Invalidate(PaintElementType type) =0; + + /// + // Send a key event to the browser. + /// + /*--cef()--*/ + virtual void SendKeyEvent(const CefKeyEvent& event) =0; + + /// + // Send a mouse click event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. + /// + /*--cef()--*/ + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, + bool mouseUp, int clickCount) =0; + + /// + // Send a mouse move event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. + /// + /*--cef()--*/ + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) =0; + + /// + // Send a mouse wheel event to the browser. The |x| and |y| coordinates are + // relative to the upper-left corner of the view. The |deltaX| and |deltaY| + // values represent the movement delta in the X and Y directions respectively. + // In order to scroll inside select popups with window rendering disabled + // CefRenderHandler::GetScreenPoint should be implemented properly. + /// + /*--cef()--*/ + virtual void SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) =0; + + /// + // Send a focus event to the browser. + /// + /*--cef()--*/ + virtual void SendFocusEvent(bool setFocus) =0; + + /// + // Send a capture lost event to the browser. + /// + /*--cef()--*/ + virtual void SendCaptureLostEvent() =0; + + /// + // Get the NSTextInputContext implementation for enabling IME on Mac when + // window rendering is disabled. + /// + /*--cef(default_retval=NULL)--*/ + virtual CefTextInputContext GetNSTextInputContext() =0; + + /// + // Handles a keyDown event prior to passing it through the NSTextInputClient + // machinery. + /// + /*--cef()--*/ + virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) =0; + + /// + // Performs any additional actions after NSTextInputClient handles the event. + /// + /*--cef()--*/ + virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) =0; + + /// + // Call this method when the user drags the mouse into the web view (before + // calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). + // |drag_data| should not contain file contents as this type of data is not + // allowed to be dragged into the web view. File contents can be removed using + // CefDragData::ResetFileContents (for example, if |drag_data| comes from + // CefRenderHandler::StartDragging). + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, + DragOperationsMask allowed_ops) =0; + + /// + // Call this method each time the mouse is moved across the web view during + // a drag operation (after calling DragTargetDragEnter and before calling + // DragTargetDragLeave/DragTargetDrop). + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops) =0; + + /// + // Call this method when the user drags the mouse out of the web view (after + // calling DragTargetDragEnter). + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragTargetDragLeave() =0; + + /// + // Call this method when the user completes the drag operation by dropping + // the object onto the web view (after calling DragTargetDragEnter). + // The object being dropped is |drag_data|, given as an argument to + // the previous DragTargetDragEnter call. + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragTargetDrop(const CefMouseEvent& event) =0; + + /// + // Call this method when the drag operation started by a + // CefRenderHandler::StartDragging call has ended either in a drop or + // by being cancelled. |x| and |y| are mouse coordinates relative to the + // upper-left corner of the view. If the web view is both the drag source + // and the drag target then all DragTarget* methods should be called before + // DragSource* mthods. + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op) =0; + + /// + // Call this method when the drag operation started by a + // CefRenderHandler::StartDragging call has completed. This method may be + // called immediately without first calling DragSourceEndedAt to cancel a + // drag operation. If the web view is both the drag source and the drag + // target then all DragTarget* methods should be called before DragSource* + // mthods. + // This method is only used when window rendering is disabled. + /// + /*--cef()--*/ + virtual void DragSourceSystemDragEnded() =0; +}; + +#endif // CEF_INCLUDE_CEF_BROWSER_H_ diff --git a/include/cef_browser_process_handler.h b/include/cef_browser_process_handler.h new file mode 100644 index 000000000..5d62cb30c --- /dev/null +++ b/include/cef_browser_process_handler.h @@ -0,0 +1,92 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_ +#define CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_command_line.h" +#include "include/cef_print_handler.h" +#include "include/cef_values.h" + +/// +// Class used to implement browser process callbacks. The methods of this class +// will be called on the browser process main thread unless otherwise indicated. +/// +/*--cef(source=client)--*/ +class CefBrowserProcessHandler : public virtual CefBase { + public: + /// + // Called on the browser process UI thread immediately after the CEF context + // has been initialized. + /// + /*--cef()--*/ + virtual void OnContextInitialized() {} + + /// + // Called before a child process is launched. Will be called on the browser + // process UI thread when launching a render process and on the browser + // process IO thread when launching a GPU or plugin process. Provides an + // opportunity to modify the child process command line. Do not keep a + // reference to |command_line| outside of this method. + /// + /*--cef()--*/ + virtual void OnBeforeChildProcessLaunch( + CefRefPtr command_line) {} + + /// + // Called on the browser process IO thread after the main thread has been + // created for a new render process. Provides an opportunity to specify extra + // information that will be passed to + // CefRenderProcessHandler::OnRenderThreadCreated() in the render process. Do + // not keep a reference to |extra_info| outside of this method. + /// + /*--cef()--*/ + virtual void OnRenderProcessThreadCreated( + CefRefPtr extra_info) {} + + /// + // Return the handler for printing on Linux. If a print handler is not + // provided then printing will not be supported on the Linux platform. + /// + /*--cef()--*/ + virtual CefRefPtr GetPrintHandler() { + return NULL; + } +}; + +#endif // CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_ diff --git a/include/cef_callback.h b/include/cef_callback.h new file mode 100644 index 000000000..e5efebd2d --- /dev/null +++ b/include/cef_callback.h @@ -0,0 +1,75 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_CALLBACK_H_ +#define CEF_INCLUDE_CEF_CALLBACK_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Generic callback interface used for asynchronous continuation. +/// +/*--cef(source=library)--*/ +class CefCallback : public virtual CefBase { + public: + /// + // Continue processing. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue() =0; + + /// + // Cancel processing. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + +/// +// Generic callback interface used for asynchronous completion. +/// +/*--cef(source=client)--*/ +class CefCompletionCallback : public virtual CefBase { + public: + /// + // Method that will be called once the task is complete. + /// + /*--cef()--*/ + virtual void OnComplete() =0; +}; + +#endif // CEF_INCLUDE_CEF_CALLBACK_H_ diff --git a/include/cef_client.h b/include/cef_client.h new file mode 100644 index 000000000..d413e0e64 --- /dev/null +++ b/include/cef_client.h @@ -0,0 +1,185 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_CLIENT_H_ +#define CEF_INCLUDE_CEF_CLIENT_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_context_menu_handler.h" +#include "include/cef_dialog_handler.h" +#include "include/cef_display_handler.h" +#include "include/cef_download_handler.h" +#include "include/cef_drag_handler.h" +#include "include/cef_focus_handler.h" +#include "include/cef_geolocation_handler.h" +#include "include/cef_jsdialog_handler.h" +#include "include/cef_keyboard_handler.h" +#include "include/cef_life_span_handler.h" +#include "include/cef_load_handler.h" +#include "include/cef_process_message.h" +#include "include/cef_render_handler.h" +#include "include/cef_request_handler.h" + +/// +// Implement this interface to provide handler implementations. +/// +/*--cef(source=client,no_debugct_check)--*/ +class CefClient : public virtual CefBase { + public: + /// + // Return the handler for context menus. If no handler is provided the default + // implementation will be used. + /// + /*--cef()--*/ + virtual CefRefPtr GetContextMenuHandler() { + return NULL; + } + + /// + // Return the handler for dialogs. If no handler is provided the default + // implementation will be used. + /// + /*--cef()--*/ + virtual CefRefPtr GetDialogHandler() { + return NULL; + } + + /// + // Return the handler for browser display state events. + /// + /*--cef()--*/ + virtual CefRefPtr GetDisplayHandler() { + return NULL; + } + + /// + // Return the handler for download events. If no handler is returned downloads + // will not be allowed. + /// + /*--cef()--*/ + virtual CefRefPtr GetDownloadHandler() { + return NULL; + } + + /// + // Return the handler for drag events. + /// + /*--cef()--*/ + virtual CefRefPtr GetDragHandler() { + return NULL; + } + + /// + // Return the handler for focus events. + /// + /*--cef()--*/ + virtual CefRefPtr GetFocusHandler() { + return NULL; + } + + /// + // Return the handler for geolocation permissions requests. If no handler is + // provided geolocation access will be denied by default. + /// + /*--cef()--*/ + virtual CefRefPtr GetGeolocationHandler() { + return NULL; + } + + /// + // Return the handler for JavaScript dialogs. If no handler is provided the + // default implementation will be used. + /// + /*--cef()--*/ + virtual CefRefPtr GetJSDialogHandler() { + return NULL; + } + + /// + // Return the handler for keyboard events. + /// + /*--cef()--*/ + virtual CefRefPtr GetKeyboardHandler() { + return NULL; + } + + /// + // Return the handler for browser life span events. + /// + /*--cef()--*/ + virtual CefRefPtr GetLifeSpanHandler() { + return NULL; + } + + /// + // Return the handler for browser load status events. + /// + /*--cef()--*/ + virtual CefRefPtr GetLoadHandler() { + return NULL; + } + + /// + // Return the handler for off-screen rendering events. + /// + /*--cef()--*/ + virtual CefRefPtr GetRenderHandler() { + return NULL; + } + + /// + // Return the handler for browser request events. + /// + /*--cef()--*/ + virtual CefRefPtr GetRequestHandler() { + return NULL; + } + + /// + // Called when a new message is received from a different process. Return true + // if the message was handled or false otherwise. Do not keep a reference to + // or attempt to access the message outside of this callback. + /// + /*--cef()--*/ + virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) { + return false; + } +}; + +#endif // CEF_INCLUDE_CEF_CLIENT_H_ diff --git a/include/cef_command_line.h b/include/cef_command_line.h new file mode 100644 index 000000000..96241cf43 --- /dev/null +++ b/include/cef_command_line.h @@ -0,0 +1,208 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_COMMAND_LINE_H_ +#define CEF_INCLUDE_CEF_COMMAND_LINE_H_ +#pragma once + +#include "include/cef_base.h" +#include +#include + +/// +// Class used to create and/or parse command line arguments. Arguments with +// '--', '-' and, on Windows, '/' prefixes are considered switches. Switches +// will always precede any arguments without switch prefixes. Switches can +// optionally have a value specified using the '=' delimiter (e.g. +// "-switch=value"). An argument of "--" will terminate switch parsing with all +// subsequent tokens, regardless of prefix, being interpreted as non-switch +// arguments. Switch names are considered case-insensitive. This class can be +// used before CefInitialize() is called. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefCommandLine : public virtual CefBase { + public: + typedef std::vector ArgumentList; + typedef std::map SwitchMap; + + /// + // Create a new CefCommandLine instance. + /// + /*--cef(api_hash_check)--*/ + static CefRefPtr CreateCommandLine(); + + /// + // Returns the singleton global CefCommandLine object. The returned object + // will be read-only. + /// + /*--cef(api_hash_check)--*/ + static CefRefPtr GetGlobalCommandLine(); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // function returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns a writable copy of this object. + /// + /*--cef()--*/ + virtual CefRefPtr Copy() =0; + + /// + // Initialize the command line with the specified |argc| and |argv| values. + // The first argument must be the name of the program. This method is only + // supported on non-Windows platforms. + /// + /*--cef()--*/ + virtual void InitFromArgv(int argc, const char* const* argv) =0; + + /// + // Initialize the command line with the string returned by calling + // GetCommandLineW(). This method is only supported on Windows. + /// + /*--cef()--*/ + virtual void InitFromString(const CefString& command_line) =0; + + /// + // Reset the command-line switches and arguments but leave the program + // component unchanged. + /// + /*--cef()--*/ + virtual void Reset() =0; + + /// + // Retrieve the original command line string as a vector of strings. + // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* } + /// + /*--cef()--*/ + virtual void GetArgv(std::vector& argv) =0; + + /// + // Constructs and returns the represented command line string. Use this method + // cautiously because quoting behavior is unclear. + /// + /*--cef()--*/ + virtual CefString GetCommandLineString() =0; + + /// + // Get the program part of the command line string (the first item). + /// + /*--cef()--*/ + virtual CefString GetProgram() =0; + + /// + // Set the program part of the command line string (the first item). + /// + /*--cef()--*/ + virtual void SetProgram(const CefString& program) =0; + + /// + // Returns true if the command line has switches. + /// + /*--cef()--*/ + virtual bool HasSwitches() =0; + + /// + // Returns true if the command line contains the given switch. + /// + /*--cef()--*/ + virtual bool HasSwitch(const CefString& name) =0; + + /// + // Returns the value associated with the given switch. If the switch has no + // value or isn't present this method returns the empty string. + /// + /*--cef()--*/ + virtual CefString GetSwitchValue(const CefString& name) =0; + + /// + // Returns the map of switch names and values. If a switch has no value an + // empty string is returned. + /// + /*--cef()--*/ + virtual void GetSwitches(SwitchMap& switches) =0; + + /// + // Add a switch to the end of the command line. If the switch has no value + // pass an empty value string. + /// + /*--cef()--*/ + virtual void AppendSwitch(const CefString& name) =0; + + /// + // Add a switch with the specified value to the end of the command line. + /// + /*--cef()--*/ + virtual void AppendSwitchWithValue(const CefString& name, + const CefString& value) =0; + + /// + // True if there are remaining command line arguments. + /// + /*--cef()--*/ + virtual bool HasArguments() =0; + + /// + // Get the remaining command line arguments. + /// + /*--cef()--*/ + virtual void GetArguments(ArgumentList& arguments) =0; + + /// + // Add an argument to the end of the command line. + /// + /*--cef()--*/ + virtual void AppendArgument(const CefString& argument) =0; + + /// + // Insert a command before the current command. + // Common for debuggers, like "valgrind" or "gdb --args". + /// + /*--cef()--*/ + virtual void PrependWrapper(const CefString& wrapper) =0; +}; + +#endif // CEF_INCLUDE_CEF_COMMAND_LINE_H_ diff --git a/include/cef_context_menu_handler.h b/include/cef_context_menu_handler.h new file mode 100644 index 000000000..048a2bcc5 --- /dev/null +++ b/include/cef_context_menu_handler.h @@ -0,0 +1,210 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_CONTEXT_MENU_HANDLER_H_ +#define CEF_INCLUDE_CEF_CONTEXT_MENU_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_menu_model.h" + +class CefContextMenuParams; + +/// +// Implement this interface to handle context menu events. The methods of this +// class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefContextMenuHandler : public virtual CefBase { + public: + typedef cef_event_flags_t EventFlags; + + /// + // Called before a context menu is displayed. |params| provides information + // about the context menu state. |model| initially contains the default + // context menu. The |model| can be cleared to show no context menu or + // modified to show a custom menu. Do not keep references to |params| or + // |model| outside of this callback. + /// + /*--cef()--*/ + virtual void OnBeforeContextMenu(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) {} + + /// + // Called to execute a command selected from the context menu. Return true if + // the command was handled or false for the default implementation. See + // cef_menu_id_t for the command ids that have default implementations. All + // user-defined command ids should be between MENU_ID_USER_FIRST and + // MENU_ID_USER_LAST. |params| will have the same values as what was passed to + // OnBeforeContextMenu(). Do not keep a reference to |params| outside of this + // callback. + /// + /*--cef()--*/ + virtual bool OnContextMenuCommand(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + int command_id, + EventFlags event_flags) { return false; } + + /// + // Called when the context menu is dismissed irregardless of whether the menu + // was empty or a command was selected. + /// + /*--cef()--*/ + virtual void OnContextMenuDismissed(CefRefPtr browser, + CefRefPtr frame) {} +}; + + +/// +// Provides information about the context menu state. The ethods of this class +// can only be accessed on browser process the UI thread. +/// +/*--cef(source=library)--*/ +class CefContextMenuParams : public virtual CefBase { + public: + typedef cef_context_menu_type_flags_t TypeFlags; + typedef cef_context_menu_media_type_t MediaType; + typedef cef_context_menu_media_state_flags_t MediaStateFlags; + typedef cef_context_menu_edit_state_flags_t EditStateFlags; + + /// + // Returns the X coordinate of the mouse where the context menu was invoked. + // Coords are relative to the associated RenderView's origin. + /// + /*--cef()--*/ + virtual int GetXCoord() =0; + + /// + // Returns the Y coordinate of the mouse where the context menu was invoked. + // Coords are relative to the associated RenderView's origin. + /// + /*--cef()--*/ + virtual int GetYCoord() =0; + + /// + // Returns flags representing the type of node that the context menu was + // invoked on. + /// + /*--cef(default_retval=CM_TYPEFLAG_NONE)--*/ + virtual TypeFlags GetTypeFlags() =0; + + /// + // Returns the URL of the link, if any, that encloses the node that the + // context menu was invoked on. + /// + /*--cef()--*/ + virtual CefString GetLinkUrl() =0; + + /// + // Returns the link URL, if any, to be used ONLY for "copy link address". We + // don't validate this field in the frontend process. + /// + /*--cef()--*/ + virtual CefString GetUnfilteredLinkUrl() =0; + + /// + // Returns the source URL, if any, for the element that the context menu was + // invoked on. Example of elements with source URLs are img, audio, and video. + /// + /*--cef()--*/ + virtual CefString GetSourceUrl() =0; + + /// + // Returns true if the context menu was invoked on an image which has + // non-empty contents. + /// + /*--cef()--*/ + virtual bool HasImageContents() =0; + + /// + // Returns the URL of the top level page that the context menu was invoked on. + /// + /*--cef()--*/ + virtual CefString GetPageUrl() =0; + + /// + // Returns the URL of the subframe that the context menu was invoked on. + /// + /*--cef()--*/ + virtual CefString GetFrameUrl() =0; + + /// + // Returns the character encoding of the subframe that the context menu was + // invoked on. + /// + /*--cef()--*/ + virtual CefString GetFrameCharset() =0; + + /// + // Returns the type of context node that the context menu was invoked on. + /// + /*--cef(default_retval=CM_MEDIATYPE_NONE)--*/ + virtual MediaType GetMediaType() =0; + + /// + // Returns flags representing the actions supported by the media element, if + // any, that the context menu was invoked on. + /// + /*--cef(default_retval=CM_MEDIAFLAG_NONE)--*/ + virtual MediaStateFlags GetMediaStateFlags() =0; + + /// + // Returns the text of the selection, if any, that the context menu was + // invoked on. + /// + /*--cef()--*/ + virtual CefString GetSelectionText() =0; + + /// + // Returns true if the context menu was invoked on an editable node. + /// + /*--cef()--*/ + virtual bool IsEditable() =0; + + /// + // Returns flags representing the actions supported by the editable node, if + // any, that the context menu was invoked on. + /// + /*--cef(default_retval=CM_EDITFLAG_NONE)--*/ + virtual EditStateFlags GetEditStateFlags() =0; +}; + +#endif // CEF_INCLUDE_CEF_CONTEXT_MENU_HANDLER_H_ diff --git a/include/cef_cookie.h b/include/cef_cookie.h new file mode 100644 index 000000000..73506dc46 --- /dev/null +++ b/include/cef_cookie.h @@ -0,0 +1,166 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_COOKIE_H_ +#define CEF_INCLUDE_CEF_COOKIE_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_callback.h" +#include + +class CefCookieVisitor; + + +/// +// Class used for managing cookies. The methods of this class may be called on +// any thread unless otherwise indicated. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefCookieManager : public virtual CefBase { + public: + /// + // Returns the global cookie manager. By default data will be stored at + // CefSettings.cache_path if specified or in memory otherwise. + /// + /*--cef()--*/ + static CefRefPtr GetGlobalManager(); + + /// + // Creates a new cookie manager. If |path| is empty data will be stored in + // memory only. Otherwise, data will be stored at the specified |path|. To + // persist session cookies (cookies without an expiry date or validity + // interval) set |persist_session_cookies| to true. Session cookies are + // generally intended to be transient and most Web browsers do not persist + // them. Returns NULL if creation fails. + /// + /*--cef(optional_param=path)--*/ + static CefRefPtr CreateManager( + const CefString& path, + bool persist_session_cookies); + + /// + // Set the schemes supported by this manager. By default only "http" and + // "https" schemes are supported. Must be called before any cookies are + // accessed. + /// + /*--cef()--*/ + virtual void SetSupportedSchemes(const std::vector& schemes) =0; + + /// + // Visit all cookies. The returned cookies are ordered by longest path, then + // by earliest creation date. Returns false if cookies cannot be accessed. + /// + /*--cef()--*/ + virtual bool VisitAllCookies(CefRefPtr visitor) =0; + + /// + // Visit a subset of cookies. The results are filtered by the given url + // scheme, host, domain and path. If |includeHttpOnly| is true HTTP-only + // cookies will also be included in the results. The returned cookies are + // ordered by longest path, then by earliest creation date. Returns false if + // cookies cannot be accessed. + /// + /*--cef()--*/ + virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, + CefRefPtr visitor) =0; + + /// + // Sets a cookie given a valid URL and explicit user-provided cookie + // attributes. This function expects each attribute to be well-formed. It will + // check for disallowed characters (e.g. the ';' character is disallowed + // within the cookie value attribute) and will return false without setting + // the cookie if such characters are found. This method must be called on the + // IO thread. + /// + /*--cef()--*/ + virtual bool SetCookie(const CefString& url, const CefCookie& cookie) =0; + + /// + // Delete all cookies that match the specified parameters. If both |url| and + // values |cookie_name| are specified all host and domain cookies matching + // both will be deleted. If only |url| is specified all host cookies (but not + // domain cookies) irrespective of path will be deleted. If |url| is empty all + // cookies for all hosts and domains will be deleted. Returns false if a non- + // empty invalid URL is specified or if cookies cannot be accessed. This + // method must be called on the IO thread. + /// + /*--cef(optional_param=url,optional_param=cookie_name)--*/ + virtual bool DeleteCookies(const CefString& url, + const CefString& cookie_name) =0; + + /// + // Sets the directory path that will be used for storing cookie data. If + // |path| is empty data will be stored in memory only. Otherwise, data will be + // stored at the specified |path|. To persist session cookies (cookies without + // an expiry date or validity interval) set |persist_session_cookies| to true. + // Session cookies are generally intended to be transient and most Web browsers + // do not persist them. Returns false if cookies cannot be accessed. + /// + /*--cef(optional_param=path)--*/ + virtual bool SetStoragePath(const CefString& path, + bool persist_session_cookies) =0; + + /// + // Flush the backing store (if any) to disk and execute the specified + // |callback| on the IO thread when done. Returns false if cookies cannot be + // accessed. + /// + /*--cef(optional_param=handler)--*/ + virtual bool FlushStore(CefRefPtr callback) =0; +}; + + +/// +// Interface to implement for visiting cookie values. The methods of this class +// will always be called on the IO thread. +/// +/*--cef(source=client)--*/ +class CefCookieVisitor : public virtual CefBase { + public: + /// + // Method that will be called once for each cookie. |count| is the 0-based + // index for the current cookie. |total| is the total number of cookies. + // Set |deleteCookie| to true to delete the cookie currently being visited. + // Return false to stop visiting cookies. This method may never be called if + // no cookies are found. + /// + /*--cef()--*/ + virtual bool Visit(const CefCookie& cookie, int count, int total, + bool& deleteCookie) =0; +}; + +#endif // CEF_INCLUDE_CEF_COOKIE_H_ diff --git a/include/cef_dialog_handler.h b/include/cef_dialog_handler.h new file mode 100644 index 000000000..83e1048a4 --- /dev/null +++ b/include/cef_dialog_handler.h @@ -0,0 +1,98 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DIALOG_HANDLER_H_ +#define CEF_INCLUDE_CEF_DIALOG_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Callback interface for asynchronous continuation of file dialog requests. +/// +/*--cef(source=library)--*/ +class CefFileDialogCallback : public virtual CefBase { + public: + /// + // Continue the file selection with the specified |file_paths|. This may be + // a single value or a list of values depending on the dialog mode. An empty + // value is treated the same as calling Cancel(). + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(const std::vector& file_paths) =0; + + /// + // Cancel the file selection. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + + +/// +// Implement this interface to handle dialog events. The methods of this class +// will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefDialogHandler : public virtual CefBase { + public: + typedef cef_file_dialog_mode_t FileDialogMode; + + /// + // Called to run a file chooser dialog. |mode| represents the type of dialog + // to display. |title| to the title to be used for the dialog and may be empty + // to show the default title ("Open" or "Save" depending on the mode). + // |default_file_name| is the default file name to select in the dialog. + // |accept_types| is a list of valid lower-cased MIME types or file extensions + // specified in an input element and is used to restrict selectable files to + // such types. To display a custom dialog return true and execute |callback| + // either inline or at a later time. To display the default dialog return + // false. + /// + /*--cef(optional_param=title,optional_param=default_file_name, + optional_param=accept_types)--*/ + virtual bool OnFileDialog(CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) { + return false; + } +}; + +#endif // CEF_INCLUDE_CEF_DIALOG_HANDLER_H_ diff --git a/include/cef_display_handler.h b/include/cef_display_handler.h new file mode 100644 index 000000000..681728cd7 --- /dev/null +++ b/include/cef_display_handler.h @@ -0,0 +1,98 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ +#define CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" + +/// +// Implement this interface to handle events related to browser display state. +// The methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefDisplayHandler : public virtual CefBase { + public: + /// + // Called when a frame's address has changed. + /// + /*--cef()--*/ + virtual void OnAddressChange(CefRefPtr browser, + CefRefPtr frame, + const CefString& url) {} + + /// + // Called when the page title changes. + /// + /*--cef(optional_param=title)--*/ + virtual void OnTitleChange(CefRefPtr browser, + const CefString& title) {} + + /// + // Called when the browser is about to display a tooltip. |text| contains the + // text that will be displayed in the tooltip. To handle the display of the + // tooltip yourself return true. Otherwise, you can optionally modify |text| + // and then return false to allow the browser to display the tooltip. + // When window rendering is disabled the application is responsible for + // drawing tooltips and the return value is ignored. + /// + /*--cef(optional_param=text)--*/ + virtual bool OnTooltip(CefRefPtr browser, + CefString& text) { return false; } + + /// + // Called when the browser receives a status message. |value| contains the + // text that will be displayed in the status message. + /// + /*--cef(optional_param=value)--*/ + virtual void OnStatusMessage(CefRefPtr browser, + const CefString& value) {} + + /// + // Called to display a console message. Return true to stop the message from + // being output to the console. + /// + /*--cef(optional_param=message,optional_param=source)--*/ + virtual bool OnConsoleMessage(CefRefPtr browser, + const CefString& message, + const CefString& source, + int line) { return false; } +}; + +#endif // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ diff --git a/include/cef_dom.h b/include/cef_dom.h new file mode 100644 index 000000000..f155e2f31 --- /dev/null +++ b/include/cef_dom.h @@ -0,0 +1,435 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DOM_H_ +#define CEF_INCLUDE_CEF_DOM_H_ +#pragma once + +#include "include/cef_base.h" +#include + +class CefDOMDocument; +class CefDOMEventListener; +class CefDOMNode; + +/// +// Interface to implement for visiting the DOM. The methods of this class will +// be called on the render process main thread. +/// +/*--cef(source=client)--*/ +class CefDOMVisitor : public virtual CefBase { + public: + /// + // Method executed for visiting the DOM. The document object passed to this + // method represents a snapshot of the DOM at the time this method is + // executed. DOM objects are only valid for the scope of this method. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this method. + /// + /*--cef()--*/ + virtual void Visit(CefRefPtr document) =0; +}; + + +/// +// Class used to represent a DOM document. The methods of this class should only +// be called on the render process main thread thread. +/// +/*--cef(source=library)--*/ +class CefDOMDocument : public virtual CefBase { + public: + typedef cef_dom_document_type_t Type; + + /// + // Returns the document type. + /// + /*--cef(default_retval=DOM_DOCUMENT_TYPE_UNKNOWN)--*/ + virtual Type GetType() =0; + + /// + // Returns the root document node. + /// + /*--cef()--*/ + virtual CefRefPtr GetDocument() =0; + + /// + // Returns the BODY node of an HTML document. + /// + /*--cef()--*/ + virtual CefRefPtr GetBody() =0; + + /// + // Returns the HEAD node of an HTML document. + /// + /*--cef()--*/ + virtual CefRefPtr GetHead() =0; + + /// + // Returns the title of an HTML document. + /// + /*--cef()--*/ + virtual CefString GetTitle() =0; + + /// + // Returns the document element with the specified ID value. + /// + /*--cef()--*/ + virtual CefRefPtr GetElementById(const CefString& id) =0; + + /// + // Returns the node that currently has keyboard focus. + /// + /*--cef()--*/ + virtual CefRefPtr GetFocusedNode() =0; + + /// + // Returns true if a portion of the document is selected. + /// + /*--cef()--*/ + virtual bool HasSelection() =0; + + /// + // Returns the selection start node. + /// + /*--cef()--*/ + virtual CefRefPtr GetSelectionStartNode() =0; + + /// + // Returns the selection offset within the start node. + /// + /*--cef()--*/ + virtual int GetSelectionStartOffset() =0; + + /// + // Returns the selection end node. + /// + /*--cef()--*/ + virtual CefRefPtr GetSelectionEndNode() =0; + + /// + // Returns the selection offset within the end node. + /// + /*--cef()--*/ + virtual int GetSelectionEndOffset() =0; + + /// + // Returns the contents of this selection as markup. + /// + /*--cef()--*/ + virtual CefString GetSelectionAsMarkup() =0; + + /// + // Returns the contents of this selection as text. + /// + /*--cef()--*/ + virtual CefString GetSelectionAsText() =0; + + /// + // Returns the base URL for the document. + /// + /*--cef()--*/ + virtual CefString GetBaseURL() =0; + + /// + // Returns a complete URL based on the document base URL and the specified + // partial URL. + /// + /*--cef()--*/ + virtual CefString GetCompleteURL(const CefString& partialURL) =0; +}; + + +/// +// Class used to represent a DOM node. The methods of this class should only be +// called on the render process main thread. +/// +/*--cef(source=library)--*/ +class CefDOMNode : public virtual CefBase { + public: + typedef std::map AttributeMap; + typedef cef_dom_node_type_t Type; + + /// + // Returns the type for this node. + /// + /*--cef(default_retval=DOM_NODE_TYPE_UNSUPPORTED)--*/ + virtual Type GetType() =0; + + /// + // Returns true if this is a text node. + /// + /*--cef()--*/ + virtual bool IsText() =0; + + /// + // Returns true if this is an element node. + /// + /*--cef()--*/ + virtual bool IsElement() =0; + + /// + // Returns true if this is an editable node. + /// + /*--cef()--*/ + virtual bool IsEditable() =0; + + /// + // Returns true if this is a form control element node. + /// + /*--cef()--*/ + virtual bool IsFormControlElement() =0; + + /// + // Returns the type of this form control element node. + /// + /*--cef()--*/ + virtual CefString GetFormControlElementType() =0; + + /// + // Returns true if this object is pointing to the same handle as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr that) =0; + + /// + // Returns the name of this node. + /// + /*--cef()--*/ + virtual CefString GetName() =0; + + /// + // Returns the value of this node. + /// + /*--cef()--*/ + virtual CefString GetValue() =0; + + /// + // Set the value of this node. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetValue(const CefString& value) =0; + + /// + // Returns the contents of this node as markup. + /// + /*--cef()--*/ + virtual CefString GetAsMarkup() =0; + + /// + // Returns the document associated with this node. + /// + /*--cef()--*/ + virtual CefRefPtr GetDocument() =0; + + /// + // Returns the parent node. + /// + /*--cef()--*/ + virtual CefRefPtr GetParent() =0; + + /// + // Returns the previous sibling node. + /// + /*--cef()--*/ + virtual CefRefPtr GetPreviousSibling() =0; + + /// + // Returns the next sibling node. + /// + /*--cef()--*/ + virtual CefRefPtr GetNextSibling() =0; + + /// + // Returns true if this node has child nodes. + /// + /*--cef()--*/ + virtual bool HasChildren() =0; + + /// + // Return the first child node. + /// + /*--cef()--*/ + virtual CefRefPtr GetFirstChild() =0; + + /// + // Returns the last child node. + /// + /*--cef()--*/ + virtual CefRefPtr GetLastChild() =0; + + /// + // Add an event listener to this node for the specified event type. If + // |useCapture| is true then this listener will be considered a capturing + // listener. Capturing listeners will recieve all events of the specified + // type before the events are dispatched to any other event targets beneath + // the current node in the tree. Events which are bubbling upwards through + // the tree will not trigger a capturing listener. Separate calls to this + // method can be used to register the same listener with and without capture. + // See WebCore/dom/EventNames.h for the list of supported event types. + /// + /*--cef()--*/ + virtual void AddEventListener(const CefString& eventType, + CefRefPtr listener, + bool useCapture) =0; + + + // The following methods are valid only for element nodes. + + /// + // Returns the tag name of this element. + /// + /*--cef()--*/ + virtual CefString GetElementTagName() =0; + + /// + // Returns true if this element has attributes. + /// + /*--cef()--*/ + virtual bool HasElementAttributes() =0; + + /// + // Returns true if this element has an attribute named |attrName|. + /// + /*--cef()--*/ + virtual bool HasElementAttribute(const CefString& attrName) =0; + + /// + // Returns the element attribute named |attrName|. + /// + /*--cef()--*/ + virtual CefString GetElementAttribute(const CefString& attrName) =0; + + /// + // Returns a map of all element attributes. + /// + /*--cef()--*/ + virtual void GetElementAttributes(AttributeMap& attrMap) =0; + + /// + // Set the value for the element attribute named |attrName|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool SetElementAttribute(const CefString& attrName, + const CefString& value) =0; + + /// + // Returns the inner text of the element. + /// + /*--cef()--*/ + virtual CefString GetElementInnerText() =0; +}; + + +/// +// Class used to represent a DOM event. The methods of this class should only +// be called on the render process main thread. +/// +/*--cef(source=library)--*/ +class CefDOMEvent : public virtual CefBase { + public: + typedef cef_dom_event_category_t Category; + typedef cef_dom_event_phase_t Phase; + + /// + // Returns the event type. + /// + /*--cef()--*/ + virtual CefString GetType() =0; + + /// + // Returns the event category. + /// + /*--cef(default_retval=DOM_EVENT_CATEGORY_UNKNOWN)--*/ + virtual Category GetCategory() =0; + + /// + // Returns the event processing phase. + /// + /*--cef(default_retval=DOM_EVENT_PHASE_UNKNOWN)--*/ + virtual Phase GetPhase() =0; + + /// + // Returns true if the event can bubble up the tree. + /// + /*--cef()--*/ + virtual bool CanBubble() =0; + + /// + // Returns true if the event can be canceled. + /// + /*--cef()--*/ + virtual bool CanCancel() =0; + + /// + // Returns the document associated with this event. + /// + /*--cef()--*/ + virtual CefRefPtr GetDocument() =0; + + /// + // Returns the target of the event. + /// + /*--cef()--*/ + virtual CefRefPtr GetTarget() =0; + + /// + // Returns the current target of the event. + /// + /*--cef()--*/ + virtual CefRefPtr GetCurrentTarget() =0; +}; + + +/// +// Interface to implement for handling DOM events. The methods of this class +// will be called on the render process main thread. +/// +/*--cef(source=client)--*/ +class CefDOMEventListener : public virtual CefBase { + public: + /// + // Called when an event is received. The event object passed to this method + // contains a snapshot of the DOM at the time this method is executed. DOM + // objects are only valid for the scope of this method. Do not keep references + // to or attempt to access any DOM objects outside the scope of this method. + /// + /*--cef()--*/ + virtual void HandleEvent(CefRefPtr event) =0; +}; + +#endif // CEF_INCLUDE_CEF_DOM_H_ diff --git a/include/cef_download_handler.h b/include/cef_download_handler.h new file mode 100644 index 000000000..f7c26b3cd --- /dev/null +++ b/include/cef_download_handler.h @@ -0,0 +1,112 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ +#define CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_download_item.h" + + +/// +// Callback interface used to asynchronously continue a download. +/// +/*--cef(source=library)--*/ +class CefBeforeDownloadCallback : public virtual CefBase { + public: + /// + // Call to continue the download. Set |download_path| to the full file path + // for the download including the file name or leave blank to use the + // suggested name and the default temp directory. Set |show_dialog| to true + // if you do wish to show the default "Save As" dialog. + /// + /*--cef(capi_name=cont,optional_param=download_path)--*/ + virtual void Continue(const CefString& download_path, bool show_dialog) =0; +}; + + +/// +// Callback interface used to asynchronously cancel a download. +/// +/*--cef(source=library)--*/ +class CefDownloadItemCallback : public virtual CefBase { + public: + /// + // Call to cancel the download. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + + +/// +// Class used to handle file downloads. The methods of this class will called +// on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefDownloadHandler : public virtual CefBase { + public: + /// + // Called before a download begins. |suggested_name| is the suggested name for + // the download file. By default the download will be canceled. Execute + // |callback| either asynchronously or in this method to continue the download + // if desired. Do not keep a reference to |download_item| outside of this + // method. + /// + /*--cef()--*/ + virtual void OnBeforeDownload( + CefRefPtr browser, + CefRefPtr download_item, + const CefString& suggested_name, + CefRefPtr callback) =0; + + /// + // Called when a download's status or progress information has been updated. + // This may be called multiple times before and after OnBeforeDownload(). + // Execute |callback| either asynchronously or in this method to cancel the + // download if desired. Do not keep a reference to |download_item| outside of + // this method. + /// + /*--cef()--*/ + virtual void OnDownloadUpdated( + CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) {} +}; + +#endif // CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ diff --git a/include/cef_download_item.h b/include/cef_download_item.h new file mode 100644 index 000000000..6f76ff5e4 --- /dev/null +++ b/include/cef_download_item.h @@ -0,0 +1,148 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DOWNLOAD_ITEM_H_ +#define CEF_INCLUDE_CEF_DOWNLOAD_ITEM_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Class used to represent a download item. +/// +/*--cef(source=library)--*/ +class CefDownloadItem : public virtual CefBase { + public: + /// + // Returns true if this object is valid. Do not call any other methods if this + // function returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if the download is in progress. + /// + /*--cef()--*/ + virtual bool IsInProgress() =0; + + /// + // Returns true if the download is complete. + /// + /*--cef()--*/ + virtual bool IsComplete() =0; + + /// + // Returns true if the download has been canceled or interrupted. + /// + /*--cef()--*/ + virtual bool IsCanceled() =0; + + /// + // Returns a simple speed estimate in bytes/s. + /// + /*--cef()--*/ + virtual int64 GetCurrentSpeed() =0; + + /// + // Returns the rough percent complete or -1 if the receive total size is + // unknown. + /// + /*--cef()--*/ + virtual int GetPercentComplete() =0; + + /// + // Returns the total number of bytes. + /// + /*--cef()--*/ + virtual int64 GetTotalBytes() =0; + + /// + // Returns the number of received bytes. + /// + /*--cef()--*/ + virtual int64 GetReceivedBytes() =0; + + /// + // Returns the time that the download started. + /// + /*--cef()--*/ + virtual CefTime GetStartTime() =0; + + /// + // Returns the time that the download ended. + /// + /*--cef()--*/ + virtual CefTime GetEndTime() =0; + + /// + // Returns the full path to the downloaded or downloading file. + /// + /*--cef()--*/ + virtual CefString GetFullPath() =0; + + /// + // Returns the unique identifier for this download. + /// + /*--cef()--*/ + virtual uint32 GetId() =0; + + /// + // Returns the URL. + /// + /*--cef()--*/ + virtual CefString GetURL() =0; + + /// + // Returns the suggested file name. + /// + /*--cef()--*/ + virtual CefString GetSuggestedFileName() =0; + + /// + // Returns the content disposition. + /// + /*--cef()--*/ + virtual CefString GetContentDisposition() =0; + + /// + // Returns the mime type. + /// + /*--cef()--*/ + virtual CefString GetMimeType() =0; +}; + +#endif // CEF_INCLUDE_CEF_DOWNLOAD_ITEM_H_ diff --git a/include/cef_drag_data.h b/include/cef_drag_data.h new file mode 100644 index 000000000..8f8094b44 --- /dev/null +++ b/include/cef_drag_data.h @@ -0,0 +1,198 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DRAG_DATA_H_ +#define CEF_INCLUDE_CEF_DRAG_DATA_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_stream.h" +#include + +/// +// Class used to represent drag data. The methods of this class may be called +// on any thread. +/// +/*--cef(source=library)--*/ +class CefDragData : public virtual CefBase { + public: + /// + // Create a new CefDragData object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns a copy of the current object. + /// + /*--cef()--*/ + virtual CefRefPtr Clone() =0; + + /// + // Returns true if this object is read-only. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns true if the drag data is a link. + /// + /*--cef()--*/ + virtual bool IsLink() =0; + + /// + // Returns true if the drag data is a text or html fragment. + /// + /*--cef()--*/ + virtual bool IsFragment() =0; + + /// + // Returns true if the drag data is a file. + /// + /*--cef()--*/ + virtual bool IsFile() =0; + + /// + // Return the link URL that is being dragged. + /// + /*--cef()--*/ + virtual CefString GetLinkURL() =0; + + /// + // Return the title associated with the link being dragged. + /// + /*--cef()--*/ + virtual CefString GetLinkTitle() =0; + + /// + // Return the metadata, if any, associated with the link being dragged. + /// + /*--cef()--*/ + virtual CefString GetLinkMetadata() =0; + + /// + // Return the plain text fragment that is being dragged. + /// + /*--cef()--*/ + virtual CefString GetFragmentText() =0; + + /// + // Return the text/html fragment that is being dragged. + /// + /*--cef()--*/ + virtual CefString GetFragmentHtml() =0; + + /// + // Return the base URL that the fragment came from. This value is used for + // resolving relative URLs and may be empty. + /// + /*--cef()--*/ + virtual CefString GetFragmentBaseURL() =0; + + /// + // Return the name of the file being dragged out of the browser window. + /// + /*--cef()--*/ + virtual CefString GetFileName() =0; + + /// + // Write the contents of the file being dragged out of the web view into + // |writer|. Returns the number of bytes sent to |writer|. If |writer| is + // NULL this method will return the size of the file contents in bytes. + // Call GetFileName() to get a suggested name for the file. + /// + /*--cef(optional_param=writer)--*/ + virtual size_t GetFileContents(CefRefPtr writer) =0; + + /// + // Retrieve the list of file names that are being dragged into the browser + // window. + /// + /*--cef()--*/ + virtual bool GetFileNames(std::vector& names) =0; + + /// + // Set the link URL that is being dragged. + /// + /*--cef(optional_param=url)--*/ + virtual void SetLinkURL(const CefString& url) =0; + + /// + // Set the title associated with the link being dragged. + /// + /*--cef(optional_param=title)--*/ + virtual void SetLinkTitle(const CefString& title) =0; + + /// + // Set the metadata associated with the link being dragged. + /// + /*--cef(optional_param=data)--*/ + virtual void SetLinkMetadata(const CefString& data) =0; + + /// + // Set the plain text fragment that is being dragged. + /// + /*--cef(optional_param=text)--*/ + virtual void SetFragmentText(const CefString& text) =0; + + /// + // Set the text/html fragment that is being dragged. + /// + /*--cef(optional_param=html)--*/ + virtual void SetFragmentHtml(const CefString& html) =0; + + /// + // Set the base URL that the fragment came from. + /// + /*--cef(optional_param=base_url)--*/ + virtual void SetFragmentBaseURL(const CefString& base_url) =0; + + /// + // Reset the file contents. You should do this before calling + // CefBrowserHost::DragTargetDragEnter as the web view does not allow us to + // drag in this kind of data. + /// + /*--cef()--*/ + virtual void ResetFileContents() =0; + + /// + // Add a file that is being dragged into the webview. + /// + /*--cef(optional_param=display_name)--*/ + virtual void AddFile(const CefString& path, const CefString& display_name) =0; +}; + +#endif // CEF_INCLUDE_CEF_DRAG_DATA_H_ diff --git a/include/cef_drag_handler.h b/include/cef_drag_handler.h new file mode 100644 index 000000000..7cfc40ba5 --- /dev/null +++ b/include/cef_drag_handler.h @@ -0,0 +1,66 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_DRAG_HANDLER_H_ +#define CEF_INCLUDE_CEF_DRAG_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_drag_data.h" +#include "include/cef_browser.h" + +/// +// Implement this interface to handle events related to dragging. The methods of +// this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefDragHandler : public virtual CefBase { + public: + typedef cef_drag_operations_mask_t DragOperationsMask; + + /// + // Called when an external drag event enters the browser window. |dragData| + // contains the drag event data and |mask| represents the type of drag + // operation. Return false for default drag handling behavior or true to + // cancel the drag event. + /// + /*--cef()--*/ + virtual bool OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, + DragOperationsMask mask) { return false; } +}; + +#endif // CEF_INCLUDE_CEF_DRAG_HANDLER_H_ diff --git a/include/cef_focus_handler.h b/include/cef_focus_handler.h new file mode 100644 index 000000000..1d91c42ab --- /dev/null +++ b/include/cef_focus_handler.h @@ -0,0 +1,81 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ +#define CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_dom.h" +#include "include/cef_frame.h" + +/// +// Implement this interface to handle events related to focus. The methods of +// this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefFocusHandler : public virtual CefBase { + public: + typedef cef_focus_source_t FocusSource; + + /// + // Called when the browser component is about to loose focus. For instance, if + // focus was on the last HTML element and the user pressed the TAB key. |next| + // will be true if the browser is giving focus to the next component and false + // if the browser is giving focus to the previous component. + /// + /*--cef()--*/ + virtual void OnTakeFocus(CefRefPtr browser, + bool next) {} + + /// + // Called when the browser component is requesting focus. |source| indicates + // where the focus request is originating from. Return false to allow the + // focus to be set or true to cancel setting the focus. + /// + /*--cef()--*/ + virtual bool OnSetFocus(CefRefPtr browser, + FocusSource source) { return false; } + + /// + // Called when the browser component has received focus. + /// + /*--cef()--*/ + virtual void OnGotFocus(CefRefPtr browser) {} +}; + +#endif // CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ diff --git a/include/cef_frame.h b/include/cef_frame.h new file mode 100644 index 000000000..adba66f1e --- /dev/null +++ b/include/cef_frame.h @@ -0,0 +1,224 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_FRAME_H_ +#define CEF_INCLUDE_CEF_FRAME_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_dom.h" +#include "include/cef_request.h" +#include "include/cef_stream.h" +#include "include/cef_string_visitor.h" + +class CefBrowser; +class CefV8Context; + +/// +// Class used to represent a frame in the browser window. When used in the +// browser process the methods of this class may be called on any thread unless +// otherwise indicated in the comments. When used in the render process the +// methods of this class may only be called on the main thread. +/// +/*--cef(source=library)--*/ +class CefFrame : public virtual CefBase { + public: + /// + // True if this object is currently attached to a valid frame. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Execute undo in this frame. + /// + /*--cef()--*/ + virtual void Undo() =0; + + /// + // Execute redo in this frame. + /// + /*--cef()--*/ + virtual void Redo() =0; + + /// + // Execute cut in this frame. + /// + /*--cef()--*/ + virtual void Cut() =0; + + /// + // Execute copy in this frame. + /// + /*--cef()--*/ + virtual void Copy() =0; + + /// + // Execute paste in this frame. + /// + /*--cef()--*/ + virtual void Paste() =0; + + /// + // Execute delete in this frame. + /// + /*--cef(capi_name=del)--*/ + virtual void Delete() =0; + + /// + // Execute select all in this frame. + /// + /*--cef()--*/ + virtual void SelectAll() =0; + + /// + // Save this frame's HTML source to a temporary file and open it in the + // default text viewing application. This method can only be called from the + // browser process. + /// + /*--cef()--*/ + virtual void ViewSource() =0; + + /// + // Retrieve this frame's HTML source as a string sent to the specified + // visitor. + /// + /*--cef()--*/ + virtual void GetSource(CefRefPtr visitor) =0; + + /// + // Retrieve this frame's display text as a string sent to the specified + // visitor. + /// + /*--cef()--*/ + virtual void GetText(CefRefPtr visitor) =0; + + /// + // Load the request represented by the |request| object. + /// + /*--cef()--*/ + virtual void LoadRequest(CefRefPtr request) =0; + + /// + // Load the specified |url|. + /// + /*--cef()--*/ + virtual void LoadURL(const CefString& url) =0; + + /// + // Load the contents of |string_val| with the specified dummy |url|. |url| + // should have a standard scheme (for example, http scheme) or behaviors like + // link clicks and web security restrictions may not behave as expected. + /// + /*--cef()--*/ + virtual void LoadString(const CefString& string_val, + const CefString& url) =0; + + /// + // Execute a string of JavaScript code in this frame. The |script_url| + // parameter is the URL where the script in question can be found, if any. + // The renderer may request this URL to show the developer the source of the + // error. The |start_line| parameter is the base line number to use for error + // reporting. + /// + /*--cef(optional_param=script_url)--*/ + virtual void ExecuteJavaScript(const CefString& code, + const CefString& script_url, + int start_line) =0; + + /// + // Returns true if this is the main (top-level) frame. + /// + /*--cef()--*/ + virtual bool IsMain() =0; + + /// + // Returns true if this is the focused frame. + /// + /*--cef()--*/ + virtual bool IsFocused() =0; + + /// + // Returns the name for this frame. If the frame has an assigned name (for + // example, set via the iframe "name" attribute) then that value will be + // returned. Otherwise a unique name will be constructed based on the frame + // parent hierarchy. The main (top-level) frame will always have an empty name + // value. + /// + /*--cef()--*/ + virtual CefString GetName() =0; + + /// + // Returns the globally unique identifier for this frame. + /// + /*--cef()--*/ + virtual int64 GetIdentifier() =0; + + /// + // Returns the parent of this frame or NULL if this is the main (top-level) + // frame. + /// + /*--cef()--*/ + virtual CefRefPtr GetParent() =0; + + /// + // Returns the URL currently loaded in this frame. + /// + /*--cef()--*/ + virtual CefString GetURL() =0; + + /// + // Returns the browser that this frame belongs to. + /// + /*--cef()--*/ + virtual CefRefPtr GetBrowser() =0; + + /// + // Get the V8 context associated with the frame. This method can only be + // called from the render process. + /// + /*--cef()--*/ + virtual CefRefPtr GetV8Context() =0; + + /// + // Visit the DOM document. This method can only be called from the render + // process. + /// + /*--cef()--*/ + virtual void VisitDOM(CefRefPtr visitor) =0; +}; + +#endif // CEF_INCLUDE_CEF_FRAME_H_ diff --git a/include/cef_geolocation.h b/include/cef_geolocation.h new file mode 100644 index 000000000..69c08779c --- /dev/null +++ b/include/cef_geolocation.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_GEOLOCATION_H_ +#define CEF_INCLUDE_CEF_GEOLOCATION_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Implement this interface to receive geolocation updates. The methods of this +// class will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefGetGeolocationCallback : public virtual CefBase { + public: + /// + // Called with the 'best available' location information or, if the location + // update failed, with error information. + /// + /*--cef()--*/ + virtual void OnLocationUpdate(const CefGeoposition& position) =0; +}; + +/// +// Request a one-time geolocation update. This function bypasses any user +// permission checks so should only be used by code that is allowed to access +// location information. +/// +/*--cef()--*/ +bool CefGetGeolocation(CefRefPtr callback); + +#endif // CEF_INCLUDE_CEF_GEOLOCATION_H_ diff --git a/include/cef_geolocation_handler.h b/include/cef_geolocation_handler.h new file mode 100644 index 000000000..679621a1f --- /dev/null +++ b/include/cef_geolocation_handler.h @@ -0,0 +1,97 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ +#define CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Callback interface used for asynchronous continuation of geolocation +// permission requests. +/// +/*--cef(source=library)--*/ +class CefGeolocationCallback : public virtual CefBase { + public: + /// + // Call to allow or deny geolocation access. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(bool allow) =0; +}; + + +/// +// Implement this interface to handle events related to geolocation permission +// requests. The methods of this class will be called on the browser process UI +// thread. +/// +/*--cef(source=client)--*/ +class CefGeolocationHandler : public virtual CefBase { + public: + /// + // Called when a page requests permission to access geolocation information. + // |requesting_url| is the URL requesting permission and |request_id| is the + // unique ID for the permission request. Return true and call + // CefGeolocationCallback::Continue() either in this method or at a later + // time to continue or cancel the request. Return false to cancel the request + // immediately. + /// + /*--cef()--*/ + virtual bool OnRequestGeolocationPermission( + CefRefPtr browser, + const CefString& requesting_url, + int request_id, + CefRefPtr callback) { + return false; + } + + /// + // Called when a geolocation access request is canceled. |requesting_url| is + // the URL that originally requested permission and |request_id| is the unique + // ID for the permission request. + /// + /*--cef()--*/ + virtual void OnCancelGeolocationPermission( + CefRefPtr browser, + const CefString& requesting_url, + int request_id) { + } +}; + +#endif // CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ diff --git a/include/cef_jsdialog_handler.h b/include/cef_jsdialog_handler.h new file mode 100644 index 000000000..29548966e --- /dev/null +++ b/include/cef_jsdialog_handler.h @@ -0,0 +1,128 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ +#define CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Callback interface used for asynchronous continuation of JavaScript dialog +// requests. +/// +/*--cef(source=library)--*/ +class CefJSDialogCallback : public virtual CefBase { + public: + /// + // Continue the JS dialog request. Set |success| to true if the OK button was + // pressed. The |user_input| value should be specified for prompt dialogs. + /// + /*--cef(capi_name=cont,optional_param=user_input)--*/ + virtual void Continue(bool success, + const CefString& user_input) =0; +}; + + +/// +// Implement this interface to handle events related to JavaScript dialogs. The +// methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefJSDialogHandler : public virtual CefBase { + public: + typedef cef_jsdialog_type_t JSDialogType; + + /// + // Called to run a JavaScript dialog. The |default_prompt_text| value will be + // specified for prompt dialogs only. Set |suppress_message| to true and + // return false to suppress the message (suppressing messages is preferable + // to immediately executing the callback as this is used to detect presumably + // malicious behavior like spamming alert messages in onbeforeunload). Set + // |suppress_message| to false and return false to use the default + // implementation (the default implementation will show one modal dialog at a + // time and suppress any additional dialog requests until the displayed dialog + // is dismissed). Return true if the application will use a custom dialog or + // if the callback has been executed immediately. Custom dialogs may be either + // modal or modeless. If a custom dialog is used the application must execute + // |callback| once the custom dialog is dismissed. + /// + /*--cef(optional_param=origin_url,optional_param=accept_lang, + optional_param=message_text,optional_param=default_prompt_text)--*/ + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + const CefString& accept_lang, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) { + return false; + } + + /// + // Called to run a dialog asking the user if they want to leave a page. Return + // false to use the default dialog implementation. Return true if the + // application will use a custom dialog or if the callback has been executed + // immediately. Custom dialogs may be either modal or modeless. If a custom + // dialog is used the application must execute |callback| once the custom + // dialog is dismissed. + /// + /*--cef(optional_param=message_text)--*/ + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) { + return false; + } + + /// + // Called to cancel any pending dialogs and reset any saved dialog state. Will + // be called due to events like page navigation irregardless of whether any + // dialogs are currently pending. + /// + /*--cef()--*/ + virtual void OnResetDialogState(CefRefPtr browser) {} + + /// + // Called when the default implementation dialog is closed. + /// + /*--cef()--*/ + virtual void OnDialogClosed(CefRefPtr browser) {} +}; + +#endif // CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ diff --git a/include/cef_keyboard_handler.h b/include/cef_keyboard_handler.h new file mode 100644 index 000000000..55cb57ef8 --- /dev/null +++ b/include/cef_keyboard_handler.h @@ -0,0 +1,74 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ +#define CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Implement this interface to handle events related to keyboard input. The +// methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefKeyboardHandler : public virtual CefBase { + public: + // Called before a keyboard event is sent to the renderer. |event| contains + // information about the keyboard event. |os_event| is the operating system + // event message, if any. Return true if the event was handled or false + // otherwise. If the event will be handled in OnKeyEvent() as a keyboard + // shortcut set |is_keyboard_shortcut| to true and return false. + /*--cef()--*/ + virtual bool OnPreKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event, + bool* is_keyboard_shortcut) { return false; } + + /// + // Called after the renderer and JavaScript in the page has had a chance to + // handle the event. |event| contains information about the keyboard event. + // |os_event| is the operating system event message, if any. Return true if + // the keyboard event was handled or false otherwise. + /// + /*--cef()--*/ + virtual bool OnKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, + CefEventHandle os_event) { return false; } +}; + +#endif // CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ diff --git a/include/cef_life_span_handler.h b/include/cef_life_span_handler.h new file mode 100644 index 000000000..14534961c --- /dev/null +++ b/include/cef_life_span_handler.h @@ -0,0 +1,164 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ +#define CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +class CefClient; + +/// +// Implement this interface to handle events related to browser life span. The +// methods of this class will be called on the UI thread unless otherwise +// indicated. +/// +/*--cef(source=client)--*/ +class CefLifeSpanHandler : public virtual CefBase { + public: + /// + // Called on the IO thread before a new popup window is created. The |browser| + // and |frame| parameters represent the source of the popup request. The + // |target_url| and |target_frame_name| values may be empty if none were + // specified with the request. The |popupFeatures| structure contains + // information about the requested popup window. To allow creation of the + // popup window optionally modify |windowInfo|, |client|, |settings| and + // |no_javascript_access| and return false. To cancel creation of the popup + // window return true. The |client| and |settings| values will default to the + // source browser's values. The |no_javascript_access| value indicates whether + // the new browser window should be scriptable and in the same process as the + // source browser. + /*--cef(optional_param=target_url,optional_param=target_frame_name)--*/ + virtual bool OnBeforePopup(CefRefPtr browser, + CefRefPtr frame, + const CefString& target_url, + const CefString& target_frame_name, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings, + bool* no_javascript_access) { + return false; + } + + /// + // Called after a new browser is created. + /// + /*--cef()--*/ + virtual void OnAfterCreated(CefRefPtr browser) {} + + /// + // Called when a modal window is about to display and the modal loop should + // begin running. Return false to use the default modal loop implementation or + // true to use a custom implementation. + /// + /*--cef()--*/ + virtual bool RunModal(CefRefPtr browser) { return false; } + + /// + // Called when a browser has recieved a request to close. This may result + // directly from a call to CefBrowserHost::CloseBrowser() or indirectly if the + // browser is a top-level OS window created by CEF and the user attempts to + // close the window. This method will be called after the JavaScript + // 'onunload' event has been fired. It will not be called for browsers after + // the associated OS window has been destroyed (for those browsers it is no + // longer possible to cancel the close). + // + // If CEF created an OS window for the browser returning false will send an OS + // close notification to the browser window's top-level owner (e.g. WM_CLOSE + // on Windows, performClose: on OS-X and "delete_event" on Linux). If no OS + // window exists (window rendering disabled) returning false will cause the + // browser object to be destroyed immediately. Return true if the browser is + // parented to another window and that other window needs to receive close + // notification via some non-standard technique. + // + // If an application provides its own top-level window it should handle OS + // close notifications by calling CefBrowserHost::CloseBrowser(false) instead + // of immediately closing (see the example below). This gives CEF an + // opportunity to process the 'onbeforeunload' event and optionally cancel the + // close before DoClose() is called. + // + // The CefLifeSpanHandler::OnBeforeClose() method will be called immediately + // before the browser object is destroyed. The application should only exit + // after OnBeforeClose() has been called for all existing browsers. + // + // If the browser represents a modal window and a custom modal loop + // implementation was provided in CefLifeSpanHandler::RunModal() this callback + // should be used to restore the opener window to a usable state. + // + // By way of example consider what should happen during window close when the + // browser is parented to an application-provided top-level OS window. + // 1. User clicks the window close button which sends an OS close + // notification (e.g. WM_CLOSE on Windows, performClose: on OS-X and + // "delete_event" on Linux). + // 2. Application's top-level window receives the close notification and: + // A. Calls CefBrowserHost::CloseBrowser(false). + // B. Cancels the window close. + // 3. JavaScript 'onbeforeunload' handler executes and shows the close + // confirmation dialog (which can be overridden via + // CefJSDialogHandler::OnBeforeUnloadDialog()). + // 4. User approves the close. + // 5. JavaScript 'onunload' handler executes. + // 6. Application's DoClose() handler is called. Application will: + // A. Set a flag to indicate that the next close attempt will be allowed. + // B. Return false. + // 7. CEF sends an OS close notification. + // 8. Application's top-level window receives the OS close notification and + // allows the window to close based on the flag from #6B. + // 9. Browser OS window is destroyed. + // 10. Application's CefLifeSpanHandler::OnBeforeClose() handler is called and + // the browser object is destroyed. + // 11. Application exits by calling CefQuitMessageLoop() if no other browsers + // exist. + /// + /*--cef()--*/ + virtual bool DoClose(CefRefPtr browser) { return false; } + + /// + // Called just before a browser is destroyed. Release all references to the + // browser object and do not attempt to execute any methods on the browser + // object after this callback returns. If this is a modal window and a custom + // modal loop implementation was provided in RunModal() this callback should + // be used to exit the custom modal loop. See DoClose() documentation for + // additional usage information. + /// + /*--cef()--*/ + virtual void OnBeforeClose(CefRefPtr browser) {} +}; + +#endif // CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ diff --git a/include/cef_load_handler.h b/include/cef_load_handler.h new file mode 100644 index 000000000..02d9d9f1a --- /dev/null +++ b/include/cef_load_handler.h @@ -0,0 +1,107 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_LOAD_HANDLER_H_ +#define CEF_INCLUDE_CEF_LOAD_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" + +/// +// Implement this interface to handle events related to browser load status. The +// methods of this class will be called on the browser process UI thread or +// render process main thread (TID_RENDERER). +/// +/*--cef(source=client)--*/ +class CefLoadHandler : public virtual CefBase { + public: + typedef cef_errorcode_t ErrorCode; + + /// + // Called when the loading state has changed. This callback will be executed + // twice -- once when loading is initiated either programmatically or by user + // action, and once when loading is terminated due to completion, cancellation + // of failure. + /// + /*--cef()--*/ + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) {} + + /// + // Called when the browser begins loading a frame. The |frame| value will + // never be empty -- call the IsMain() method to check if this frame is the + // main frame. Multiple frames may be loading at the same time. Sub-frames may + // start or continue loading after the main frame load has ended. This method + // may not be called for a particular frame if the load request for that frame + // fails. For notification of overall browser load status use + // OnLoadingStateChange instead. + /// + /*--cef()--*/ + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) {} + + /// + // Called when the browser is done loading a frame. The |frame| value will + // never be empty -- call the IsMain() method to check if this frame is the + // main frame. Multiple frames may be loading at the same time. Sub-frames may + // start or continue loading after the main frame load has ended. This method + // will always be called for all frames irrespective of whether the request + // completes successfully. + /// + /*--cef()--*/ + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) {} + + /// + // Called when the resource load for a navigation fails or is canceled. + // |errorCode| is the error code number, |errorText| is the error text and + // |failedUrl| is the URL that failed to load. See net\base\net_error_list.h + // for complete descriptions of the error codes. + /// + /*--cef(optional_param=errorText)--*/ + virtual void OnLoadError(CefRefPtr browser, + CefRefPtr frame, + ErrorCode errorCode, + const CefString& errorText, + const CefString& failedUrl) {} +}; + +#endif // CEF_INCLUDE_CEF_LOAD_HANDLER_H_ diff --git a/include/cef_menu_model.h b/include/cef_menu_model.h new file mode 100644 index 000000000..84728c58b --- /dev/null +++ b/include/cef_menu_model.h @@ -0,0 +1,402 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_MENU_MODEL_H_ +#define CEF_INCLUDE_CEF_MENU_MODEL_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Supports creation and modification of menus. See cef_menu_id_t for the +// command ids that have default implementations. All user-defined command ids +// should be between MENU_ID_USER_FIRST and MENU_ID_USER_LAST. The methods of +// this class can only be accessed on the browser process the UI thread. +/// +/*--cef(source=library)--*/ +class CefMenuModel : public virtual CefBase { + public: + typedef cef_menu_item_type_t MenuItemType; + + /// + // Clears the menu. Returns true on success. + /// + /*--cef()--*/ + virtual bool Clear() =0; + + /// + // Returns the number of items in this menu. + /// + /*--cef()--*/ + virtual int GetCount() =0; + + // + // Add a separator to the menu. Returns true on success. + /// + /*--cef()--*/ + virtual bool AddSeparator() =0; + + // + // Add an item to the menu. Returns true on success. + /// + /*--cef()--*/ + virtual bool AddItem(int command_id, + const CefString& label) =0; + + // + // Add a check item to the menu. Returns true on success. + /// + /*--cef()--*/ + virtual bool AddCheckItem(int command_id, + const CefString& label) =0; + // + // Add a radio item to the menu. Only a single item with the specified + // |group_id| can be checked at a time. Returns true on success. + /// + /*--cef()--*/ + virtual bool AddRadioItem(int command_id, + const CefString& label, + int group_id) =0; + + // + // Add a sub-menu to the menu. The new sub-menu is returned. + /// + /*--cef()--*/ + virtual CefRefPtr AddSubMenu(int command_id, + const CefString& label) =0; + + // + // Insert a separator in the menu at the specified |index|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool InsertSeparatorAt(int index) =0; + + // + // Insert an item in the menu at the specified |index|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool InsertItemAt(int index, + int command_id, + const CefString& label) =0; + + // + // Insert a check item in the menu at the specified |index|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool InsertCheckItemAt(int index, + int command_id, + const CefString& label) =0; + + // + // Insert a radio item in the menu at the specified |index|. Only a single + // item with the specified |group_id| can be checked at a time. Returns true + // on success. + /// + /*--cef()--*/ + virtual bool InsertRadioItemAt(int index, + int command_id, + const CefString& label, + int group_id) =0; + + // + // Insert a sub-menu in the menu at the specified |index|. The new sub-menu + // is returned. + /// + /*--cef()--*/ + virtual CefRefPtr InsertSubMenuAt(int index, + int command_id, + const CefString& label) =0; + + /// + // Removes the item with the specified |command_id|. Returns true on success. + /// + /*--cef()--*/ + virtual bool Remove(int command_id) =0; + + /// + // Removes the item at the specified |index|. Returns true on success. + /// + /*--cef()--*/ + virtual bool RemoveAt(int index) =0; + + /// + // Returns the index associated with the specified |command_id| or -1 if not + // found due to the command id not existing in the menu. + /// + /*--cef()--*/ + virtual int GetIndexOf(int command_id) =0; + + /// + // Returns the command id at the specified |index| or -1 if not found due to + // invalid range or the index being a separator. + /// + /*--cef()--*/ + virtual int GetCommandIdAt(int index) =0; + + /// + // Sets the command id at the specified |index|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetCommandIdAt(int index, int command_id) =0; + + /// + // Returns the label for the specified |command_id| or empty if not found. + /// + /*--cef()--*/ + virtual CefString GetLabel(int command_id) =0; + + /// + // Returns the label at the specified |index| or empty if not found due to + // invalid range or the index being a separator. + /// + /*--cef()--*/ + virtual CefString GetLabelAt(int index) =0; + + /// + // Sets the label for the specified |command_id|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetLabel(int command_id, const CefString& label) =0; + + /// + // Set the label at the specified |index|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetLabelAt(int index, const CefString& label) =0; + + /// + // Returns the item type for the specified |command_id|. + /// + /*--cef(default_retval=MENUITEMTYPE_NONE)--*/ + virtual MenuItemType GetType(int command_id) =0; + + /// + // Returns the item type at the specified |index|. + /// + /*--cef(default_retval=MENUITEMTYPE_NONE)--*/ + virtual MenuItemType GetTypeAt(int index) =0; + + /// + // Returns the group id for the specified |command_id| or -1 if invalid. + /// + /*--cef()--*/ + virtual int GetGroupId(int command_id) =0; + + /// + // Returns the group id at the specified |index| or -1 if invalid. + /// + /*--cef()--*/ + virtual int GetGroupIdAt(int index) =0; + + /// + // Sets the group id for the specified |command_id|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetGroupId(int command_id, int group_id) =0; + + /// + // Sets the group id at the specified |index|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetGroupIdAt(int index, int group_id) =0; + + /// + // Returns the submenu for the specified |command_id| or empty if invalid. + /// + /*--cef()--*/ + virtual CefRefPtr GetSubMenu(int command_id) =0; + + /// + // Returns the submenu at the specified |index| or empty if invalid. + /// + /*--cef()--*/ + virtual CefRefPtr GetSubMenuAt(int index) =0; + + // + // Returns true if the specified |command_id| is visible. + /// + /*--cef()--*/ + virtual bool IsVisible(int command_id) =0; + + // + // Returns true if the specified |index| is visible. + /// + /*--cef()--*/ + virtual bool IsVisibleAt(int index) =0; + + // + // Change the visibility of the specified |command_id|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool SetVisible(int command_id, bool visible) =0; + + // + // Change the visibility at the specified |index|. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetVisibleAt(int index, bool visible) =0; + + // + // Returns true if the specified |command_id| is enabled. + /// + /*--cef()--*/ + virtual bool IsEnabled(int command_id) =0; + + // + // Returns true if the specified |index| is enabled. + /// + /*--cef()--*/ + virtual bool IsEnabledAt(int index) =0; + + // + // Change the enabled status of the specified |command_id|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool SetEnabled(int command_id, bool enabled) =0; + + // + // Change the enabled status at the specified |index|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool SetEnabledAt(int index, bool enabled) =0; + + // + // Returns true if the specified |command_id| is checked. Only applies to + // check and radio items. + /// + /*--cef()--*/ + virtual bool IsChecked(int command_id) =0; + + // + // Returns true if the specified |index| is checked. Only applies to check + // and radio items. + /// + /*--cef()--*/ + virtual bool IsCheckedAt(int index) =0; + + // + // Check the specified |command_id|. Only applies to check and radio items. + // Returns true on success. + /// + /*--cef()--*/ + virtual bool SetChecked(int command_id, bool checked) =0; + + // + // Check the specified |index|. Only applies to check and radio items. Returns + // true on success. + /// + /*--cef()--*/ + virtual bool SetCheckedAt(int index, bool checked) =0; + + // + // Returns true if the specified |command_id| has a keyboard accelerator + // assigned. + /// + /*--cef()--*/ + virtual bool HasAccelerator(int command_id) =0; + + // + // Returns true if the specified |index| has a keyboard accelerator assigned. + /// + /*--cef()--*/ + virtual bool HasAcceleratorAt(int index) =0; + + // + // Set the keyboard accelerator for the specified |command_id|. |key_code| can + // be any virtual key or character value. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetAccelerator(int command_id, + int key_code, + bool shift_pressed, + bool ctrl_pressed, + bool alt_pressed) =0; + + // + // Set the keyboard accelerator at the specified |index|. |key_code| can be + // any virtual key or character value. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetAcceleratorAt(int index, + int key_code, + bool shift_pressed, + bool ctrl_pressed, + bool alt_pressed) =0; + + // + // Remove the keyboard accelerator for the specified |command_id|. Returns + // true on success. + /// + /*--cef()--*/ + virtual bool RemoveAccelerator(int command_id) =0; + + // + // Remove the keyboard accelerator at the specified |index|. Returns true on + // success. + /// + /*--cef()--*/ + virtual bool RemoveAcceleratorAt(int index) =0; + + // + // Retrieves the keyboard accelerator for the specified |command_id|. Returns + // true on success. + /// + /*--cef()--*/ + virtual bool GetAccelerator(int command_id, + int& key_code, + bool& shift_pressed, + bool& ctrl_pressed, + bool& alt_pressed) =0; + + // + // Retrieves the keyboard accelerator for the specified |index|. Returns true + // on success. + /// + /*--cef()--*/ + virtual bool GetAcceleratorAt(int index, + int& key_code, + bool& shift_pressed, + bool& ctrl_pressed, + bool& alt_pressed) =0; +}; + +#endif // CEF_INCLUDE_CEF_MENU_MODEL_H_ diff --git a/include/cef_origin_whitelist.h b/include/cef_origin_whitelist.h new file mode 100644 index 000000000..7fed3453a --- /dev/null +++ b/include/cef_origin_whitelist.h @@ -0,0 +1,103 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ +#define CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ +#pragma once + +#include "include/cef_base.h" + + +/// +// Add an entry to the cross-origin access whitelist. +// +// The same-origin policy restricts how scripts hosted from different origins +// (scheme + domain + port) can communicate. By default, scripts can only access +// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes +// (but no other schemes) can use the "Access-Control-Allow-Origin" header to +// allow cross-origin requests. For example, https://source.example.com can make +// XMLHttpRequest requests on http://target.example.com if the +// http://target.example.com request returns an "Access-Control-Allow-Origin: +// https://source.example.com" response header. +// +// Scripts in separate frames or iframes and hosted from the same protocol and +// domain suffix can execute cross-origin JavaScript if both pages set the +// document.domain value to the same domain suffix. For example, +// scheme://foo.example.com and scheme://bar.example.com can communicate using +// JavaScript if both domains set document.domain="example.com". +// +// This method is used to allow access to origins that would otherwise violate +// the same-origin policy. Scripts hosted underneath the fully qualified +// |source_origin| URL (like http://www.example.com) will be allowed access to +// all resources hosted on the specified |target_protocol| and |target_domain|. +// If |target_domain| is non-empty and |allow_target_subdomains| if false only +// exact domain matches will be allowed. If |target_domain| contains a top- +// level domain component (like "example.com") and |allow_target_subdomains| is +// true sub-domain matches will be allowed. If |target_domain| is empty and +// |allow_target_subdomains| if true all domains and IP addresses will be +// allowed. +// +// This method cannot be used to bypass the restrictions on local or display +// isolated schemes. See the comments on CefRegisterCustomScheme for more +// information. +// +// This function may be called on any thread. Returns false if |source_origin| +// is invalid or the whitelist cannot be accessed. +/// +/*--cef(optional_param=target_domain)--*/ +bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin, + const CefString& target_protocol, + const CefString& target_domain, + bool allow_target_subdomains); + +/// +// Remove an entry from the cross-origin access whitelist. Returns false if +// |source_origin| is invalid or the whitelist cannot be accessed. +/// +/*--cef(optional_param=target_domain)--*/ +bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin, + const CefString& target_protocol, + const CefString& target_domain, + bool allow_target_subdomains); + +/// +// Remove all entries from the cross-origin access whitelist. Returns false if +// the whitelist cannot be accessed. +/// +/*--cef()--*/ +bool CefClearCrossOriginWhitelist(); + +#endif // CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ diff --git a/include/cef_path_util.h b/include/cef_path_util.h new file mode 100644 index 000000000..552f4ba59 --- /dev/null +++ b/include/cef_path_util.h @@ -0,0 +1,52 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_PATH_UTIL_H_ +#define CEF_INCLUDE_CEF_PATH_UTIL_H_ +#pragma once + +#include "include/cef_base.h" + +typedef cef_path_key_t PathKey; + +/// +// Retrieve the path associated with the specified |key|. Returns true on +// success. Can be called on any thread in the browser process. +/// +/*--cef()--*/ +bool CefGetPath(PathKey key, CefString& path); + +#endif // CEF_INCLUDE_CEF_PATH_UTIL_H_ diff --git a/include/cef_print_handler.h b/include/cef_print_handler.h new file mode 100644 index 000000000..a157cbbd6 --- /dev/null +++ b/include/cef_print_handler.h @@ -0,0 +1,120 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_PRINT_HANDLER_H_ +#define CEF_INCLUDE_CEF_PRINT_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_print_settings.h" + +/// +// Callback interface for asynchronous continuation of print dialog requests. +/// +/*--cef(source=library)--*/ +class CefPrintDialogCallback : public virtual CefBase { + public: + /// + // Continue printing with the specified |settings|. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(CefRefPtr settings) =0; + + /// + // Cancel the printing. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + +/// +// Callback interface for asynchronous continuation of print job requests. +/// +/*--cef(source=library)--*/ +class CefPrintJobCallback : public virtual CefBase { + public: + /// + // Indicate completion of the print job. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue() =0; +}; + + +/// +// Implement this interface to handle printing on Linux. The methods of this +// class will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefPrintHandler : public virtual CefBase { + public: + /// + // Synchronize |settings| with client state. If |get_defaults| is true then + // populate |settings| with the default print settings. Do not keep a + // reference to |settings| outside of this callback. + /// + /*--cef()--*/ + virtual void OnPrintSettings(CefRefPtr settings, + bool get_defaults) =0; + + /// + // Show the print dialog. Execute |callback| once the dialog is dismissed. + // Return true if the dialog will be displayed or false to cancel the + // printing immediately. + /// + /*--cef()--*/ + virtual bool OnPrintDialog(bool has_selection, + CefRefPtr callback) =0; + + /// + // Send the print job to the printer. Execute |callback| once the job is + // completed. Return true if the job will proceed or false to cancel the job + // immediately. + /// + /*--cef()--*/ + virtual bool OnPrintJob(const CefString& document_name, + const CefString& pdf_file_path, + CefRefPtr callback) =0; + + /// + // Reset client state related to printing. + /// + /*--cef()--*/ + virtual void OnPrintReset() =0; +}; + +#endif // CEF_INCLUDE_CEF_PRINT_HANDLER_H_ diff --git a/include/cef_print_settings.h b/include/cef_print_settings.h new file mode 100644 index 000000000..af3fff4f5 --- /dev/null +++ b/include/cef_print_settings.h @@ -0,0 +1,208 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_PRINT_SETTINGS_H_ +#define CEF_INCLUDE_CEF_PRINT_SETTINGS_H_ +#pragma once + +#include + +#include "include/cef_base.h" + +/// +// Class representing print settings. +/// +/*--cef(source=library)--*/ +class CefPrintSettings : public virtual CefBase { + public: + typedef cef_color_model_t ColorModel; + typedef cef_duplex_mode_t DuplexMode; + typedef std::vector PageRangeList; + + /// + // Create a new CefPrintSettings object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // function returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns a writable copy of this object. + /// + /*--cef()--*/ + virtual CefRefPtr Copy() =0; + + /// + // Set the page orientation. + /// + /*--cef()--*/ + virtual void SetOrientation(bool landscape) =0; + + /// + // Returns true if the orientation is landscape. + /// + /*--cef()--*/ + virtual bool IsLandscape() =0; + + /// + // Set the printer printable area in device units. + // Some platforms already provide flipped area. Set |landscape_needs_flip| + // to false on those platforms to avoid double flipping. + /// + /*--cef()--*/ + virtual void SetPrinterPrintableArea( + const CefSize& physical_size_device_units, + const CefRect& printable_area_device_units, + bool landscape_needs_flip) =0; + + /// + // Set the device name. + /// + /*--cef(optional_param=name)--*/ + virtual void SetDeviceName(const CefString& name) =0; + + /// + // Get the device name. + /// + /*--cef()--*/ + virtual CefString GetDeviceName() =0; + + /// + // Set the DPI (dots per inch). + /// + /*--cef()--*/ + virtual void SetDPI(int dpi) =0; + + /// + // Get the DPI (dots per inch). + /// + /*--cef()--*/ + virtual int GetDPI() =0; + + /// + // Set the page ranges. + /// + /*--cef()--*/ + virtual void SetPageRanges(const PageRangeList& ranges) =0; + + /// + // Returns the number of page ranges that currently exist. + /// + /*--cef()--*/ + virtual size_t GetPageRangesCount() =0; + + /// + // Retrieve the page ranges. + /// + /*--cef(count_func=ranges:GetPageRangesCount)--*/ + virtual void GetPageRanges(PageRangeList& ranges) =0; + + /// + // Set whether only the selection will be printed. + /// + /*--cef()--*/ + virtual void SetSelectionOnly(bool selection_only) =0; + + /// + // Returns true if only the selection will be printed. + /// + /*--cef()--*/ + virtual bool IsSelectionOnly() =0; + + /// + // Set whether pages will be collated. + /// + /*--cef()--*/ + virtual void SetCollate(bool collate) =0; + + /// + // Returns true if pages will be collated. + /// + /*--cef()--*/ + virtual bool WillCollate() =0; + + /// + // Set the color model. + /// + /*--cef()--*/ + virtual void SetColorModel(ColorModel model) =0; + + /// + // Get the color model. + /// + /*--cef(default_retval=COLOR_MODEL_UNKNOWN)--*/ + virtual ColorModel GetColorModel() =0; + + /// + // Set the number of copies. + /// + /*--cef()--*/ + virtual void SetCopies(int copies) =0; + + /// + // Get the number of copies. + /// + /*--cef()--*/ + virtual int GetCopies() =0; + + /// + // Set the duplex mode. + /// + /*--cef()--*/ + virtual void SetDuplexMode(DuplexMode mode) =0; + + /// + // Get the duplex mode. + /// + /*--cef(default_retval=DUPLEX_MODE_UNKNOWN)--*/ + virtual DuplexMode GetDuplexMode() =0; +}; + +#endif // CEF_INCLUDE_CEF_PRINT_SETTINGS_H_ + diff --git a/include/cef_process_message.h b/include/cef_process_message.h new file mode 100644 index 000000000..1e27bd681 --- /dev/null +++ b/include/cef_process_message.h @@ -0,0 +1,91 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_MESSAGE_H_ +#define CEF_INCLUDE_CEF_MESSAGE_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_values.h" + +typedef cef_process_id_t CefProcessId; + +/// +// Class representing a message. Can be used on any process and thread. +/// +/*--cef(source=library)--*/ +class CefProcessMessage : public virtual CefBase { + public: + /// + // Create a new CefProcessMessage object with the specified name. + /// + /*--cef()--*/ + static CefRefPtr Create(const CefString& name); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // function returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns a writable copy of this object. + /// + /*--cef()--*/ + virtual CefRefPtr Copy() =0; + + /// + // Returns the message name. + /// + /*--cef()--*/ + virtual CefString GetName() =0; + + /// + // Returns the list of arguments. + /// + /*--cef()--*/ + virtual CefRefPtr GetArgumentList() =0; +}; + +#endif // CEF_INCLUDE_CEF_MESSAGE_H_ diff --git a/include/cef_process_util.h b/include/cef_process_util.h new file mode 100644 index 000000000..4fce778e7 --- /dev/null +++ b/include/cef_process_util.h @@ -0,0 +1,57 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_PROCESS_UTIL_H_ +#define CEF_INCLUDE_CEF_PROCESS_UTIL_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_command_line.h" + +/// +// Launches the process specified via |command_line|. Returns true upon +// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread. +// +// Unix-specific notes: +// - All file descriptors open in the parent process will be closed in the +// child process except for stdin, stdout, and stderr. +// - If the first argument on the command line does not contain a slash, +// PATH will be searched. (See man execvp.) +/// +/*--cef()--*/ +bool CefLaunchProcess(CefRefPtr command_line); + +#endif // CEF_INCLUDE_CEF_PROCESS_UTIL_H_ diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h new file mode 100644 index 000000000..aa4157f8d --- /dev/null +++ b/include/cef_render_handler.h @@ -0,0 +1,170 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_RENDER_HANDLER_H_ +#define CEF_INCLUDE_CEF_RENDER_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_drag_data.h" +#include + +/// +// Implement this interface to handle events when window rendering is disabled. +// The methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefRenderHandler : public virtual CefBase { + public: + typedef cef_drag_operations_mask_t DragOperation; + typedef cef_drag_operations_mask_t DragOperationsMask; + typedef cef_paint_element_type_t PaintElementType; + typedef std::vector RectList; + + /// + // Called to retrieve the root window rectangle in screen coordinates. Return + // true if the rectangle was provided. + /// + /*--cef()--*/ + virtual bool GetRootScreenRect(CefRefPtr browser, + CefRect& rect) { return false; } + + /// + // Called to retrieve the view rectangle which is relative to screen + // coordinates. Return true if the rectangle was provided. + /// + /*--cef()--*/ + virtual bool GetViewRect(CefRefPtr browser, CefRect& rect) =0; + + /// + // Called to retrieve the translation from view coordinates to actual screen + // coordinates. Return true if the screen coordinates were provided. + /// + /*--cef()--*/ + virtual bool GetScreenPoint(CefRefPtr browser, + int viewX, + int viewY, + int& screenX, + int& screenY) { return false; } + + /// + // Called to allow the client to fill in the CefScreenInfo object with + // appropriate values. Return true if the |screen_info| structure has been + // modified. + // + // If the screen info rectangle is left empty the rectangle from GetViewRect + // will be used. If the rectangle is still empty or invalid popups may not be + // drawn correctly. + /// + /*--cef()--*/ + virtual bool GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) { return false; } + + /// + // Called when the browser wants to show or hide the popup widget. The popup + // should be shown if |show| is true and hidden if |show| is false. + /// + /*--cef()--*/ + virtual void OnPopupShow(CefRefPtr browser, + bool show) {} + + /// + // Called when the browser wants to move or resize the popup widget. |rect| + // contains the new location and size. + /// + /*--cef()--*/ + virtual void OnPopupSize(CefRefPtr browser, + const CefRect& rect) {} + + /// + // Called when an element should be painted. |type| indicates whether the + // element is the view or the popup widget. |buffer| contains the pixel data + // for the whole image. |dirtyRects| contains the set of rectangles that need + // to be repainted. On Windows |buffer| will be |width|*|height|*4 bytes + // in size and represents a BGRA image with an upper-left origin. + /// + /*--cef()--*/ + virtual void OnPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const void* buffer, + int width, int height) =0; + + /// + // Called when the browser window's cursor has changed. + /// + /*--cef()--*/ + virtual void OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor) {} + + /// + // Called when the user starts dragging content in the web view. Contextual + // information about the dragged content is supplied by |drag_data|. + // OS APIs that run a system message loop may be used within the + // StartDragging call. + // + // Return false to abort the drag operation. Don't call any of + // CefBrowserHost::DragSource*Ended* methods after returning false. + // + // Return true to handle the drag operation. Call + // CefBrowserHost::DragSourceEndedAt and DragSourceSystemDragEnded either + // synchronously or asynchronously to inform the web view that the drag + // operation has ended. + /// + /*--cef()--*/ + virtual bool StartDragging(CefRefPtr browser, + CefRefPtr drag_data, + DragOperationsMask allowed_ops, + int x, int y) { return false; } + + /// + // Called when the web view wants to update the mouse cursor during a + // drag & drop operation. |operation| describes the allowed operation + // (none, move, copy, link). + /// + /*--cef()--*/ + virtual void UpdateDragCursor(CefRefPtr browser, + DragOperation operation) {} + + /// + // Called when the scroll offset has changed. + /// + /*--cef()--*/ + virtual void OnScrollOffsetChanged(CefRefPtr browser) {} +}; + +#endif // CEF_INCLUDE_CEF_RENDER_HANDLER_H_ diff --git a/include/cef_render_process_handler.h b/include/cef_render_process_handler.h new file mode 100644 index 000000000..98ab391bc --- /dev/null +++ b/include/cef_render_process_handler.h @@ -0,0 +1,168 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_RENDER_PROCESS_HANDLER_H_ +#define CEF_INCLUDE_CEF_RENDER_PROCESS_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_dom.h" +#include "include/cef_frame.h" +#include "include/cef_load_handler.h" +#include "include/cef_process_message.h" +#include "include/cef_v8.h" +#include "include/cef_values.h" + +/// +// Class used to implement render process callbacks. The methods of this class +// will be called on the render process main thread (TID_RENDERER) unless +// otherwise indicated. +/// +/*--cef(source=client)--*/ +class CefRenderProcessHandler : public virtual CefBase { + public: + typedef cef_navigation_type_t NavigationType; + + /// + // Called after the render process main thread has been created. |extra_info| + // is a read-only value originating from + // CefBrowserProcessHandler::OnRenderProcessThreadCreated(). Do not keep a + // reference to |extra_info| outside of this method. + /// + /*--cef()--*/ + virtual void OnRenderThreadCreated(CefRefPtr extra_info) {} + + /// + // Called after WebKit has been initialized. + /// + /*--cef()--*/ + virtual void OnWebKitInitialized() {} + + /// + // Called after a browser has been created. When browsing cross-origin a new + // browser will be created before the old browser with the same identifier is + // destroyed. + /// + /*--cef()--*/ + virtual void OnBrowserCreated(CefRefPtr browser) {} + + /// + // Called before a browser is destroyed. + /// + /*--cef()--*/ + virtual void OnBrowserDestroyed(CefRefPtr browser) {} + + /// + // Return the handler for browser load status events. + /// + /*--cef()--*/ + virtual CefRefPtr GetLoadHandler() { + return NULL; + } + + /// + // Called before browser navigation. Return true to cancel the navigation or + // false to allow the navigation to proceed. The |request| object cannot be + // modified in this callback. + /// + /*--cef()--*/ + virtual bool OnBeforeNavigation(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + NavigationType navigation_type, + bool is_redirect) { return false; } + + /// + // Called immediately after the V8 context for a frame has been created. To + // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal() + // method. V8 handles can only be accessed from the thread on which they are + // created. A task runner for posting tasks on the associated thread can be + // retrieved via the CefV8Context::GetTaskRunner() method. + /// + /*--cef()--*/ + virtual void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) {} + + /// + // Called immediately before the V8 context for a frame is released. No + // references to the context should be kept after this method is called. + /// + /*--cef()--*/ + virtual void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) {} + + /// + // Called for global uncaught exceptions in a frame. Execution of this + // callback is disabled by default. To enable set + // CefSettings.uncaught_exception_stack_size > 0. + /// + /*--cef()--*/ + virtual void OnUncaughtException(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context, + CefRefPtr exception, + CefRefPtr stackTrace) {} + + /// + // Called when a new node in the the browser gets focus. The |node| value may + // be empty if no specific node has gained focus. The node object passed to + // this method represents a snapshot of the DOM at the time this method is + // executed. DOM objects are only valid for the scope of this method. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this method. + /// + /*--cef(optional_param=frame,optional_param=node)--*/ + virtual void OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr node) {} + + /// + // Called when a new message is received from a different process. Return true + // if the message was handled or false otherwise. Do not keep a reference to + // or attempt to access the message outside of this callback. + /// + /*--cef()--*/ + virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) { + return false; + } +}; + +#endif // CEF_INCLUDE_CEF_RENDER_PROCESS_HANDLER_H_ diff --git a/include/cef_request.h b/include/cef_request.h new file mode 100644 index 000000000..da9ec4304 --- /dev/null +++ b/include/cef_request.h @@ -0,0 +1,297 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_REQUEST_H_ +#define CEF_INCLUDE_CEF_REQUEST_H_ +#pragma once + +#include "include/cef_base.h" +#include +#include + +class CefPostData; +class CefPostDataElement; + +/// +// Class used to represent a web request. The methods of this class may be +// called on any thread. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefRequest : public virtual CefBase { + public: + typedef std::multimap HeaderMap; + typedef cef_resource_type_t ResourceType; + typedef cef_transition_type_t TransitionType; + + /// + // Create a new CefRequest object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is read-only. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Get the fully qualified URL. + /// + /*--cef()--*/ + virtual CefString GetURL() =0; + + /// + // Set the fully qualified URL. + /// + /*--cef()--*/ + virtual void SetURL(const CefString& url) =0; + + /// + // Get the request method type. The value will default to POST if post data + // is provided and GET otherwise. + /// + /*--cef()--*/ + virtual CefString GetMethod() =0; + + /// + // Set the request method type. + /// + /*--cef()--*/ + virtual void SetMethod(const CefString& method) =0; + + /// + // Get the post data. + /// + /*--cef()--*/ + virtual CefRefPtr GetPostData() =0; + + /// + // Set the post data. + /// + /*--cef()--*/ + virtual void SetPostData(CefRefPtr postData) =0; + + /// + // Get the header values. + /// + /*--cef()--*/ + virtual void GetHeaderMap(HeaderMap& headerMap) =0; + + /// + // Set the header values. + /// + /*--cef()--*/ + virtual void SetHeaderMap(const HeaderMap& headerMap) =0; + + /// + // Set all values at one time. + /// + /*--cef(optional_param=postData)--*/ + virtual void Set(const CefString& url, + const CefString& method, + CefRefPtr postData, + const HeaderMap& headerMap) =0; + + /// + // Get the flags used in combination with CefURLRequest. See + // cef_urlrequest_flags_t for supported values. + /// + /*--cef(default_retval=UR_FLAG_NONE)--*/ + virtual int GetFlags() =0; + + /// + // Set the flags used in combination with CefURLRequest. See + // cef_urlrequest_flags_t for supported values. + /// + /*--cef()--*/ + virtual void SetFlags(int flags) =0; + + /// + // Set the URL to the first party for cookies used in combination with + // CefURLRequest. + /// + /*--cef()--*/ + virtual CefString GetFirstPartyForCookies() =0; + + /// + // Get the URL to the first party for cookies used in combination with + // CefURLRequest. + /// + /*--cef()--*/ + virtual void SetFirstPartyForCookies(const CefString& url) =0; + + /// + // Get the resource type for this request. Accurate resource type information + // may only be available in the browser process. + /// + /*--cef(default_retval=RT_SUB_RESOURCE)--*/ + virtual ResourceType GetResourceType() =0; + + /// + // Get the transition type for this request. Only available in the browser + // process and only applies to requests that represent a main frame or + // sub-frame navigation. + /// + /*--cef(default_retval=TT_EXPLICIT)--*/ + virtual TransitionType GetTransitionType() =0; +}; + + +/// +// Class used to represent post data for a web request. The methods of this +// class may be called on any thread. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefPostData : public virtual CefBase { + public: + typedef std::vector > ElementVector; + + /// + // Create a new CefPostData object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is read-only. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns the number of existing post data elements. + /// + /*--cef()--*/ + virtual size_t GetElementCount() =0; + + /// + // Retrieve the post data elements. + /// + /*--cef(count_func=elements:GetElementCount)--*/ + virtual void GetElements(ElementVector& elements) =0; + + /// + // Remove the specified post data element. Returns true if the removal + // succeeds. + /// + /*--cef()--*/ + virtual bool RemoveElement(CefRefPtr element) =0; + + /// + // Add the specified post data element. Returns true if the add succeeds. + /// + /*--cef()--*/ + virtual bool AddElement(CefRefPtr element) =0; + + /// + // Remove all existing post data elements. + /// + /*--cef()--*/ + virtual void RemoveElements() =0; +}; + + +/// +// Class used to represent a single element in the request post data. The +// methods of this class may be called on any thread. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefPostDataElement : public virtual CefBase { + public: + /// + // Post data elements may represent either bytes or files. + /// + typedef cef_postdataelement_type_t Type; + + /// + // Create a new CefPostDataElement object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is read-only. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Remove all contents from the post data element. + /// + /*--cef()--*/ + virtual void SetToEmpty() =0; + + /// + // The post data element will represent a file. + /// + /*--cef()--*/ + virtual void SetToFile(const CefString& fileName) =0; + + /// + // The post data element will represent bytes. The bytes passed + // in will be copied. + /// + /*--cef()--*/ + virtual void SetToBytes(size_t size, const void* bytes) =0; + + /// + // Return the type of this post data element. + /// + /*--cef(default_retval=PDE_TYPE_EMPTY)--*/ + virtual Type GetType() =0; + + /// + // Return the file name. + /// + /*--cef()--*/ + virtual CefString GetFile() =0; + + /// + // Return the number of bytes. + /// + /*--cef()--*/ + virtual size_t GetBytesCount() =0; + + /// + // Read up to |size| bytes into |bytes| and return the number of bytes + // actually read. + /// + /*--cef()--*/ + virtual size_t GetBytes(size_t size, void* bytes) =0; +}; + +#endif // CEF_INCLUDE_CEF_REQUEST_H_ diff --git a/include/cef_request_context.h b/include/cef_request_context.h new file mode 100644 index 000000000..32495a952 --- /dev/null +++ b/include/cef_request_context.h @@ -0,0 +1,94 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ +#define CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ +#pragma once + +#include "include/cef_request_context_handler.h" + +/// +// A request context provides request handling for a set of related browser +// objects. A request context is specified when creating a new browser object +// via the CefBrowserHost static factory methods. Browser objects with different +// request contexts will never be hosted in the same render process. Browser +// objects with the same request context may or may not be hosted in the same +// render process depending on the process model. Browser objects created +// indirectly via the JavaScript window.open function or targeted links will +// share the same render process and the same request context as the source +// browser. When running in single-process mode there is only a single render +// process (the main process) and so all browsers created in single-process mode +// will share the same request context. This will be the first request context +// passed into a CefBrowserHost static factory method and all other request +// context objects will be ignored. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefRequestContext : public virtual CefBase { + public: + /// + // Returns the global context object. + /// + /*--cef()--*/ + static CefRefPtr GetGlobalContext(); + + /// + // Creates a new context object with the specified handler. + /// + /*--cef(optional_param=handler)--*/ + static CefRefPtr CreateContext( + CefRefPtr handler); + + /// + // Returns true if this object is pointing to the same context as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr other) =0; + + /// + // Returns true if this object is the global context. + /// + /*--cef()--*/ + virtual bool IsGlobal() =0; + + /// + // Returns the handler for this context if any. + /// + /*--cef()--*/ + virtual CefRefPtr GetHandler() =0; +}; + +#endif // CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ diff --git a/include/cef_request_context_handler.h b/include/cef_request_context_handler.h new file mode 100644 index 000000000..f77259efe --- /dev/null +++ b/include/cef_request_context_handler.h @@ -0,0 +1,58 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_REQUEST_CONTEXT_HANDLER_H_ +#define CEF_INCLUDE_CEF_REQUEST_CONTEXT_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_cookie.h" + +/// +// Implement this interface to provide handler implementations. +/// +/*--cef(source=client,no_debugct_check)--*/ +class CefRequestContextHandler : public virtual CefBase { + public: + /// + // Called on the IO thread to retrieve the cookie manager. The global cookie + // manager will be used if this method returns NULL. + /// + /*--cef()--*/ + virtual CefRefPtr GetCookieManager() { return NULL; } +}; + +#endif // CEF_INCLUDE_CEF_REQUEST_CONTEXT_HANDLER_H_ diff --git a/include/cef_request_handler.h b/include/cef_request_handler.h new file mode 100644 index 000000000..0f434310b --- /dev/null +++ b/include/cef_request_handler.h @@ -0,0 +1,245 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ +#define CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ +#pragma once + +#include "include/cef_auth_callback.h" +#include "include/cef_base.h" +#include "include/cef_browser.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_web_plugin.h" + +/// +// Callback interface used for asynchronous continuation of quota requests. +/// +/*--cef(source=library)--*/ +class CefQuotaCallback : public virtual CefBase { + public: + /// + // Continue the quota request. If |allow| is true the request will be + // allowed. Otherwise, the request will be denied. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(bool allow) =0; + + /// + // Cancel the quota request. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + + +/// +// Callback interface used for asynchronous continuation of url requests when +// invalid SSL certificates are encountered. +/// +/*--cef(source=library)--*/ +class CefAllowCertificateErrorCallback : public virtual CefBase { + public: + /// + // Continue the url request. If |allow| is true the request will be + // continued. Otherwise, the request will be canceled. + /// + /*--cef(capi_name=cont)--*/ + virtual void Continue(bool allow) =0; +}; + + +/// +// Implement this interface to handle events related to browser requests. The +// methods of this class will be called on the thread indicated. +/// +/*--cef(source=client)--*/ +class CefRequestHandler : public virtual CefBase { + public: + typedef cef_termination_status_t TerminationStatus; + + /// + // Called on the UI thread before browser navigation. Return true to cancel + // the navigation or false to allow the navigation to proceed. The |request| + // object cannot be modified in this callback. + // CefLoadHandler::OnLoadingStateChange will be called twice in all cases. + // If the navigation is allowed CefLoadHandler::OnLoadStart and + // CefLoadHandler::OnLoadEnd will be called. If the navigation is canceled + // CefLoadHandler::OnLoadError will be called with an |errorCode| value of + // ERR_ABORTED. + /// + /*--cef()--*/ + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) { + return false; + } + + /// + // Called on the IO thread before a resource request is loaded. The |request| + // object may be modified. To cancel the request return true otherwise return + // false. + /// + /*--cef()--*/ + virtual bool OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) { + return false; + } + + /// + // Called on the IO thread before a resource is loaded. To allow the resource + // to load normally return NULL. To specify a handler for the resource return + // a CefResourceHandler object. The |request| object should not be modified in + // this callback. + /// + /*--cef()--*/ + virtual CefRefPtr GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) { + return NULL; + } + + /// + // Called on the IO thread when a resource load is redirected. The |old_url| + // parameter will contain the old URL. The |new_url| parameter will contain + // the new URL and can be changed if desired. + /// + /*--cef()--*/ + virtual void OnResourceRedirect(CefRefPtr browser, + CefRefPtr frame, + const CefString& old_url, + CefString& new_url) {} + + /// + // Called on the IO thread when the browser needs credentials from the user. + // |isProxy| indicates whether the host is a proxy server. |host| contains the + // hostname and |port| contains the port number. Return true to continue the + // request and call CefAuthCallback::Continue() when the authentication + // information is available. Return false to cancel the request. + /// + /*--cef(optional_param=realm)--*/ + virtual bool GetAuthCredentials(CefRefPtr browser, + CefRefPtr frame, + bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + CefRefPtr callback) { + return false; + } + + /// + // Called on the IO thread when JavaScript requests a specific storage quota + // size via the webkitStorageInfo.requestQuota function. |origin_url| is the + // origin of the page making the request. |new_size| is the requested quota + // size in bytes. Return true and call CefQuotaCallback::Continue() either in + // this method or at a later time to grant or deny the request. Return false + // to cancel the request. + /// + /*--cef()--*/ + virtual bool OnQuotaRequest(CefRefPtr browser, + const CefString& origin_url, + int64 new_size, + CefRefPtr callback) { + return false; + } + + /// + // Called on the UI thread to handle requests for URLs with an unknown + // protocol component. Set |allow_os_execution| to true to attempt execution + // via the registered OS protocol handler, if any. + // SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED + // ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION. + /// + /*--cef()--*/ + virtual void OnProtocolExecution(CefRefPtr browser, + const CefString& url, + bool& allow_os_execution) {} + + /// + // Called on the UI thread to handle requests for URLs with an invalid + // SSL certificate. Return true and call CefAllowCertificateErrorCallback:: + // Continue() either in this method or at a later time to continue or cancel + // the request. Return false to cancel the request immediately. If |callback| + // is empty the error cannot be recovered from and the request will be + // canceled automatically. If CefSettings.ignore_certificate_errors is set + // all invalid certificates will be accepted without calling this method. + /// + /*--cef()--*/ + virtual bool OnCertificateError( + cef_errorcode_t cert_error, + const CefString& request_url, + CefRefPtr callback) { + return false; + } + + /// + // Called on the browser process IO thread before a plugin is loaded. Return + // true to block loading of the plugin. + /// + /*--cef(optional_param=url,optional_param=policy_url)--*/ + virtual bool OnBeforePluginLoad(CefRefPtr browser, + const CefString& url, + const CefString& policy_url, + CefRefPtr info) { + return false; + } + + /// + // Called on the browser process UI thread when a plugin has crashed. + // |plugin_path| is the path of the plugin that crashed. + /// + /*--cef()--*/ + virtual void OnPluginCrashed(CefRefPtr browser, + const CefString& plugin_path) {} + + /// + // Called on the browser process UI thread when the render process + // terminates unexpectedly. |status| indicates how the process + // terminated. + /// + /*--cef()--*/ + virtual void OnRenderProcessTerminated(CefRefPtr browser, + TerminationStatus status) {} +}; + +#endif // CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ diff --git a/include/cef_resource_bundle_handler.h b/include/cef_resource_bundle_handler.h new file mode 100644 index 000000000..2cd39a5eb --- /dev/null +++ b/include/cef_resource_bundle_handler.h @@ -0,0 +1,73 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ +#define CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" + +/// +// Class used to implement a custom resource bundle interface. The methods of +// this class may be called on multiple threads. +/// +/*--cef(source=client)--*/ +class CefResourceBundleHandler : public virtual CefBase { + public: + /// + // Called to retrieve a localized translation for the string specified by + // |message_id|. To provide the translation set |string| to the translation + // string and return true. To use the default translation return false. + // Supported message IDs are listed in cef_pack_strings.h. + /// + /*--cef()--*/ + virtual bool GetLocalizedString(int message_id, + CefString& string) =0; + + /// + // Called to retrieve data for the resource specified by |resource_id|. To + // provide the resource data set |data| and |data_size| to the data pointer + // and size respectively and return true. To use the default resource data + // return false. The resource data will not be copied and must remain resident + // in memory. Supported resource IDs are listed in cef_pack_resources.h. + /// + /*--cef()--*/ + virtual bool GetDataResource(int resource_id, + void*& data, + size_t& data_size) =0; +}; + +#endif // CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ diff --git a/include/cef_resource_handler.h b/include/cef_resource_handler.h new file mode 100644 index 000000000..57c8b7fc0 --- /dev/null +++ b/include/cef_resource_handler.h @@ -0,0 +1,116 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_RESOURCE_HANDLER_H_ +#define CEF_INCLUDE_CEF_RESOURCE_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_callback.h" +#include "include/cef_cookie.h" +#include "include/cef_request.h" +#include "include/cef_response.h" + +/// +// Class used to implement a custom request handler interface. The methods of +// this class will always be called on the IO thread. +/// +/*--cef(source=client)--*/ +class CefResourceHandler : public virtual CefBase { + public: + /// + // Begin processing the request. To handle the request return true and call + // CefCallback::Continue() once the response header information is available + // (CefCallback::Continue() can also be called from inside this method if + // header information is available immediately). To cancel the request return + // false. + /// + /*--cef()--*/ + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) =0; + + /// + // Retrieve response header information. If the response length is not known + // set |response_length| to -1 and ReadResponse() will be called until it + // returns false. If the response length is known set |response_length| + // to a positive value and ReadResponse() will be called until it returns + // false or the specified number of bytes have been read. Use the |response| + // object to set the mime type, http status code and other optional header + // values. To redirect the request to a new URL set |redirectUrl| to the new + // URL. + /// + /*--cef()--*/ + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) =0; + + /// + // Read response data. If data is available immediately copy up to + // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of + // bytes copied, and return true. To read the data at a later time set + // |bytes_read| to 0, return true and call CefCallback::Continue() when the + // data is available. To indicate response completion return false. + /// + /*--cef()--*/ + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) =0; + + /// + // Return true if the specified cookie can be sent with the request or false + // otherwise. If false is returned for any cookie then no cookies will be sent + // with the request. + /// + /*--cef()--*/ + virtual bool CanGetCookie(const CefCookie& cookie) { return true; } + + /// + // Return true if the specified cookie returned with the response can be set + // or false otherwise. + /// + /*--cef()--*/ + virtual bool CanSetCookie(const CefCookie& cookie) { return true; } + + /// + // Request processing has been canceled. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + +#endif // CEF_INCLUDE_CEF_RESOURCE_HANDLER_H_ diff --git a/include/cef_response.h b/include/cef_response.h new file mode 100644 index 000000000..32fbef1b0 --- /dev/null +++ b/include/cef_response.h @@ -0,0 +1,120 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_RESPONSE_H_ +#define CEF_INCLUDE_CEF_RESPONSE_H_ +#pragma once + +#include "include/cef_base.h" +#include + +/// +// Class used to represent a web response. The methods of this class may be +// called on any thread. +/// +/*--cef(source=library,no_debugct_check)--*/ +class CefResponse : public virtual CefBase { + public: + typedef std::multimap HeaderMap; + + /// + // Create a new CefResponse object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is read-only. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Get the response status code. + /// + /*--cef()--*/ + virtual int GetStatus() =0; + + /// + // Set the response status code. + /// + /*--cef()--*/ + virtual void SetStatus(int status) = 0; + + /// + // Get the response status text. + /// + /*--cef()--*/ + virtual CefString GetStatusText() =0; + + /// + // Set the response status text. + /// + /*--cef()--*/ + virtual void SetStatusText(const CefString& statusText) = 0; + + /// + // Get the response mime type. + /// + /*--cef()--*/ + virtual CefString GetMimeType() = 0; + + /// + // Set the response mime type. + /// + /*--cef()--*/ + virtual void SetMimeType(const CefString& mimeType) = 0; + + /// + // Get the value for the specified response header field. + /// + /*--cef()--*/ + virtual CefString GetHeader(const CefString& name) =0; + + /// + // Get all response header fields. + /// + /*--cef()--*/ + virtual void GetHeaderMap(HeaderMap& headerMap) =0; + + /// + // Set all response header fields. + /// + /*--cef()--*/ + virtual void SetHeaderMap(const HeaderMap& headerMap) =0; +}; + +#endif // CEF_INCLUDE_CEF_RESPONSE_H_ diff --git a/include/cef_runnable.h b/include/cef_runnable.h new file mode 100644 index 000000000..32e2df17a --- /dev/null +++ b/include/cef_runnable.h @@ -0,0 +1,342 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-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. +// +// The contents of this file are a modified extract of base/task.h + +#ifndef CEF_INCLUDE_CEF_RUNNABLE_H_ +#define CEF_INCLUDE_CEF_RUNNABLE_H_ +#pragma once + +#include "include/base/cef_tuple.h" +#include "include/cef_base.h" +#include "include/cef_task.h" + +// CefRunnableMethodTraits ----------------------------------------------------- +// +// This traits-class is used by CefRunnableMethod to manage the lifetime of the +// callee object. By default, it is assumed that the callee supports AddRef +// and Release methods. A particular class can specialize this template to +// define other lifetime management. For example, if the callee is known to +// live longer than the CefRunnableMethod object, then a CefRunnableMethodTraits +// struct could be defined with empty RetainCallee and ReleaseCallee methods. +// +// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way +// for declaring a CefRunnableMethodTraits that disables refcounting. + +template +struct CefRunnableMethodTraits { + CefRunnableMethodTraits() { + } + + ~CefRunnableMethodTraits() { + } + + void RetainCallee(T* obj) { +#ifndef NDEBUG + // Catch NewCefRunnableMethod being called in an object's constructor. + // This isn't safe since the method can be invoked before the constructor + // completes, causing the object to be deleted. + obj->AddRef(); + obj->Release(); +#endif + obj->AddRef(); + } + + void ReleaseCallee(T* obj) { + obj->Release(); + } +}; + +// Convenience macro for declaring a CefRunnableMethodTraits that disables +// refcounting of a class. This is useful if you know that the callee +// will outlive the CefRunnableMethod object and thus do not need the ref +// counts. +// +// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the +// global namespace scope. Example: +// +// namespace foo { +// class Bar { +// ... +// }; +// } // namespace foo +// +// DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar); +// +// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the +// class. +#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \ + template <> \ + struct CefRunnableMethodTraits { \ + void RetainCallee(TypeName* manager) {} \ + void ReleaseCallee(TypeName* manager) {} \ + } + +// CefRunnableMethod and CefRunnableFunction ---------------------------------- +// +// CefRunnable methods are a type of task that call a function on an object +// when they are run. We implement both an object and a set of +// NewCefRunnableMethod and NewCefRunnableFunction functions for convenience. +// These functions are overloaded and will infer the template types, +// simplifying calling code. +// +// The template definitions all use the following names: +// T - the class type of the object you're supplying +// this is not needed for the Static version of the call +// Method/Function - the signature of a pointer to the method or function you +// want to call +// Param - the parameter(s) to the method, possibly packed as a Tuple +// A - the first parameter (if any) to the method +// B - the second parameter (if any) to the method +// +// Put these all together and you get an object that can call a method whose +// signature is: +// R T::MyFunction([A[, B]]) +// +// Usage: +// CefPostTask(TID_UI, NewCefRunnableMethod(object, &Object::method[, a[, b]]) +// CefPostTask(TID_UI, NewCefRunnableFunction(&function[, a[, b]]) + +// CefRunnableMethod and NewCefRunnableMethod implementation ------------------ + +template +class CefRunnableMethod : public CefTask { + public: + CefRunnableMethod(T* obj, Method meth, const Params& params) + : obj_(obj), meth_(meth), params_(params) { + traits_.RetainCallee(obj_); + } + + ~CefRunnableMethod() { + T* obj = obj_; + obj_ = NULL; + if (obj) + traits_.ReleaseCallee(obj); + } + + virtual void Execute() { + if (obj_) + DispatchToMethod(obj_, meth_, params_); + } + + private: + T* obj_; + Method meth_; + Params params_; + CefRunnableMethodTraits traits_; + + IMPLEMENT_REFCOUNTING(CefRunnableMethod); +}; + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method) { + return new CefRunnableMethod(object, method, MakeTuple()); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b, + c)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b, + c, + d)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d, + const E& e) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a, b, c, d, + e)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a, b, c, d, + e, f)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f, + const G& g) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a, b, c, + d, e, f, + g)); +} + +// CefRunnableFunction and NewCefRunnableFunction implementation -------------- + +template +class CefRunnableFunction : public CefTask { + public: + CefRunnableFunction(Function function, const Params& params) + : function_(function), params_(params) { + } + + ~CefRunnableFunction() { + } + + virtual void Execute() { + if (function_) + DispatchToFunction(function_, params_); + } + + private: + Function function_; + Params params_; + + IMPLEMENT_REFCOUNTING(CefRunnableFunction); +}; + +template +inline CefRefPtr NewCefRunnableFunction(Function function) { + return new CefRunnableFunction(function, MakeTuple()); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a) { + return new CefRunnableFunction >(function, MakeTuple(a)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b) { + return new CefRunnableFunction >(function, + MakeTuple(a, b)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, + c)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, + c, + d)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d, + const E& e) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, c, d, e)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, c, d, e, f)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f, + const G& g) { + return new CefRunnableFunction >( + function, MakeTuple(a, b, c, d, e, f, g)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d, + const E& e, const F& f, + const G& g, const H& h) { + return new CefRunnableFunction >( + function, MakeTuple(a, b, c, d, e, f, g, h)); +} + +#endif // CEF_INCLUDE_CEF_RUNNABLE_H_ diff --git a/include/cef_sandbox_win.h b/include/cef_sandbox_win.h new file mode 100644 index 000000000..9b6c48b09 --- /dev/null +++ b/include/cef_sandbox_win.h @@ -0,0 +1,92 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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_CEF_SANDBOX_WIN_H_ +#define CEF_INCLUDE_CEF_SANDBOX_WIN_H_ +#pragma once + +#include "include/cef_base.h" + +#if defined(OS_WIN) + +#ifdef __cplusplus +extern "C" { +#endif + +// The sandbox is used to restrict sub-processes (renderer, plugin, GPU, etc) +// from directly accessing system resources. This helps to protect the user +// from untrusted and potentially malicious Web content. +// See http://www.chromium.org/developers/design-documents/sandbox for +// complete details. +// +// To enable the sandbox on Windows the following requirements must be met: +// 1. Use the same executable for the browser process and all sub-processes. +// 2. Link the executable with the cef_sandbox static library. +// 3. Call the cef_sandbox_info_create() function from within the executable +// (not from a separate DLL) and pass the resulting pointer into both the +// CefExecutProcess() and CefInitialize() functions via the +// |windows_sandbox_info| parameter. + +/// +// Create the sandbox information object for this process. It is safe to create +// multiple of this object and to destroy the object immediately after passing +// into the CefExecutProcess() and/or CefInitialize() functions. +/// +void* cef_sandbox_info_create(); + +/// +// Destroy the specified sandbox information object. +/// +void cef_sandbox_info_destroy(void* sandbox_info); + +#ifdef __cplusplus +} + +/// +// Manages the life span of a sandbox information object. +/// +class CefScopedSandboxInfo { + public: + CefScopedSandboxInfo() { + sandbox_info_ = cef_sandbox_info_create(); + } + ~CefScopedSandboxInfo() { + cef_sandbox_info_destroy(sandbox_info_); + } + + void* sandbox_info() const { return sandbox_info_; } + + private: + void* sandbox_info_; +}; +#endif // __cplusplus + +#endif // defined(OS_WIN) + +#endif // CEF_INCLUDE_CEF_SANDBOX_WIN_H_ diff --git a/include/cef_scheme.h b/include/cef_scheme.h new file mode 100644 index 000000000..cd8415c07 --- /dev/null +++ b/include/cef_scheme.h @@ -0,0 +1,161 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_SCHEME_H_ +#define CEF_INCLUDE_CEF_SCHEME_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_request.h" +#include "include/cef_response.h" +#include "include/cef_resource_handler.h" + +class CefSchemeHandlerFactory; + + +/// +// Register a scheme handler factory for the specified |scheme_name| and +// optional |domain_name|. An empty |domain_name| value for a standard scheme +// will cause the factory to match all domain names. The |domain_name| value +// will be ignored for non-standard schemes. If |scheme_name| is a built-in +// scheme and no handler is returned by |factory| then the built-in scheme +// handler factory will be called. If |scheme_name| is a custom scheme then +// also implement the CefApp::OnRegisterCustomSchemes() method in all processes. +// This function may be called multiple times to change or remove the factory +// that matches the specified |scheme_name| and optional |domain_name|. +// Returns false if an error occurs. This function may be called on any thread +// in the browser process. +/// +/*--cef(optional_param=domain_name,optional_param=factory)--*/ +bool CefRegisterSchemeHandlerFactory( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory); + +/// +// Clear all registered scheme handler factories. Returns false on error. This +// function may be called on any thread in the browser process. +/// +/*--cef()--*/ +bool CefClearSchemeHandlerFactories(); + + +/// +// Class that manages custom scheme registrations. +/// +/*--cef(source=library)--*/ +class CefSchemeRegistrar : public virtual CefBase { + public: + /// + // Register a custom scheme. This method should not be called for the built-in + // HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes. + // + // If |is_standard| is true the scheme will be treated as a standard scheme. + // Standard schemes are subject to URL canonicalization and parsing rules as + // defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available + // at http://www.ietf.org/rfc/rfc1738.txt + // + // In particular, the syntax for standard scheme URLs must be of the form: + //
+  //  [scheme]://[username]:[password]@[host]:[port]/[url-path]
+  // 
+ // Standard scheme URLs must have a host component that is a fully qualified + // domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of + // RFC 1123. These URLs will be canonicalized to "scheme://host/path" in the + // simplest case and "scheme://username:password@host:port/path" in the most + // explicit case. For example, "scheme:host/path" and "scheme:///host/path" + // will both be canonicalized to "scheme://host/path". The origin of a + // standard scheme URL is the combination of scheme, host and port (i.e., + // "scheme://host:port" in the most explicit case). + // + // For non-standard scheme URLs only the "scheme:" component is parsed and + // canonicalized. The remainder of the URL will be passed to the handler + // as-is. For example, "scheme:///some%20text" will remain the same. + // Non-standard scheme URLs cannot be used as a target for form submission. + // + // If |is_local| is true the scheme will be treated as local (i.e., with the + // same security rules as those applied to "file" URLs). Normal pages cannot + // link to or access local URLs. Also, by default, local URLs can only perform + // XMLHttpRequest calls to the same URL (origin + path) that originated the + // request. To allow XMLHttpRequest calls from a local URL to other URLs with + // the same origin set the CefSettings.file_access_from_file_urls_allowed + // value to true. To allow XMLHttpRequest calls from a local URL to all + // origins set the CefSettings.universal_access_from_file_urls_allowed value + // to true. + // + // If |is_display_isolated| is true the scheme will be treated as display- + // isolated. This means that pages cannot display these URLs unless they are + // from the same scheme. For example, pages in another origin cannot create + // iframes or hyperlinks to URLs with this scheme. + // + // This function may be called on any thread. It should only be called once + // per unique |scheme_name| value. If |scheme_name| is already registered or + // if an error occurs this method will return false. + /// + /*--cef()--*/ + virtual bool AddCustomScheme(const CefString& scheme_name, + bool is_standard, + bool is_local, + bool is_display_isolated) =0; +}; + + +/// +// Class that creates CefResourceHandler instances for handling scheme requests. +// The methods of this class will always be called on the IO thread. +/// +/*--cef(source=client)--*/ +class CefSchemeHandlerFactory : public virtual CefBase { + public: + /// + // Return a new resource handler instance to handle the request or an empty + // reference to allow default handling of the request. |browser| and |frame| + // will be the browser window and frame respectively that originated the + // request or NULL if the request did not originate from a browser window + // (for example, if the request came from CefURLRequest). The |request| object + // passed to this method will not contain cookie data. + /// + /*--cef(optional_param=browser,optional_param=frame)--*/ + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) =0; +}; + +#endif // CEF_INCLUDE_CEF_SCHEME_H_ diff --git a/include/cef_stream.h b/include/cef_stream.h new file mode 100644 index 000000000..3d0633c25 --- /dev/null +++ b/include/cef_stream.h @@ -0,0 +1,242 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_STREAM_H_ +#define CEF_INCLUDE_CEF_STREAM_H_ + +#include "include/cef_base.h" + +/// +// Interface the client can implement to provide a custom stream reader. The +// methods of this class may be called on any thread. +/// +/*--cef(source=client)--*/ +class CefReadHandler : public virtual CefBase { + public: + /// + // Read raw binary data. + /// + /*--cef()--*/ + virtual size_t Read(void* ptr, size_t size, size_t n) =0; + + /// + // Seek to the specified offset position. |whence| may be any one of + // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on + // failure. + /// + /*--cef()--*/ + virtual int Seek(int64 offset, int whence) =0; + + /// + // Return the current offset position. + /// + /*--cef()--*/ + virtual int64 Tell() =0; + + /// + // Return non-zero if at end of file. + /// + /*--cef()--*/ + virtual int Eof() =0; + + /// + // Return true if this handler performs work like accessing the file system + // which may block. Used as a hint for determining the thread to access the + // handler from. + /// + /*--cef()--*/ + virtual bool MayBlock() =0; +}; + + +/// +// Class used to read data from a stream. The methods of this class may be +// called on any thread. +/// +/*--cef(source=library)--*/ +class CefStreamReader : public virtual CefBase { + public: + /// + // Create a new CefStreamReader object from a file. + /// + /*--cef()--*/ + static CefRefPtr CreateForFile(const CefString& fileName); + /// + // Create a new CefStreamReader object from data. + /// + /*--cef()--*/ + static CefRefPtr CreateForData(void* data, size_t size); + /// + // Create a new CefStreamReader object from a custom handler. + /// + /*--cef()--*/ + static CefRefPtr CreateForHandler( + CefRefPtr handler); + + /// + // Read raw binary data. + /// + /*--cef()--*/ + virtual size_t Read(void* ptr, size_t size, size_t n) =0; + + /// + // Seek to the specified offset position. |whence| may be any one of + // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on + // failure. + /// + /*--cef()--*/ + virtual int Seek(int64 offset, int whence) =0; + + /// + // Return the current offset position. + /// + /*--cef()--*/ + virtual int64 Tell() =0; + + /// + // Return non-zero if at end of file. + /// + /*--cef()--*/ + virtual int Eof() =0; + + /// + // Returns true if this reader performs work like accessing the file system + // which may block. Used as a hint for determining the thread to access the + // reader from. + /// + /*--cef()--*/ + virtual bool MayBlock() =0; +}; + + +/// +// Interface the client can implement to provide a custom stream writer. The +// methods of this class may be called on any thread. +/// +/*--cef(source=client)--*/ +class CefWriteHandler : public virtual CefBase { + public: + /// + // Write raw binary data. + /// + /*--cef()--*/ + virtual size_t Write(const void* ptr, size_t size, size_t n) =0; + + /// + // Seek to the specified offset position. |whence| may be any one of + // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on + // failure. + /// + /*--cef()--*/ + virtual int Seek(int64 offset, int whence) =0; + + /// + // Return the current offset position. + /// + /*--cef()--*/ + virtual int64 Tell() =0; + + /// + // Flush the stream. + /// + /*--cef()--*/ + virtual int Flush() =0; + + /// + // Return true if this handler performs work like accessing the file system + // which may block. Used as a hint for determining the thread to access the + // handler from. + /// + /*--cef()--*/ + virtual bool MayBlock() =0; +}; + + +/// +// Class used to write data to a stream. The methods of this class may be called +// on any thread. +/// +/*--cef(source=library)--*/ +class CefStreamWriter : public virtual CefBase { + public: + /// + // Create a new CefStreamWriter object for a file. + /// + /*--cef()--*/ + static CefRefPtr CreateForFile(const CefString& fileName); + /// + // Create a new CefStreamWriter object for a custom handler. + /// + /*--cef()--*/ + static CefRefPtr CreateForHandler( + CefRefPtr handler); + + /// + // Write raw binary data. + /// + /*--cef()--*/ + virtual size_t Write(const void* ptr, size_t size, size_t n) =0; + + /// + // Seek to the specified offset position. |whence| may be any one of + // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on + // failure. + /// + /*--cef()--*/ + virtual int Seek(int64 offset, int whence) =0; + + /// + // Return the current offset position. + /// + /*--cef()--*/ + virtual int64 Tell() =0; + + /// + // Flush the stream. + /// + /*--cef()--*/ + virtual int Flush() =0; + + /// + // Returns true if this writer performs work like accessing the file system + // which may block. Used as a hint for determining the thread to access the + // writer from. + /// + /*--cef()--*/ + virtual bool MayBlock() =0; +}; + +#endif // CEF_INCLUDE_CEF_STREAM_H_ diff --git a/include/cef_string_visitor.h b/include/cef_string_visitor.h new file mode 100644 index 000000000..549371473 --- /dev/null +++ b/include/cef_string_visitor.h @@ -0,0 +1,55 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_STRING_VISITOR_H_ +#define CEF_INCLUDE_CEF_STRING_VISITOR_H_ + +#include "include/cef_base.h" + +/// +// Implement this interface to receive string values asynchronously. +/// +/*--cef(source=client)--*/ +class CefStringVisitor : public virtual CefBase { + public: + /// + // Method that will be executed. + /// + /*--cef(optional_param=string)--*/ + virtual void Visit(const CefString& string) =0; +}; + +#endif // CEF_INCLUDE_CEF_STRING_VISITOR_H_ diff --git a/include/cef_task.h b/include/cef_task.h new file mode 100644 index 000000000..0ecaa7526 --- /dev/null +++ b/include/cef_task.h @@ -0,0 +1,148 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_TASK_H_ +#define CEF_INCLUDE_CEF_TASK_H_ + +#include "include/cef_base.h" + +typedef cef_thread_id_t CefThreadId; + +/// +// Implement this interface for asynchronous task execution. If the task is +// posted successfully and if the associated message loop is still running then +// the Execute() method will be called on the target thread. If the task fails +// to post then the task object may be destroyed on the source thread instead of +// the target thread. For this reason be cautious when performing work in the +// task object destructor. +/// +/*--cef(source=client)--*/ +class CefTask : public virtual CefBase { + public: + /// + // Method that will be executed on the target thread. + /// + /*--cef()--*/ + virtual void Execute() =0; +}; + +/// +// Class that asynchronously executes tasks on the associated thread. It is safe +// to call the methods of this class on any thread. +// +// CEF maintains multiple internal threads that are used for handling different +// types of tasks in different processes. The cef_thread_id_t definitions in +// cef_types.h list the common CEF threads. Task runners are also available for +// other CEF threads as appropriate (for example, V8 WebWorker threads). +/// +/*--cef(source=library)--*/ +class CefTaskRunner : public virtual CefBase { + public: + /// + // Returns the task runner for the current thread. Only CEF threads will have + // task runners. An empty reference will be returned if this method is called + // on an invalid thread. + /// + /*--cef()--*/ + static CefRefPtr GetForCurrentThread(); + + /// + // Returns the task runner for the specified CEF thread. + /// + /*--cef()--*/ + static CefRefPtr GetForThread(CefThreadId threadId); + + /// + // Returns true if this object is pointing to the same task runner as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr that) =0; + + /// + // Returns true if this task runner belongs to the current thread. + /// + /*--cef()--*/ + virtual bool BelongsToCurrentThread() =0; + + /// + // Returns true if this task runner is for the specified CEF thread. + /// + /*--cef()--*/ + virtual bool BelongsToThread(CefThreadId threadId) =0; + + /// + // Post a task for execution on the thread associated with this task runner. + // Execution will occur asynchronously. + /// + /*--cef()--*/ + virtual bool PostTask(CefRefPtr task) =0; + + /// + // Post a task for delayed execution on the thread associated with this task + // runner. Execution will occur asynchronously. Delayed tasks are not + // supported on V8 WebWorker threads and will be executed without the + // specified delay. + /// + /*--cef()--*/ + virtual bool PostDelayedTask(CefRefPtr task, int64 delay_ms) =0; +}; + + +/// +// Returns true if called on the specified thread. Equivalent to using +// CefTaskRunner::GetForThread(threadId)->BelongsToCurrentThread(). +/// +/*--cef()--*/ +bool CefCurrentlyOn(CefThreadId threadId); + +/// +// Post a task for execution on the specified thread. Equivalent to +// using CefTaskRunner::GetForThread(threadId)->PostTask(task). +/// +/*--cef()--*/ +bool CefPostTask(CefThreadId threadId, CefRefPtr task); + +/// +// Post a task for delayed execution on the specified thread. Equivalent to +// using CefTaskRunner::GetForThread(threadId)->PostDelayedTask(task, delay_ms). +/// +/*--cef()--*/ +bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr task, + int64 delay_ms); + + +#endif // CEF_INCLUDE_CEF_TASK_H_ diff --git a/include/cef_trace.h b/include/cef_trace.h new file mode 100644 index 000000000..5b977c6e5 --- /dev/null +++ b/include/cef_trace.h @@ -0,0 +1,111 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. Portons 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +// See cef_trace_event.h for trace macros and additonal documentation. + +#ifndef CEF_INCLUDE_CEF_TRACE_H_ +#define CEF_INCLUDE_CEF_TRACE_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_callback.h" + +/// +// Implement this interface to receive notification when tracing has completed. +// The methods of this class will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefEndTracingCallback : public virtual CefBase { + public: + /// + // Called after all processes have sent their trace data. |tracing_file| is + // the path at which tracing data was written. The client is responsible for + // deleting |tracing_file|. + /// + /*--cef()--*/ + virtual void OnEndTracingComplete(const CefString& tracing_file) =0; +}; + + +/// +// Start tracing events on all processes. Tracing is initialized asynchronously +// and |callback| will be executed on the UI thread after initialization is +// complete. +// +// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is +// pending, CefBeginTracing will fail and return false. +// +// |categories| is a comma-delimited list of category wildcards. A category can +// have an optional '-' prefix to make it an excluded category. Having both +// included and excluded categories in the same list is not supported. +// +// Example: "test_MyTest*" +// Example: "test_MyTest*,test_OtherStuff" +// Example: "-excluded_category1,-excluded_category2" +// +// This function must be called on the browser process UI thread. +/// +/*--cef(optional_param=categories,optional_param=callback)--*/ +bool CefBeginTracing(const CefString& categories, + CefRefPtr callback); + +/// +// Stop tracing events on all processes. +// +// This function will fail and return false if a previous call to +// CefEndTracingAsync is already pending or if CefBeginTracing was not called. +// +// |tracing_file| is the path at which tracing data will be written and +// |callback| is the callback that will be executed once all processes have +// sent their trace data. If |tracing_file| is empty a new temporary file path +// will be used. If |callback| is empty no trace data will be written. +// +// This function must be called on the browser process UI thread. +/// +/*--cef(optional_param=tracing_file,optional_param=callback)--*/ +bool CefEndTracing(const CefString& tracing_file, + CefRefPtr callback); + +/// +// Returns the current system trace time or, if none is defined, the current +// high-res time. Can be used by clients to synchronize with the time +// information in trace events. +/// +/*--cef()--*/ +int64 CefNowFromSystemTraceTime(); + +#endif // CEF_INCLUDE_CEF_TRACE_H_ diff --git a/include/cef_url.h b/include/cef_url.h new file mode 100644 index 000000000..d2def08e9 --- /dev/null +++ b/include/cef_url.h @@ -0,0 +1,77 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_URL_H_ +#define CEF_INCLUDE_CEF_URL_H_ +#pragma once + +#include + +#include "include/cef_base.h" + +/// +// Parse the specified |url| into its component parts. +// Returns false if the URL is empty or invalid. +/// +/*--cef()--*/ +bool CefParseURL(const CefString& url, + CefURLParts& parts); + +/// +// Creates a URL from the specified |parts|, which must contain a non-empty +// spec or a non-empty host and path (at a minimum), but not both. +// Returns false if |parts| isn't initialized as described. +/// +/*--cef()--*/ +bool CefCreateURL(const CefURLParts& parts, + CefString& url); + +/// +// Returns the mime type for the specified file extension or an empty string if +// unknown. +/// +/*--cef()--*/ +CefString CefGetMimeType(const CefString& extension); + +// Get the extensions associated with the given mime type. This should be passed +// in lower case. There could be multiple extensions for a given mime type, like +// "html,htm" for "text/html", or "txt,text,html,..." for "text/*". Any existing +// elements in the provided vector will not be erased. +/*--cef()--*/ +void CefGetExtensionsForMimeType(const CefString& mime_type, + std::vector& extensions); + +#endif // CEF_INCLUDE_CEF_URL_H_ diff --git a/include/cef_urlrequest.h b/include/cef_urlrequest.h new file mode 100644 index 000000000..02a9da684 --- /dev/null +++ b/include/cef_urlrequest.h @@ -0,0 +1,183 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_URLREQUEST_H_ +#define CEF_INCLUDE_CEF_URLREQUEST_H_ +#pragma once + +#include "include/cef_auth_callback.h" +#include "include/cef_base.h" +#include "include/cef_request.h" +#include "include/cef_response.h" + +class CefURLRequestClient; + +/// +// Class used to make a URL request. URL requests are not associated with a +// browser instance so no CefClient callbacks will be executed. URL requests +// can be created on any valid CEF thread in either the browser or render +// process. Once created the methods of the URL request object must be accessed +// on the same thread that created it. +/// +/*--cef(source=library)--*/ +class CefURLRequest : public virtual CefBase { + public: + typedef cef_urlrequest_status_t Status; + typedef cef_errorcode_t ErrorCode; + + /// + // Create a new URL request. Only GET, POST, HEAD, DELETE and PUT request + // methods are supported. Multiple post data elements are not supported and + // elements of type PDE_TYPE_FILE are only supported for requests originating + // from the browser process. Requests originating from the render process will + // receive the same handling as requests originating from Web content -- if + // the response contains Content-Disposition or Mime-Type header values that + // would not normally be rendered then the response may receive special + // handling inside the browser (for example, via the file download code path + // instead of the URL request code path). The |request| object will be marked + // as read-only after calling this method. + /// + /*--cef()--*/ + static CefRefPtr Create( + CefRefPtr request, + CefRefPtr client); + + /// + // Returns the request object used to create this URL request. The returned + // object is read-only and should not be modified. + /// + /*--cef()--*/ + virtual CefRefPtr GetRequest() =0; + + /// + // Returns the client. + /// + /*--cef()--*/ + virtual CefRefPtr GetClient() =0; + + /// + // Returns the request status. + /// + /*--cef(default_retval=UR_UNKNOWN)--*/ + virtual Status GetRequestStatus() =0; + + /// + // Returns the request error if status is UR_CANCELED or UR_FAILED, or 0 + // otherwise. + /// + /*--cef(default_retval=ERR_NONE)--*/ + virtual ErrorCode GetRequestError() =0; + + /// + // Returns the response, or NULL if no response information is available. + // Response information will only be available after the upload has completed. + // The returned object is read-only and should not be modified. + /// + /*--cef()--*/ + virtual CefRefPtr GetResponse() =0; + + /// + // Cancel the request. + /// + /*--cef()--*/ + virtual void Cancel() =0; +}; + +/// +// Interface that should be implemented by the CefURLRequest client. The +// methods of this class will be called on the same thread that created the +// request unless otherwise documented. +/// +/*--cef(source=client)--*/ +class CefURLRequestClient : public virtual CefBase { + public: + /// + // Notifies the client that the request has completed. Use the + // CefURLRequest::GetRequestStatus method to determine if the request was + // successful or not. + /// + /*--cef()--*/ + virtual void OnRequestComplete(CefRefPtr request) =0; + + /// + // Notifies the client of upload progress. |current| denotes the number of + // bytes sent so far and |total| is the total size of uploading data (or -1 if + // chunked upload is enabled). This method will only be called if the + // UR_FLAG_REPORT_UPLOAD_PROGRESS flag is set on the request. + /// + /*--cef()--*/ + virtual void OnUploadProgress(CefRefPtr request, + uint64 current, + uint64 total) =0; + + /// + // Notifies the client of download progress. |current| denotes the number of + // bytes received up to the call and |total| is the expected total size of the + // response (or -1 if not determined). + /// + /*--cef()--*/ + virtual void OnDownloadProgress(CefRefPtr request, + uint64 current, + uint64 total) =0; + + /// + // Called when some part of the response is read. |data| contains the current + // bytes received since the last call. This method will not be called if the + // UR_FLAG_NO_DOWNLOAD_DATA flag is set on the request. + /// + /*--cef()--*/ + virtual void OnDownloadData(CefRefPtr request, + const void* data, + size_t data_length) =0; + + /// + // Called on the IO thread when the browser needs credentials from the user. + // |isProxy| indicates whether the host is a proxy server. |host| contains the + // hostname and |port| contains the port number. Return true to continue the + // request and call CefAuthCallback::Continue() when the authentication + // information is available. Return false to cancel the request. This method + // will only be called for requests initiated from the browser process. + /// + /*--cef(optional_param=realm)--*/ + virtual bool GetAuthCredentials(bool isProxy, + const CefString& host, + int port, + const CefString& realm, + const CefString& scheme, + CefRefPtr callback) =0; +}; + +#endif // CEF_INCLUDE_CEF_URLREQUEST_H_ diff --git a/include/cef_v8.h b/include/cef_v8.h new file mode 100644 index 000000000..3f05b802e --- /dev/null +++ b/include/cef_v8.h @@ -0,0 +1,879 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + + +#ifndef CEF_INCLUDE_CEF_V8_H_ +#define CEF_INCLUDE_CEF_V8_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_task.h" +#include + +class CefV8Exception; +class CefV8Handler; +class CefV8StackFrame; +class CefV8Value; + + +/// +// Register a new V8 extension with the specified JavaScript extension code and +// handler. Functions implemented by the handler are prototyped using the +// keyword 'native'. The calling of a native function is restricted to the scope +// in which the prototype of the native function is defined. This function may +// only be called on the render process main thread. +// +// Example JavaScript extension code: +//
+//   // create the 'example' global object if it doesn't already exist.
+//   if (!example)
+//     example = {};
+//   // create the 'example.test' global object if it doesn't already exist.
+//   if (!example.test)
+//     example.test = {};
+//   (function() {
+//     // Define the function 'example.test.myfunction'.
+//     example.test.myfunction = function() {
+//       // Call CefV8Handler::Execute() with the function name 'MyFunction'
+//       // and no arguments.
+//       native function MyFunction();
+//       return MyFunction();
+//     };
+//     // Define the getter function for parameter 'example.test.myparam'.
+//     example.test.__defineGetter__('myparam', function() {
+//       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
+//       // and no arguments.
+//       native function GetMyParam();
+//       return GetMyParam();
+//     });
+//     // Define the setter function for parameter 'example.test.myparam'.
+//     example.test.__defineSetter__('myparam', function(b) {
+//       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
+//       // and a single argument.
+//       native function SetMyParam();
+//       if(b) SetMyParam(b);
+//     });
+//
+//     // Extension definitions can also contain normal JavaScript variables
+//     // and functions.
+//     var myint = 0;
+//     example.test.increment = function() {
+//       myint += 1;
+//       return myint;
+//     };
+//   })();
+// 
+// Example usage in the page: +//
+//   // Call the function.
+//   example.test.myfunction();
+//   // Set the parameter.
+//   example.test.myparam = value;
+//   // Get the parameter.
+//   value = example.test.myparam;
+//   // Call another function.
+//   example.test.increment();
+// 
+/// +/*--cef(optional_param=handler)--*/ +bool CefRegisterExtension(const CefString& extension_name, + const CefString& javascript_code, + CefRefPtr handler); + + +/// +// Class representing a V8 context handle. V8 handles can only be accessed from +// the thread on which they are created. Valid threads for creating a V8 handle +// include the render process main thread (TID_RENDERER) and WebWorker threads. +// A task runner for posting tasks on the associated thread can be retrieved via +// the CefV8Context::GetTaskRunner() method. +/// +/*--cef(source=library)--*/ +class CefV8Context : public virtual CefBase { + public: + /// + // Returns the current (top) context object in the V8 context stack. + /// + /*--cef()--*/ + static CefRefPtr GetCurrentContext(); + + /// + // Returns the entered (bottom) context object in the V8 context stack. + /// + /*--cef()--*/ + static CefRefPtr GetEnteredContext(); + + /// + // Returns true if V8 is currently inside a context. + /// + /*--cef()--*/ + static bool InContext(); + + /// + // Returns the task runner associated with this context. V8 handles can only + // be accessed from the thread on which they are created. This method can be + // called on any render process thread. + /// + /*--cef()--*/ + virtual CefRefPtr GetTaskRunner() =0; + + /// + // Returns true if the underlying handle is valid and it can be accessed on + // the current thread. Do not call any other methods if this method returns + // false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns the browser for this context. This method will return an empty + // reference for WebWorker contexts. + /// + /*--cef()--*/ + virtual CefRefPtr GetBrowser() =0; + + /// + // Returns the frame for this context. This method will return an empty + // reference for WebWorker contexts. + /// + /*--cef()--*/ + virtual CefRefPtr GetFrame() =0; + + /// + // Returns the global object for this context. The context must be entered + // before calling this method. + /// + /*--cef()--*/ + virtual CefRefPtr GetGlobal() =0; + + /// + // Enter this context. A context must be explicitly entered before creating a + // V8 Object, Array, Function or Date asynchronously. Exit() must be called + // the same number of times as Enter() before releasing this context. V8 + // objects belong to the context in which they are created. Returns true if + // the scope was entered successfully. + /// + /*--cef()--*/ + virtual bool Enter() =0; + + /// + // Exit this context. Call this method only after calling Enter(). Returns + // true if the scope was exited successfully. + /// + /*--cef()--*/ + virtual bool Exit() =0; + + /// + // Returns true if this object is pointing to the same handle as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr that) =0; + + /// + // Evaluates the specified JavaScript code using this context's global object. + // On success |retval| will be set to the return value, if any, and the + // function will return true. On failure |exception| will be set to the + // exception, if any, and the function will return false. + /// + /*--cef()--*/ + virtual bool Eval(const CefString& code, + CefRefPtr& retval, + CefRefPtr& exception) =0; +}; + + +typedef std::vector > CefV8ValueList; + +/// +// Interface that should be implemented to handle V8 function calls. The methods +// of this class will be called on the thread associated with the V8 function. +/// +/*--cef(source=client)--*/ +class CefV8Handler : public virtual CefBase { + public: + /// + // Handle execution of the function identified by |name|. |object| is the + // receiver ('this' object) of the function. |arguments| is the list of + // arguments passed to the function. If execution succeeds set |retval| to the + // function return value. If execution fails set |exception| to the exception + // that will be thrown. Return true if execution was handled. + /// + /*--cef()--*/ + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) =0; +}; + +/// +// Interface that should be implemented to handle V8 accessor calls. Accessor +// identifiers are registered by calling CefV8Value::SetValue(). The methods +// of this class will be called on the thread associated with the V8 accessor. +/// +/*--cef(source=client)--*/ +class CefV8Accessor : public virtual CefBase { + public: + /// + // Handle retrieval the accessor value identified by |name|. |object| is the + // receiver ('this' object) of the accessor. If retrieval succeeds set + // |retval| to the return value. If retrieval fails set |exception| to the + // exception that will be thrown. Return true if accessor retrieval was + // handled. + /// + /*--cef()--*/ + virtual bool Get(const CefString& name, + const CefRefPtr object, + CefRefPtr& retval, + CefString& exception) =0; + + /// + // Handle assignment of the accessor value identified by |name|. |object| is + // the receiver ('this' object) of the accessor. |value| is the new value + // being assigned to the accessor. If assignment fails set |exception| to the + // exception that will be thrown. Return true if accessor assignment was + // handled. + /// + /*--cef()--*/ + virtual bool Set(const CefString& name, + const CefRefPtr object, + const CefRefPtr value, + CefString& exception) =0; +}; + +/// +// Class representing a V8 exception. The methods of this class may be called on +// any render process thread. +/// +/*--cef(source=library)--*/ +class CefV8Exception : public virtual CefBase { + public: + /// + // Returns the exception message. + /// + /*--cef()--*/ + virtual CefString GetMessage() =0; + + /// + // Returns the line of source code that the exception occurred within. + /// + /*--cef()--*/ + virtual CefString GetSourceLine() =0; + + /// + // Returns the resource name for the script from where the function causing + // the error originates. + /// + /*--cef()--*/ + virtual CefString GetScriptResourceName() =0; + + /// + // Returns the 1-based number of the line where the error occurred or 0 if the + // line number is unknown. + /// + /*--cef()--*/ + virtual int GetLineNumber() =0; + + /// + // Returns the index within the script of the first character where the error + // occurred. + /// + /*--cef()--*/ + virtual int GetStartPosition() =0; + + /// + // Returns the index within the script of the last character where the error + // occurred. + /// + /*--cef()--*/ + virtual int GetEndPosition() =0; + + /// + // Returns the index within the line of the first character where the error + // occurred. + /// + /*--cef()--*/ + virtual int GetStartColumn() =0; + + /// + // Returns the index within the line of the last character where the error + // occurred. + /// + /*--cef()--*/ + virtual int GetEndColumn() =0; +}; + +/// +// Class representing a V8 value handle. V8 handles can only be accessed from +// the thread on which they are created. Valid threads for creating a V8 handle +// include the render process main thread (TID_RENDERER) and WebWorker threads. +// A task runner for posting tasks on the associated thread can be retrieved via +// the CefV8Context::GetTaskRunner() method. +/// +/*--cef(source=library)--*/ +class CefV8Value : public virtual CefBase { + public: + typedef cef_v8_accesscontrol_t AccessControl; + typedef cef_v8_propertyattribute_t PropertyAttribute; + + /// + // Create a new CefV8Value object of type undefined. + /// + /*--cef()--*/ + static CefRefPtr CreateUndefined(); + + /// + // Create a new CefV8Value object of type null. + /// + /*--cef()--*/ + static CefRefPtr CreateNull(); + + /// + // Create a new CefV8Value object of type bool. + /// + /*--cef()--*/ + static CefRefPtr CreateBool(bool value); + + /// + // Create a new CefV8Value object of type int. + /// + /*--cef()--*/ + static CefRefPtr CreateInt(int32 value); + + /// + // Create a new CefV8Value object of type unsigned int. + /// + /*--cef()--*/ + static CefRefPtr CreateUInt(uint32 value); + + /// + // Create a new CefV8Value object of type double. + /// + /*--cef()--*/ + static CefRefPtr CreateDouble(double value); + + /// + // Create a new CefV8Value object of type Date. This method should only be + // called from within the scope of a CefV8ContextHandler, CefV8Handler or + // CefV8Accessor callback, or in combination with calling Enter() and Exit() + // on a stored CefV8Context reference. + /// + /*--cef()--*/ + static CefRefPtr CreateDate(const CefTime& date); + + /// + // Create a new CefV8Value object of type string. + /// + /*--cef(optional_param=value)--*/ + static CefRefPtr CreateString(const CefString& value); + + /// + // Create a new CefV8Value object of type object with optional accessor. This + // method should only be called from within the scope of a + // CefV8ContextHandler, CefV8Handler or CefV8Accessor callback, or in + // combination with calling Enter() and Exit() on a stored CefV8Context + // reference. + /// + /*--cef(optional_param=accessor)--*/ + static CefRefPtr CreateObject(CefRefPtr accessor); + + /// + // Create a new CefV8Value object of type array with the specified |length|. + // If |length| is negative the returned array will have length 0. This method + // should only be called from within the scope of a CefV8ContextHandler, + // CefV8Handler or CefV8Accessor callback, or in combination with calling + // Enter() and Exit() on a stored CefV8Context reference. + /// + /*--cef()--*/ + static CefRefPtr CreateArray(int length); + + /// + // Create a new CefV8Value object of type function. This method should only be + // called from within the scope of a CefV8ContextHandler, CefV8Handler or + // CefV8Accessor callback, or in combination with calling Enter() and Exit() + // on a stored CefV8Context reference. + /// + /*--cef()--*/ + static CefRefPtr CreateFunction(const CefString& name, + CefRefPtr handler); + + /// + // Returns true if the underlying handle is valid and it can be accessed on + // the current thread. Do not call any other methods if this method returns + // false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // True if the value type is undefined. + /// + /*--cef()--*/ + virtual bool IsUndefined() =0; + + /// + // True if the value type is null. + /// + /*--cef()--*/ + virtual bool IsNull() =0; + + /// + // True if the value type is bool. + /// + /*--cef()--*/ + virtual bool IsBool() =0; + + /// + // True if the value type is int. + /// + /*--cef()--*/ + virtual bool IsInt() =0; + + /// + // True if the value type is unsigned int. + /// + /*--cef()--*/ + virtual bool IsUInt() =0; + + /// + // True if the value type is double. + /// + /*--cef()--*/ + virtual bool IsDouble() =0; + + /// + // True if the value type is Date. + /// + /*--cef()--*/ + virtual bool IsDate() =0; + + /// + // True if the value type is string. + /// + /*--cef()--*/ + virtual bool IsString() =0; + + /// + // True if the value type is object. + /// + /*--cef()--*/ + virtual bool IsObject() =0; + + /// + // True if the value type is array. + /// + /*--cef()--*/ + virtual bool IsArray() =0; + + /// + // True if the value type is function. + /// + /*--cef()--*/ + virtual bool IsFunction() =0; + + /// + // Returns true if this object is pointing to the same handle as |that| + // object. + /// + /*--cef()--*/ + virtual bool IsSame(CefRefPtr that) =0; + + /// + // Return a bool value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual bool GetBoolValue() =0; + + /// + // Return an int value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual int32 GetIntValue() =0; + + /// + // Return an unisgned int value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual uint32 GetUIntValue() =0; + + /// + // Return a double value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual double GetDoubleValue() =0; + + /// + // Return a Date value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual CefTime GetDateValue() =0; + + /// + // Return a string value. The underlying data will be converted to if + // necessary. + /// + /*--cef()--*/ + virtual CefString GetStringValue() =0; + + + // OBJECT METHODS - These methods are only available on objects. Arrays and + // functions are also objects. String- and integer-based keys can be used + // interchangably with the framework converting between them as necessary. + + /// + // Returns true if this is a user created object. + /// + /*--cef()--*/ + virtual bool IsUserCreated() =0; + + /// + // Returns true if the last method call resulted in an exception. This + // attribute exists only in the scope of the current CEF value object. + /// + /*--cef()--*/ + virtual bool HasException() =0; + + /// + // Returns the exception resulting from the last method call. This attribute + // exists only in the scope of the current CEF value object. + /// + /*--cef()--*/ + virtual CefRefPtr GetException() =0; + + /// + // Clears the last exception and returns true on success. + /// + /*--cef()--*/ + virtual bool ClearException() =0; + + /// + // Returns true if this object will re-throw future exceptions. This attribute + // exists only in the scope of the current CEF value object. + /// + /*--cef()--*/ + virtual bool WillRethrowExceptions() =0; + + /// + // Set whether this object will re-throw future exceptions. By default + // exceptions are not re-thrown. If a exception is re-thrown the current + // context should not be accessed again until after the exception has been + // caught and not re-thrown. Returns true on success. This attribute exists + // only in the scope of the current CEF value object. + /// + /*--cef()--*/ + virtual bool SetRethrowExceptions(bool rethrow) =0; + + /// + // Returns true if the object has a value with the specified identifier. + /// + /*--cef(capi_name=has_value_bykey,optional_param=key)--*/ + virtual bool HasValue(const CefString& key) =0; + + /// + // Returns true if the object has a value with the specified identifier. + /// + /*--cef(capi_name=has_value_byindex,index_param=index)--*/ + virtual bool HasValue(int index) =0; + + /// + // Deletes the value with the specified identifier and returns true on + // success. Returns false if this method is called incorrectly or an exception + // is thrown. For read-only and don't-delete values this method will return + // true even though deletion failed. + /// + /*--cef(capi_name=delete_value_bykey,optional_param=key)--*/ + virtual bool DeleteValue(const CefString& key) =0; + + /// + // Deletes the value with the specified identifier and returns true on + // success. Returns false if this method is called incorrectly, deletion fails + // or an exception is thrown. For read-only and don't-delete values this + // method will return true even though deletion failed. + /// + /*--cef(capi_name=delete_value_byindex,index_param=index)--*/ + virtual bool DeleteValue(int index) =0; + + /// + // Returns the value with the specified identifier on success. Returns NULL + // if this method is called incorrectly or an exception is thrown. + /// + /*--cef(capi_name=get_value_bykey,optional_param=key)--*/ + virtual CefRefPtr GetValue(const CefString& key) =0; + + /// + // Returns the value with the specified identifier on success. Returns NULL + // if this method is called incorrectly or an exception is thrown. + /// + /*--cef(capi_name=get_value_byindex,index_param=index)--*/ + virtual CefRefPtr GetValue(int index) =0; + + /// + // Associates a value with the specified identifier and returns true on + // success. Returns false if this method is called incorrectly or an exception + // is thrown. For read-only values this method will return true even though + // assignment failed. + /// + /*--cef(capi_name=set_value_bykey,optional_param=key)--*/ + virtual bool SetValue(const CefString& key, CefRefPtr value, + PropertyAttribute attribute) =0; + + /// + // Associates a value with the specified identifier and returns true on + // success. Returns false if this method is called incorrectly or an exception + // is thrown. For read-only values this method will return true even though + // assignment failed. + /// + /*--cef(capi_name=set_value_byindex,index_param=index)--*/ + virtual bool SetValue(int index, CefRefPtr value) =0; + + /// + // Registers an identifier and returns true on success. Access to the + // identifier will be forwarded to the CefV8Accessor instance passed to + // CefV8Value::CreateObject(). Returns false if this method is called + // incorrectly or an exception is thrown. For read-only values this method + // will return true even though assignment failed. + /// + /*--cef(capi_name=set_value_byaccessor,optional_param=key)--*/ + virtual bool SetValue(const CefString& key, AccessControl settings, + PropertyAttribute attribute) =0; + + /// + // Read the keys for the object's values into the specified vector. Integer- + // based keys will also be returned as strings. + /// + /*--cef()--*/ + virtual bool GetKeys(std::vector& keys) =0; + + /// + // Sets the user data for this object and returns true on success. Returns + // false if this method is called incorrectly. This method can only be called + // on user created objects. + /// + /*--cef(optional_param=user_data)--*/ + virtual bool SetUserData(CefRefPtr user_data) =0; + + /// + // Returns the user data, if any, assigned to this object. + /// + /*--cef()--*/ + virtual CefRefPtr GetUserData() =0; + + /// + // Returns the amount of externally allocated memory registered for the + // object. + /// + /*--cef()--*/ + virtual int GetExternallyAllocatedMemory() =0; + + /// + // Adjusts the amount of registered external memory for the object. Used to + // give V8 an indication of the amount of externally allocated memory that is + // kept alive by JavaScript objects. V8 uses this information to decide when + // to perform global garbage collection. Each CefV8Value tracks the amount of + // external memory associated with it and automatically decreases the global + // total by the appropriate amount on its destruction. |change_in_bytes| + // specifies the number of bytes to adjust by. This method returns the number + // of bytes associated with the object after the adjustment. This method can + // only be called on user created objects. + /// + /*--cef()--*/ + virtual int AdjustExternallyAllocatedMemory(int change_in_bytes) =0; + + + // ARRAY METHODS - These methods are only available on arrays. + + /// + // Returns the number of elements in the array. + /// + /*--cef()--*/ + virtual int GetArrayLength() =0; + + + // FUNCTION METHODS - These methods are only available on functions. + + /// + // Returns the function name. + /// + /*--cef()--*/ + virtual CefString GetFunctionName() =0; + + /// + // Returns the function handler or NULL if not a CEF-created function. + /// + /*--cef()--*/ + virtual CefRefPtr GetFunctionHandler() =0; + + /// + // Execute the function using the current V8 context. This method should only + // be called from within the scope of a CefV8Handler or CefV8Accessor + // callback, or in combination with calling Enter() and Exit() on a stored + // CefV8Context reference. |object| is the receiver ('this' object) of the + // function. If |object| is empty the current context's global object will be + // used. |arguments| is the list of arguments that will be passed to the + // function. Returns the function return value on success. Returns NULL if + // this method is called incorrectly or an exception is thrown. + /// + /*--cef(optional_param=object)--*/ + virtual CefRefPtr ExecuteFunction( + CefRefPtr object, + const CefV8ValueList& arguments) =0; + + /// + // Execute the function using the specified V8 context. |object| is the + // receiver ('this' object) of the function. If |object| is empty the + // specified context's global object will be used. |arguments| is the list of + // arguments that will be passed to the function. Returns the function return + // value on success. Returns NULL if this method is called incorrectly or an + // exception is thrown. + /// + /*--cef(optional_param=object)--*/ + virtual CefRefPtr ExecuteFunctionWithContext( + CefRefPtr context, + CefRefPtr object, + const CefV8ValueList& arguments) =0; +}; + +/// +// Class representing a V8 stack trace handle. V8 handles can only be accessed +// from the thread on which they are created. Valid threads for creating a V8 +// handle include the render process main thread (TID_RENDERER) and WebWorker +// threads. A task runner for posting tasks on the associated thread can be +// retrieved via the CefV8Context::GetTaskRunner() method. +/// +/*--cef(source=library)--*/ +class CefV8StackTrace : public virtual CefBase { + public: + /// + // Returns the stack trace for the currently active context. |frame_limit| is + // the maximum number of frames that will be captured. + /// + /*--cef()--*/ + static CefRefPtr GetCurrent(int frame_limit); + + /// + // Returns true if the underlying handle is valid and it can be accessed on + // the current thread. Do not call any other methods if this method returns + // false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns the number of stack frames. + /// + /*--cef()--*/ + virtual int GetFrameCount() =0; + + /// + // Returns the stack frame at the specified 0-based index. + /// + /*--cef()--*/ + virtual CefRefPtr GetFrame(int index) =0; +}; + +/// +// Class representing a V8 stack frame handle. V8 handles can only be accessed +// from the thread on which they are created. Valid threads for creating a V8 +// handle include the render process main thread (TID_RENDERER) and WebWorker +// threads. A task runner for posting tasks on the associated thread can be +// retrieved via the CefV8Context::GetTaskRunner() method. +/// +/*--cef(source=library)--*/ +class CefV8StackFrame : public virtual CefBase { + public: + /// + // Returns true if the underlying handle is valid and it can be accessed on + // the current thread. Do not call any other methods if this method returns + // false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns the name of the resource script that contains the function. + /// + /*--cef()--*/ + virtual CefString GetScriptName() =0; + + /// + // Returns the name of the resource script that contains the function or the + // sourceURL value if the script name is undefined and its source ends with + // a "//@ sourceURL=..." string. + /// + /*--cef()--*/ + virtual CefString GetScriptNameOrSourceURL() =0; + + /// + // Returns the name of the function. + /// + /*--cef()--*/ + virtual CefString GetFunctionName() =0; + + /// + // Returns the 1-based line number for the function call or 0 if unknown. + /// + /*--cef()--*/ + virtual int GetLineNumber() =0; + + /// + // Returns the 1-based column offset on the line for the function call or 0 if + // unknown. + /// + /*--cef()--*/ + virtual int GetColumn() =0; + + /// + // Returns true if the function was compiled using eval(). + /// + /*--cef()--*/ + virtual bool IsEval() =0; + + /// + // Returns true if the function was called as a constructor via "new". + /// + /*--cef()--*/ + virtual bool IsConstructor() =0; +}; + +#endif // CEF_INCLUDE_CEF_V8_H_ diff --git a/include/cef_values.h b/include/cef_values.h new file mode 100644 index 000000000..9a640ab77 --- /dev/null +++ b/include/cef_values.h @@ -0,0 +1,471 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_VALUES_H_ +#define CEF_INCLUDE_CEF_VALUES_H_ +#pragma once + +#include +#include "include/cef_base.h" + +class CefDictionaryValue; +class CefListValue; + +typedef cef_value_type_t CefValueType; + +/// +// Class representing a binary value. Can be used on any process and thread. +/// +/*--cef(source=library)--*/ +class CefBinaryValue : public virtual CefBase { + public: + /// + // Creates a new object that is not owned by any other object. The specified + // |data| will be copied. + /// + /*--cef()--*/ + static CefRefPtr Create(const void* data, + size_t data_size); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // method returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if this object is currently owned by another object. + /// + /*--cef()--*/ + virtual bool IsOwned() =0; + + /// + // Returns a copy of this object. The data in this object will also be copied. + /// + /*--cef()--*/ + virtual CefRefPtr Copy() =0; + + /// + // Returns the data size. + /// + /*--cef()--*/ + virtual size_t GetSize() =0; + + /// + // Read up to |buffer_size| number of bytes into |buffer|. Reading begins at + // the specified byte |data_offset|. Returns the number of bytes read. + /// + /*--cef()--*/ + virtual size_t GetData(void* buffer, + size_t buffer_size, + size_t data_offset) =0; +}; + + +/// +// Class representing a dictionary value. Can be used on any process and thread. +/// +/*--cef(source=library)--*/ +class CefDictionaryValue : public virtual CefBase { + public: + typedef std::vector KeyList; + + /// + // Creates a new object that is not owned by any other object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // method returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if this object is currently owned by another object. + /// + /*--cef()--*/ + virtual bool IsOwned() =0; + + /// + // Returns true if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns a writable copy of this object. If |exclude_empty_children| is true + // any empty dictionaries or lists will be excluded from the copy. + /// + /*--cef()--*/ + virtual CefRefPtr Copy(bool exclude_empty_children) =0; + + /// + // Returns the number of values. + /// + /*--cef()--*/ + virtual size_t GetSize() =0; + + /// + // Removes all values. Returns true on success. + /// + /*--cef()--*/ + virtual bool Clear() =0; + + /// + // Returns true if the current dictionary has a value for the given key. + /// + /*--cef()--*/ + virtual bool HasKey(const CefString& key) =0; + + /// + // Reads all keys for this dictionary into the specified vector. + /// + /*--cef()--*/ + virtual bool GetKeys(KeyList& keys) =0; + + /// + // Removes the value at the specified key. Returns true is the value was + // removed successfully. + /// + /*--cef()--*/ + virtual bool Remove(const CefString& key) =0; + + /// + // Returns the value type for the specified key. + /// + /*--cef(default_retval=VTYPE_INVALID)--*/ + virtual CefValueType GetType(const CefString& key) =0; + + /// + // Returns the value at the specified key as type bool. + /// + /*--cef()--*/ + virtual bool GetBool(const CefString& key) =0; + + /// + // Returns the value at the specified key as type int. + /// + /*--cef()--*/ + virtual int GetInt(const CefString& key) =0; + + /// + // Returns the value at the specified key as type double. + /// + /*--cef()--*/ + virtual double GetDouble(const CefString& key) =0; + + /// + // Returns the value at the specified key as type string. + /// + /*--cef()--*/ + virtual CefString GetString(const CefString& key) =0; + + /// + // Returns the value at the specified key as type binary. + /// + /*--cef()--*/ + virtual CefRefPtr GetBinary(const CefString& key) =0; + + /// + // Returns the value at the specified key as type dictionary. + /// + /*--cef()--*/ + virtual CefRefPtr GetDictionary(const CefString& key) =0; + + /// + // Returns the value at the specified key as type list. + /// + /*--cef()--*/ + virtual CefRefPtr GetList(const CefString& key) =0; + + /// + // Sets the value at the specified key as type null. Returns true if the + // value was set successfully. + /// + /*--cef()--*/ + virtual bool SetNull(const CefString& key) =0; + + /// + // Sets the value at the specified key as type bool. Returns true if the + // value was set successfully. + /// + /*--cef()--*/ + virtual bool SetBool(const CefString& key, bool value) =0; + + /// + // Sets the value at the specified key as type int. Returns true if the + // value was set successfully. + /// + /*--cef()--*/ + virtual bool SetInt(const CefString& key, int value) =0; + + /// + // Sets the value at the specified key as type double. Returns true if the + // value was set successfully. + /// + /*--cef()--*/ + virtual bool SetDouble(const CefString& key, double value) =0; + + /// + // Sets the value at the specified key as type string. Returns true if the + // value was set successfully. + /// + /*--cef(optional_param=value)--*/ + virtual bool SetString(const CefString& key, const CefString& value) =0; + + /// + // Sets the value at the specified key as type binary. Returns true if the + // value was set successfully. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef()--*/ + virtual bool SetBinary(const CefString& key, + CefRefPtr value) =0; + + /// + // Sets the value at the specified key as type dict. Returns true if the + // value was set successfully. After calling this method the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef()--*/ + virtual bool SetDictionary(const CefString& key, + CefRefPtr value) =0; + + /// + // Sets the value at the specified key as type list. Returns true if the + // value was set successfully. After calling this method the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef()--*/ + virtual bool SetList(const CefString& key, + CefRefPtr value) =0; +}; + + +/// +// Class representing a list value. Can be used on any process and thread. +/// +/*--cef(source=library)--*/ +class CefListValue : public virtual CefBase { + public: + /// + // Creates a new object that is not owned by any other object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns true if this object is valid. Do not call any other methods if this + // method returns false. + /// + /*--cef()--*/ + virtual bool IsValid() =0; + + /// + // Returns true if this object is currently owned by another object. + /// + /*--cef()--*/ + virtual bool IsOwned() =0; + + /// + // Returns true if the values of this object are read-only. Some APIs may + // expose read-only objects. + /// + /*--cef()--*/ + virtual bool IsReadOnly() =0; + + /// + // Returns a writable copy of this object. + /// + /*--cef()--*/ + virtual CefRefPtr Copy() =0; + + /// + // Sets the number of values. If the number of values is expanded all + // new value slots will default to type null. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetSize(size_t size) =0; + + /// + // Returns the number of values. + /// + /*--cef()--*/ + virtual size_t GetSize() =0; + + /// + // Removes all values. Returns true on success. + /// + /*--cef()--*/ + virtual bool Clear() =0; + + /// + // Removes the value at the specified index. + /// + /*--cef(index_param=index)--*/ + virtual bool Remove(int index) =0; + + /// + // Returns the value type at the specified index. + /// + /*--cef(default_retval=VTYPE_INVALID,index_param=index)--*/ + virtual CefValueType GetType(int index) =0; + + /// + // Returns the value at the specified index as type bool. + /// + /*--cef(index_param=index)--*/ + virtual bool GetBool(int index) =0; + + /// + // Returns the value at the specified index as type int. + /// + /*--cef(index_param=index)--*/ + virtual int GetInt(int index) =0; + + /// + // Returns the value at the specified index as type double. + /// + /*--cef(index_param=index)--*/ + virtual double GetDouble(int index) =0; + + /// + // Returns the value at the specified index as type string. + /// + /*--cef(index_param=index)--*/ + virtual CefString GetString(int index) =0; + + /// + // Returns the value at the specified index as type binary. + /// + /*--cef(index_param=index)--*/ + virtual CefRefPtr GetBinary(int index) =0; + + /// + // Returns the value at the specified index as type dictionary. + /// + /*--cef(index_param=index)--*/ + virtual CefRefPtr GetDictionary(int index) =0; + + /// + // Returns the value at the specified index as type list. + /// + /*--cef(index_param=index)--*/ + virtual CefRefPtr GetList(int index) =0; + + /// + // Sets the value at the specified index as type null. Returns true if the + // value was set successfully. + /// + /*--cef(index_param=index)--*/ + virtual bool SetNull(int index) =0; + + /// + // Sets the value at the specified index as type bool. Returns true if the + // value was set successfully. + /// + /*--cef(index_param=index)--*/ + virtual bool SetBool(int index, bool value) =0; + + /// + // Sets the value at the specified index as type int. Returns true if the + // value was set successfully. + /// + /*--cef(index_param=index)--*/ + virtual bool SetInt(int index, int value) =0; + + /// + // Sets the value at the specified index as type double. Returns true if the + // value was set successfully. + /// + /*--cef(index_param=index)--*/ + virtual bool SetDouble(int index, double value) =0; + + /// + // Sets the value at the specified index as type string. Returns true if the + // value was set successfully. + /// + /*--cef(optional_param=value,index_param=index)--*/ + virtual bool SetString(int index, const CefString& value) =0; + + /// + // Sets the value at the specified index as type binary. Returns true if the + // value was set successfully. After calling this method the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef(index_param=index)--*/ + virtual bool SetBinary(int index, CefRefPtr value) =0; + + /// + // Sets the value at the specified index as type dict. Returns true if the + // value was set successfully. After calling this method the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef(index_param=index)--*/ + virtual bool SetDictionary(int index, CefRefPtr value) =0; + + /// + // Sets the value at the specified index as type list. Returns true if the + // value was set successfully. After calling this method the |value| object + // will no longer be valid. If |value| is currently owned by another object + // then the value will be copied and the |value| reference will not change. + // Otherwise, ownership will be transferred to this object and the |value| + // reference will be invalidated. + /// + /*--cef(index_param=index)--*/ + virtual bool SetList(int index, CefRefPtr value) =0; +}; + +#endif // CEF_INCLUDE_CEF_VALUES_H_ diff --git a/include/cef_web_plugin.h b/include/cef_web_plugin.h new file mode 100644 index 000000000..0ff2b8ea1 --- /dev/null +++ b/include/cef_web_plugin.h @@ -0,0 +1,178 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_WEB_PLUGIN_H_ +#define CEF_INCLUDE_CEF_WEB_PLUGIN_H_ + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Information about a specific web plugin. +/// +/*--cef(source=library)--*/ +class CefWebPluginInfo : public virtual CefBase { + public: + /// + // Returns the plugin name (i.e. Flash). + /// + /*--cef()--*/ + virtual CefString GetName() =0; + + /// + // Returns the plugin file path (DLL/bundle/library). + /// + /*--cef()--*/ + virtual CefString GetPath() =0; + + /// + // Returns the version of the plugin (may be OS-specific). + /// + /*--cef()--*/ + virtual CefString GetVersion() =0; + + /// + // Returns a description of the plugin from the version information. + /// + /*--cef()--*/ + virtual CefString GetDescription() =0; +}; + +/// +// Interface to implement for visiting web plugin information. The methods of +// this class will be called on the browser process UI thread. +/// +/*--cef(source=client)--*/ +class CefWebPluginInfoVisitor : public virtual CefBase { + public: + /// + // Method that will be called once for each plugin. |count| is the 0-based + // index for the current plugin. |total| is the total number of plugins. + // Return false to stop visiting plugins. This method may never be called if + // no plugins are found. + /// + /*--cef()--*/ + virtual bool Visit(CefRefPtr info, int count, int total) =0; +}; + +/// +// Visit web plugin information. Can be called on any thread in the browser +// process. +/// +/*--cef()--*/ +void CefVisitWebPluginInfo(CefRefPtr visitor); + +/// +// Cause the plugin list to refresh the next time it is accessed regardless +// of whether it has already been loaded. Can be called on any thread in the +// browser process. +/// +/*--cef()--*/ +void CefRefreshWebPlugins(); + +/// +// Add a plugin path (directory + file). This change may not take affect until +// after CefRefreshWebPlugins() is called. Can be called on any thread in the +// browser process. +/// +/*--cef()--*/ +void CefAddWebPluginPath(const CefString& path); + +/// +// Add a plugin directory. This change may not take affect until after +// CefRefreshWebPlugins() is called. Can be called on any thread in the browser +// process. +/// +/*--cef()--*/ +void CefAddWebPluginDirectory(const CefString& dir); + +/// +// Remove a plugin path (directory + file). This change may not take affect +// until after CefRefreshWebPlugins() is called. Can be called on any thread in +// the browser process. +/// +/*--cef()--*/ +void CefRemoveWebPluginPath(const CefString& path); + +/// +// Unregister an internal plugin. This may be undone the next time +// CefRefreshWebPlugins() is called. Can be called on any thread in the browser +// process. +/// +/*--cef()--*/ +void CefUnregisterInternalWebPlugin(const CefString& path); + +/// +// Force a plugin to shutdown. Can be called on any thread in the browser +// process but will be executed on the IO thread. +/// +/*--cef()--*/ +void CefForceWebPluginShutdown(const CefString& path); + +/// +// Register a plugin crash. Can be called on any thread in the browser process +// but will be executed on the IO thread. +/// +/*--cef()--*/ +void CefRegisterWebPluginCrash(const CefString& path); + +/// +// Interface to implement for receiving unstable plugin information. The methods +// of this class will be called on the browser process IO thread. +/// +/*--cef(source=client)--*/ +class CefWebPluginUnstableCallback : public virtual CefBase { + public: + /// + // Method that will be called for the requested plugin. |unstable| will be + // true if the plugin has reached the crash count threshold of 3 times in 120 + // seconds. + /// + /*--cef()--*/ + virtual void IsUnstable(const CefString& path, + bool unstable) =0; +}; + +/// +// Query if a plugin is unstable. Can be called on any thread in the browser +// process. +/// +/*--cef()--*/ +void CefIsWebPluginUnstable(const CefString& path, + CefRefPtr callback); + + +#endif // CEF_INCLUDE_CEF_WEB_PLUGIN_H_ diff --git a/include/cef_xml_reader.h b/include/cef_xml_reader.h new file mode 100644 index 000000000..86be8bac7 --- /dev/null +++ b/include/cef_xml_reader.h @@ -0,0 +1,268 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_XML_READER_H_ +#define CEF_INCLUDE_CEF_XML_READER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_stream.h" + +/// +// Class that supports the reading of XML data via the libxml streaming API. +// The methods of this class should only be called on the thread that creates +// the object. +/// +/*--cef(source=library)--*/ +class CefXmlReader : public virtual CefBase { + public: + typedef cef_xml_encoding_type_t EncodingType; + typedef cef_xml_node_type_t NodeType; + + /// + // Create a new CefXmlReader object. The returned object's methods can only + // be called from the thread that created the object. + /// + /*--cef()--*/ + static CefRefPtr Create(CefRefPtr stream, + EncodingType encodingType, + const CefString& URI); + + /// + // Moves the cursor to the next node in the document. This method must be + // called at least once to set the current cursor position. Returns true if + // the cursor position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToNextNode() =0; + + /// + // Close the document. This should be called directly to ensure that cleanup + // occurs on the correct thread. + /// + /*--cef()--*/ + virtual bool Close() =0; + + /// + // Returns true if an error has been reported by the XML parser. + /// + /*--cef()--*/ + virtual bool HasError() =0; + + /// + // Returns the error string. + /// + /*--cef()--*/ + virtual CefString GetError() =0; + + + // The below methods retrieve data for the node at the current cursor + // position. + + /// + // Returns the node type. + /// + /*--cef(default_retval=XML_NODE_UNSUPPORTED)--*/ + virtual NodeType GetType() =0; + + /// + // Returns the node depth. Depth starts at 0 for the root node. + /// + /*--cef()--*/ + virtual int GetDepth() =0; + + /// + // Returns the local name. See + // http://www.w3.org/TR/REC-xml-names/#NT-LocalPart for additional details. + /// + /*--cef()--*/ + virtual CefString GetLocalName() =0; + + /// + // Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for + // additional details. + /// + /*--cef()--*/ + virtual CefString GetPrefix() =0; + + /// + // Returns the qualified name, equal to (Prefix:)LocalName. See + // http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details. + /// + /*--cef()--*/ + virtual CefString GetQualifiedName() =0; + + /// + // Returns the URI defining the namespace associated with the node. See + // http://www.w3.org/TR/REC-xml-names/ for additional details. + /// + /*--cef()--*/ + virtual CefString GetNamespaceURI() =0; + + /// + // Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for + // additional details. + /// + /*--cef()--*/ + virtual CefString GetBaseURI() =0; + + /// + // Returns the xml:lang scope within which the node resides. See + // http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details. + /// + /*--cef()--*/ + virtual CefString GetXmlLang() =0; + + /// + // Returns true if the node represents an empty element. is considered + // empty but is not. + /// + /*--cef()--*/ + virtual bool IsEmptyElement() =0; + + /// + // Returns true if the node has a text value. + /// + /*--cef()--*/ + virtual bool HasValue() =0; + + /// + // Returns the text value. + /// + /*--cef()--*/ + virtual CefString GetValue() =0; + + /// + // Returns true if the node has attributes. + /// + /*--cef()--*/ + virtual bool HasAttributes() =0; + + /// + // Returns the number of attributes. + /// + /*--cef()--*/ + virtual size_t GetAttributeCount() =0; + + /// + // Returns the value of the attribute at the specified 0-based index. + /// + /*--cef(capi_name=get_attribute_byindex,index_param=index)--*/ + virtual CefString GetAttribute(int index) =0; + + /// + // Returns the value of the attribute with the specified qualified name. + /// + /*--cef(capi_name=get_attribute_byqname)--*/ + virtual CefString GetAttribute(const CefString& qualifiedName) =0; + + /// + // Returns the value of the attribute with the specified local name and + // namespace URI. + /// + /*--cef(capi_name=get_attribute_bylname)--*/ + virtual CefString GetAttribute(const CefString& localName, + const CefString& namespaceURI) =0; + + /// + // Returns an XML representation of the current node's children. + /// + /*--cef()--*/ + virtual CefString GetInnerXml() =0; + + /// + // Returns an XML representation of the current node including its children. + /// + /*--cef()--*/ + virtual CefString GetOuterXml() =0; + + /// + // Returns the line number for the current node. + /// + /*--cef()--*/ + virtual int GetLineNumber() =0; + + + // Attribute nodes are not traversed by default. The below methods can be + // used to move the cursor to an attribute node. MoveToCarryingElement() can + // be called afterwards to return the cursor to the carrying element. The + // depth of an attribute node will be 1 + the depth of the carrying element. + + /// + // Moves the cursor to the attribute at the specified 0-based index. Returns + // true if the cursor position was set successfully. + /// + /*--cef(capi_name=move_to_attribute_byindex,index_param=index)--*/ + virtual bool MoveToAttribute(int index) =0; + + /// + // Moves the cursor to the attribute with the specified qualified name. + // Returns true if the cursor position was set successfully. + /// + /*--cef(capi_name=move_to_attribute_byqname)--*/ + virtual bool MoveToAttribute(const CefString& qualifiedName) =0; + + /// + // Moves the cursor to the attribute with the specified local name and + // namespace URI. Returns true if the cursor position was set successfully. + /// + /*--cef(capi_name=move_to_attribute_bylname)--*/ + virtual bool MoveToAttribute(const CefString& localName, + const CefString& namespaceURI) =0; + + /// + // Moves the cursor to the first attribute in the current element. Returns + // true if the cursor position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToFirstAttribute() =0; + + /// + // Moves the cursor to the next attribute in the current element. Returns + // true if the cursor position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToNextAttribute() =0; + + /// + // Moves the cursor back to the carrying element. Returns true if the cursor + // position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToCarryingElement() =0; +}; + +#endif // CEF_INCLUDE_CEF_XML_READER_H_ diff --git a/include/cef_zip_reader.h b/include/cef_zip_reader.h new file mode 100644 index 000000000..1fe02b916 --- /dev/null +++ b/include/cef_zip_reader.h @@ -0,0 +1,141 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_ZIP_READER_H_ +#define CEF_INCLUDE_CEF_ZIP_READER_H_ + +#include "include/cef_base.h" +#include "include/cef_stream.h" + +/// +// Class that supports the reading of zip archives via the zlib unzip API. +// The methods of this class should only be called on the thread that creates +// the object. +/// +/*--cef(source=library)--*/ +class CefZipReader : public virtual CefBase { + public: + /// + // Create a new CefZipReader object. The returned object's methods can only + // be called from the thread that created the object. + /// + /*--cef()--*/ + static CefRefPtr Create(CefRefPtr stream); + + /// + // Moves the cursor to the first file in the archive. Returns true if the + // cursor position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToFirstFile() =0; + + /// + // Moves the cursor to the next file in the archive. Returns true if the + // cursor position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToNextFile() =0; + + /// + // Moves the cursor to the specified file in the archive. If |caseSensitive| + // is true then the search will be case sensitive. Returns true if the cursor + // position was set successfully. + /// + /*--cef()--*/ + virtual bool MoveToFile(const CefString& fileName, bool caseSensitive) =0; + + /// + // Closes the archive. This should be called directly to ensure that cleanup + // occurs on the correct thread. + /// + /*--cef()--*/ + virtual bool Close() =0; + + + // The below methods act on the file at the current cursor position. + + /// + // Returns the name of the file. + /// + /*--cef()--*/ + virtual CefString GetFileName() =0; + + /// + // Returns the uncompressed size of the file. + /// + /*--cef()--*/ + virtual int64 GetFileSize() =0; + + /// + // Returns the last modified timestamp for the file. + /// + /*--cef()--*/ + virtual time_t GetFileLastModified() =0; + + /// + // Opens the file for reading of uncompressed data. A read password may + // optionally be specified. + /// + /*--cef(optional_param=password)--*/ + virtual bool OpenFile(const CefString& password) =0; + + /// + // Closes the file. + /// + /*--cef()--*/ + virtual bool CloseFile() =0; + + /// + // Read uncompressed file contents into the specified buffer. Returns < 0 if + // an error occurred, 0 if at the end of file, or the number of bytes read. + /// + /*--cef()--*/ + virtual int ReadFile(void* buffer, size_t bufferSize) =0; + + /// + // Returns the current offset in the uncompressed file contents. + /// + /*--cef()--*/ + virtual int64 Tell() =0; + + /// + // Returns true if at end of the file contents. + /// + /*--cef()--*/ + virtual bool Eof() =0; +}; + +#endif // CEF_INCLUDE_CEF_ZIP_READER_H_ diff --git a/include/internal/cef_export.h b/include/internal/cef_export.h new file mode 100644 index 000000000..2813253b6 --- /dev/null +++ b/include/internal/cef_export.h @@ -0,0 +1,55 @@ +// Copyright (c) 2009 The Chromium Embedded Framework Authors. 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_INTERNAL_CEF_EXPORT_H_ +#define CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_ +#pragma once + +#include "include/base/cef_build.h" + +#if defined(COMPILER_MSVC) + +#ifdef BUILDING_CEF_SHARED +#define CEF_EXPORT __declspec(dllexport) +#elif USING_CEF_SHARED +#define CEF_EXPORT __declspec(dllimport) +#else +#define CEF_EXPORT +#endif +#define CEF_CALLBACK __stdcall + +#elif defined(COMPILER_GCC) + +#define CEF_EXPORT __attribute__ ((visibility("default"))) +#define CEF_CALLBACK + +#endif // COMPILER_GCC + +#endif // CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_ diff --git a/include/internal/cef_linux.h b/include/internal/cef_linux.h new file mode 100644 index 000000000..6238397a3 --- /dev/null +++ b/include/internal/cef_linux.h @@ -0,0 +1,130 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. 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_INTERNAL_CEF_LINUX_H_ +#define CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ +#pragma once + +#include "include/internal/cef_types_linux.h" +#include "include/internal/cef_types_wrappers.h" + +// Handle types. +#define CefCursorHandle cef_cursor_handle_t +#define CefEventHandle cef_event_handle_t +#define CefWindowHandle cef_window_handle_t +#define CefTextInputContext cef_text_input_context_t + +struct CefMainArgsTraits { + typedef cef_main_args_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->argc = src->argc; + target->argv = src->argv; + } +}; + +// Class representing CefExecuteProcess arguments. +class CefMainArgs : public CefStructBase { + public: + typedef CefStructBase parent; + + CefMainArgs() : parent() {} + explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {} + explicit CefMainArgs(const CefMainArgs& r) : parent(r) {} + CefMainArgs(int argc_arg, char** argv_arg) : parent() { + argc = argc_arg; + argv = argv_arg; + } +}; + +struct CefWindowInfoTraits { + typedef cef_window_info_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->x = src->x; + target->y = src->y; + target->width = src->width; + target->height = src->height; + target->parent_window = src->parent_window; + target->windowless_rendering_enabled = src->windowless_rendering_enabled; + target->transparent_painting_enabled = src->transparent_painting_enabled; + target->window = src->window; + } +}; + +// Class representing window information. +class CefWindowInfo : public CefStructBase { + public: + typedef CefStructBase parent; + + CefWindowInfo() : parent() {} + explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} + explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + + /// + // Create the browser as a child window. + /// + void SetAsChild(CefWindowHandle parent, + const CefRect& windowRect) { + parent_window = parent; + x = windowRect.x; + y = windowRect.y; + width = windowRect.width; + height = windowRect.height; + } + + /// + // Create the browser using windowless (off-screen) rendering. No window + // will be created for the browser and all rendering will occur via the + // CefRenderHandler interface. The |parent| value will be used to identify + // monitor info and to act as the parent window for dialogs, context menus, + // etc. If |parent| is not provided then the main screen monitor will be used + // and some functionality that requires a parent window may not function + // correctly. If |transparent| is true a transparent background color will be + // used (RGBA=0x00000000). If |transparent| is false the background will be + // white and opaque. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + void SetAsWindowless(CefWindowHandle parent, bool transparent) { + windowless_rendering_enabled = true; + parent_window = parent; + transparent_painting_enabled = transparent; + } +}; + +#endif // CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ diff --git a/include/internal/cef_logging_internal.h b/include/internal/cef_logging_internal.h new file mode 100644 index 000000000..c376d0526 --- /dev/null +++ b/include/internal/cef_logging_internal.h @@ -0,0 +1,66 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_LOGGING_INTERNAL_H_ +#define CEF_INCLUDE_INTERNAL_CEF_LOGGING_INTERNAL_H_ +#pragma once + +#include "include/internal/cef_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// See include/base/cef_logging.h for macros and intended usage. + +/// +// Gets the current log level. +/// +CEF_EXPORT int cef_get_min_log_level(); + +/// +// Gets the current vlog level for the given file (usually taken from +// __FILE__). Note that |N| is the size *with* the null terminator. +/// +CEF_EXPORT int cef_get_vlog_level(const char* file_start, size_t N); + +/// +// Add a log message. See the LogSeverity defines for supported |severity| +// values. +/// +CEF_EXPORT void cef_log(const char* file, + int line, + int severity, + const char* message); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // CEF_INCLUDE_INTERNAL_CEF_LOGGING_INTERNAL_H_ diff --git a/include/internal/cef_mac.h b/include/internal/cef_mac.h new file mode 100644 index 000000000..8defbfb09 --- /dev/null +++ b/include/internal/cef_mac.h @@ -0,0 +1,137 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. 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_INTERNAL_CEF_MAC_H_ +#define CEF_INCLUDE_INTERNAL_CEF_MAC_H_ +#pragma once + +#include "include/internal/cef_types_mac.h" +#include "include/internal/cef_types_wrappers.h" + +// Handle types. +#define CefCursorHandle cef_cursor_handle_t +#define CefEventHandle cef_event_handle_t +#define CefWindowHandle cef_window_handle_t +#define CefTextInputContext cef_text_input_context_t + +struct CefMainArgsTraits { + typedef cef_main_args_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->argc = src->argc; + target->argv = src->argv; + } +}; + +// Class representing CefExecuteProcess arguments. +class CefMainArgs : public CefStructBase { + public: + typedef CefStructBase parent; + + CefMainArgs() : parent() {} + explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {} + explicit CefMainArgs(const CefMainArgs& r) : parent(r) {} + CefMainArgs(int argc, char** argv) : parent() { + this->argc = argc; + this->argv = argv; + } +}; + +struct CefWindowInfoTraits { + typedef cef_window_info_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) { + cef_string_clear(&s->window_name); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + cef_string_set(src->window_name.str, src->window_name.length, + &target->window_name, copy); + target->x = src->x; + target->y = src->y; + target->width = src->width; + target->height = src->height; + target->hidden = src->hidden; + target->parent_view = src->parent_view; + target->windowless_rendering_enabled = src->windowless_rendering_enabled; + target->transparent_painting_enabled = src->transparent_painting_enabled; + target->view = src->view; + } +}; + +// Class representing window information. +class CefWindowInfo : public CefStructBase { + public: + typedef CefStructBase parent; + + CefWindowInfo() : parent() {} + explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} + explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + + /// + // Create the browser as a child view. + /// + void SetAsChild(CefWindowHandle parent, int x, int y, int width, + int height) { + parent_view = parent; + this->x = x; + this->y = y; + this->width = width; + this->height = height; + hidden = false; + } + + /// + // Create the browser using windowless (off-screen) rendering. No view + // will be created for the browser and all rendering will occur via the + // CefRenderHandler interface. The |parent| value will be used to identify + // monitor info and to act as the parent view for dialogs, context menus, + // etc. If |parent| is not provided then the main screen monitor will be used + // and some functionality that requires a parent view may not function + // correctly. If |transparent| is true a transparent background color will be + // used (RGBA=0x00000000). If |transparent| is false the background will be + // white and opaque. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + void SetAsWindowless(CefWindowHandle parent, bool transparent) { + windowless_rendering_enabled = true; + parent_view = parent; + transparent_painting_enabled = transparent; + } +}; + +#endif // CEF_INCLUDE_INTERNAL_CEF_MAC_H_ diff --git a/include/internal/cef_ptr.h b/include/internal/cef_ptr.h new file mode 100644 index 000000000..e38543911 --- /dev/null +++ b/include/internal/cef_ptr.h @@ -0,0 +1,161 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_PTR_H_ +#define CEF_INCLUDE_INTERNAL_CEF_PTR_H_ +#pragma once + +#include "include/base/cef_ref_counted.h" + +/// +// Smart pointer implementation that is an alias of scoped_refptr from +// include/base/cef_ref_counted.h. +//

+// A smart pointer class for reference counted objects. Use this class instead +// of calling AddRef and Release manually on a reference counted object to +// avoid common memory leaks caused by forgetting to Release an object +// reference. Sample usage: +//

+//   class MyFoo : public CefBase {
+//    ...
+//   };
+//
+//   void some_function() {
+//     // The MyFoo object that |foo| represents starts with a single
+//     // reference.
+//     CefRefPtr<MyFoo> foo = new MyFoo();
+//     foo->Method(param);
+//     // |foo| is released when this function returns
+//   }
+//
+//   void some_other_function() {
+//     CefRefPtr<MyFoo> foo = new MyFoo();
+//     ...
+//     foo = NULL;  // explicitly releases |foo|
+//     ...
+//     if (foo)
+//       foo->Method(param);
+//   }
+// 
+// The above examples show how CefRefPtr<T> acts like a pointer to T. +// Given two CefRefPtr<T> classes, it is also possible to exchange +// references between the two objects, like so: +//
+//   {
+//     CefRefPtr<MyFoo> a = new MyFoo();
+//     CefRefPtr<MyFoo> b;
+//
+//     b.swap(a);
+//     // now, |b| references the MyFoo object, and |a| references NULL.
+//   }
+// 
+// To make both |a| and |b| in the above example reference the same MyFoo +// object, simply use the assignment operator: +//
+//   {
+//     CefRefPtr<MyFoo> a = new MyFoo();
+//     CefRefPtr<MyFoo> b;
+//
+//     b = a;
+//     // now, |a| and |b| each own a reference to the same MyFoo object.
+//     // the reference count of the underlying MyFoo object will be 2.
+//   }
+// 
+// Reference counted objects can also be passed as function parameters and +// used as function return values: +//
+//   void some_func_with_param(CefRefPtr<MyFoo> param) {
+//     // A reference is added to the MyFoo object that |param| represents
+//     // during the scope of some_func_with_param() and released when
+//     // some_func_with_param() goes out of scope.
+//   }
+//
+//   CefRefPtr<MyFoo> some_func_with_retval() {
+//     // The MyFoo object that |foox| represents starts with a single
+//     // reference.
+//     CefRefPtr<MyFoo> foox = new MyFoo();
+//
+//     // Creating the return value adds an additional reference.
+//     return foox;
+//
+//     // When some_func_with_retval() goes out of scope the original |foox|
+//     // reference is released.
+//   }
+//
+//   void and_another_function() {
+//     CefRefPtr<MyFoo> foo = new MyFoo();
+//
+//     // pass |foo| as a parameter.
+//     some_function(foo);
+//
+//     CefRefPtr<MyFoo> foo2 = some_func_with_retval();
+//     // Now, since we kept a reference to the some_func_with_retval() return
+//     // value, |foo2| is the only class pointing to the MyFoo object created
+//     in some_func_with_retval(), and it has a reference count of 1.
+//
+//     some_func_with_retval();
+//     // Now, since we didn't keep a reference to the some_func_with_retval()
+//     // return value, the MyFoo object created in some_func_with_retval()
+//     // will automatically be released.
+//   }
+// 
+// And in standard containers: +//
+//   {
+//      // Create a vector that holds MyFoo objects.
+//      std::vector<CefRefPtr<MyFoo> > MyFooVec;
+//
+//     // The MyFoo object that |foo| represents starts with a single
+//     // reference.
+//     CefRefPtr<MyFoo> foo = new MyFoo();
+//
+//     // When the MyFoo object is added to |MyFooVec| the reference count
+//     // is increased to 2.
+//     MyFooVec.push_back(foo);
+//   }
+// 
+//

+/// +template +class CefRefPtr : public scoped_refptr { + public: + typedef scoped_refptr parent; + + CefRefPtr() : parent() {} + + CefRefPtr(T* p) : parent(p) {} + + CefRefPtr(const scoped_refptr& r) : parent(r) {} + + template + CefRefPtr(const scoped_refptr& r) : parent(r) {} +}; + +#endif // CEF_INCLUDE_INTERNAL_CEF_PTR_H_ diff --git a/include/internal/cef_string.h b/include/internal/cef_string.h new file mode 100644 index 000000000..a7876fe56 --- /dev/null +++ b/include/internal/cef_string.h @@ -0,0 +1,113 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_H_ +#pragma once + +// The CEF interface is built with one string type as the default. Comment out +// all but one of the CEF_STRING_TYPE_* defines below to specify the default. +// If you change the default you MUST recompile all of CEF. + +// Build with the UTF8 string type as default. +// #define CEF_STRING_TYPE_UTF8 1 + +// Build with the UTF16 string type as default. +#define CEF_STRING_TYPE_UTF16 1 + +// Build with the wide string type as default. +// #define CEF_STRING_TYPE_WIDE 1 + + +#include "include/internal/cef_string_types.h" + +#ifdef __cplusplus +#include "include/internal/cef_string_wrappers.h" +#if defined(CEF_STRING_TYPE_UTF16) +typedef CefStringUTF16 CefString; +#elif defined(CEF_STRING_TYPE_UTF8) +typedef CefStringUTF8 CefString; +#elif defined(CEF_STRING_TYPE_WIDE) +typedef CefStringWide CefString; +#endif +#endif // __cplusplus + +#if defined(CEF_STRING_TYPE_UTF8) +typedef char cef_char_t; +typedef cef_string_utf8_t cef_string_t; +typedef cef_string_userfree_utf8_t cef_string_userfree_t; +#define cef_string_set cef_string_utf8_set +#define cef_string_copy cef_string_utf8_copy +#define cef_string_clear cef_string_utf8_clear +#define cef_string_userfree_alloc cef_string_userfree_utf8_alloc +#define cef_string_userfree_free cef_string_userfree_utf8_free +#define cef_string_from_ascii cef_string_utf8_copy +#define cef_string_to_utf8 cef_string_utf8_copy +#define cef_string_from_utf8 cef_string_utf8_copy +#define cef_string_to_utf16 cef_string_utf8_to_utf16 +#define cef_string_from_utf16 cef_string_utf16_to_utf8 +#define cef_string_to_wide cef_string_utf8_to_wide +#define cef_string_from_wide cef_string_wide_to_utf8 +#elif defined(CEF_STRING_TYPE_UTF16) +typedef char16 cef_char_t; +typedef cef_string_userfree_utf16_t cef_string_userfree_t; +typedef cef_string_utf16_t cef_string_t; +#define cef_string_set cef_string_utf16_set +#define cef_string_copy cef_string_utf16_copy +#define cef_string_clear cef_string_utf16_clear +#define cef_string_userfree_alloc cef_string_userfree_utf16_alloc +#define cef_string_userfree_free cef_string_userfree_utf16_free +#define cef_string_from_ascii cef_string_ascii_to_utf16 +#define cef_string_to_utf8 cef_string_utf16_to_utf8 +#define cef_string_from_utf8 cef_string_utf8_to_utf16 +#define cef_string_to_utf16 cef_string_utf16_copy +#define cef_string_from_utf16 cef_string_utf16_copy +#define cef_string_to_wide cef_string_utf16_to_wide +#define cef_string_from_wide cef_string_wide_to_utf16 +#elif defined(CEF_STRING_TYPE_WIDE) +typedef wchar_t cef_char_t; +typedef cef_string_wide_t cef_string_t; +typedef cef_string_userfree_wide_t cef_string_userfree_t; +#define cef_string_set cef_string_wide_set +#define cef_string_copy cef_string_wide_copy +#define cef_string_clear cef_string_wide_clear +#define cef_string_userfree_alloc cef_string_userfree_wide_alloc +#define cef_string_userfree_free cef_string_userfree_wide_free +#define cef_string_from_ascii cef_string_ascii_to_wide +#define cef_string_to_utf8 cef_string_wide_to_utf8 +#define cef_string_from_utf8 cef_string_utf8_to_wide +#define cef_string_to_utf16 cef_string_wide_to_utf16 +#define cef_string_from_utf16 cef_string_utf16_to_wide +#define cef_string_to_wide cef_string_wide_copy +#define cef_string_from_wide cef_string_wide_copy +#else +#error Please choose a string type. +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_H_ diff --git a/include/internal/cef_string_list.h b/include/internal/cef_string_list.h new file mode 100644 index 000000000..52a0abf2f --- /dev/null +++ b/include/internal/cef_string_list.h @@ -0,0 +1,88 @@ +// Copyright (c) 2009 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_LIST_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_LIST_H_ +#pragma once + +#include "include/internal/cef_export.h" +#include "include/internal/cef_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// CEF string maps are a set of key/value string pairs. +/// +typedef void* cef_string_list_t; + +/// +// Allocate a new string map. +/// +CEF_EXPORT cef_string_list_t cef_string_list_alloc(); + +/// +// Return the number of elements in the string list. +/// +CEF_EXPORT int cef_string_list_size(cef_string_list_t list); + +/// +// Retrieve the value at the specified zero-based string list index. Returns +// true (1) if the value was successfully retrieved. +/// +CEF_EXPORT int cef_string_list_value(cef_string_list_t list, + int index, cef_string_t* value); + +/// +// Append a new value at the end of the string list. +/// +CEF_EXPORT void cef_string_list_append(cef_string_list_t list, + const cef_string_t* value); + +/// +// Clear the string list. +/// +CEF_EXPORT void cef_string_list_clear(cef_string_list_t list); + +/// +// Free the string list. +/// +CEF_EXPORT void cef_string_list_free(cef_string_list_t list); + +/// +// Creates a copy of an existing string list. +/// +CEF_EXPORT cef_string_list_t cef_string_list_copy(cef_string_list_t list); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_LIST_H_ diff --git a/include/internal/cef_string_map.h b/include/internal/cef_string_map.h new file mode 100644 index 000000000..93eea2a55 --- /dev/null +++ b/include/internal/cef_string_map.h @@ -0,0 +1,97 @@ +// Copyright (c) 2009 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_MAP_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_MAP_H_ +#pragma once + +#include "include/internal/cef_export.h" +#include "include/internal/cef_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// CEF string maps are a set of key/value string pairs. +/// +typedef void* cef_string_map_t; + +/// +// Allocate a new string map. +/// +CEF_EXPORT cef_string_map_t cef_string_map_alloc(); + +/// +// Return the number of elements in the string map. +/// +CEF_EXPORT int cef_string_map_size(cef_string_map_t map); + +/// +// Return the value assigned to the specified key. +/// +CEF_EXPORT int cef_string_map_find(cef_string_map_t map, + const cef_string_t* key, + cef_string_t* value); + +/// +// Return the key at the specified zero-based string map index. +/// +CEF_EXPORT int cef_string_map_key(cef_string_map_t map, int index, + cef_string_t* key); + +/// +// Return the value at the specified zero-based string map index. +/// +CEF_EXPORT int cef_string_map_value(cef_string_map_t map, int index, + cef_string_t* value); + +/// +// Append a new key/value pair at the end of the string map. +/// +CEF_EXPORT int cef_string_map_append(cef_string_map_t map, + const cef_string_t* key, + const cef_string_t* value); + +/// +// Clear the string map. +/// +CEF_EXPORT void cef_string_map_clear(cef_string_map_t map); + +/// +// Free the string map. +/// +CEF_EXPORT void cef_string_map_free(cef_string_map_t map); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_MAP_H_ diff --git a/include/internal/cef_string_multimap.h b/include/internal/cef_string_multimap.h new file mode 100644 index 000000000..cd3904244 --- /dev/null +++ b/include/internal/cef_string_multimap.h @@ -0,0 +1,105 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_MULTIMAP_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_MULTIMAP_H_ +#pragma once + +#include "include/internal/cef_export.h" +#include "include/internal/cef_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// CEF string multimaps are a set of key/value string pairs. +// More than one value can be assigned to a single key. +/// +typedef void* cef_string_multimap_t; + +/// +// Allocate a new string multimap. +/// +CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc(); + +/// +// Return the number of elements in the string multimap. +/// +CEF_EXPORT int cef_string_multimap_size(cef_string_multimap_t map); + +/// +// Return the number of values with the specified key. +/// +CEF_EXPORT int cef_string_multimap_find_count(cef_string_multimap_t map, + const cef_string_t* key); + +/// +// Return the value_index-th value with the specified key. +/// +CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map, + const cef_string_t* key, + int value_index, + cef_string_t* value); + +/// +// Return the key at the specified zero-based string multimap index. +/// +CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map, int index, + cef_string_t* key); + +/// +// Return the value at the specified zero-based string multimap index. +/// +CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map, int index, + cef_string_t* value); + +/// +// Append a new key/value pair at the end of the string multimap. +/// +CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map, + const cef_string_t* key, + const cef_string_t* value); + +/// +// Clear the string multimap. +/// +CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map); + +/// +// Free the string multimap. +/// +CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_MULTIMAP_H_ diff --git a/include/internal/cef_string_types.h b/include/internal/cef_string_types.h new file mode 100644 index 000000000..493dc7e65 --- /dev/null +++ b/include/internal/cef_string_types.h @@ -0,0 +1,205 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_TYPES_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_ +#pragma once + +// CEF provides functions for converting between UTF-8, -16 and -32 strings. +// CEF string types are safe for reading from multiple threads but not for +// modification. It is the user's responsibility to provide synchronization if +// modifying CEF strings from multiple threads. + +#include + +#include "include/base/cef_build.h" +#include "include/internal/cef_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// CEF character type definitions. wchar_t is 2 bytes on Windows and 4 bytes on +// most other platforms. + +#if defined(OS_WIN) +typedef wchar_t char16; +#else // !OS_WIN +typedef unsigned short char16; // NOLINT (runtime/int) +#ifndef WCHAR_T_IS_UTF32 +#define WCHAR_T_IS_UTF32 +#endif // WCHAR_T_IS_UTF32 +#endif // !OS_WIN + + +// CEF string type definitions. Whomever allocates |str| is responsible for +// providing an appropriate |dtor| implementation that will free the string in +// the same memory space. When reusing an existing string structure make sure +// to call |dtor| for the old value before assigning new |str| and |dtor| +// values. Static strings will have a NULL |dtor| value. Using the below +// functions if you want this managed for you. + +typedef struct _cef_string_wide_t { + wchar_t* str; + size_t length; + void (*dtor)(wchar_t* str); +} cef_string_wide_t; + +typedef struct _cef_string_utf8_t { + char* str; + size_t length; + void (*dtor)(char* str); +} cef_string_utf8_t; + +typedef struct _cef_string_utf16_t { + char16* str; + size_t length; + void (*dtor)(char16* str); +} cef_string_utf16_t; + + +/// +// These functions set string values. If |copy| is true (1) the value will be +// copied instead of referenced. It is up to the user to properly manage +// the lifespan of references. +/// + +CEF_EXPORT int cef_string_wide_set(const wchar_t* src, size_t src_len, + cef_string_wide_t* output, int copy); +CEF_EXPORT int cef_string_utf8_set(const char* src, size_t src_len, + cef_string_utf8_t* output, int copy); +CEF_EXPORT int cef_string_utf16_set(const char16* src, size_t src_len, + cef_string_utf16_t* output, int copy); + + +/// +// Convenience macros for copying values. +/// + +#define cef_string_wide_copy(src, src_len, output) \ + cef_string_wide_set(src, src_len, output, true) +#define cef_string_utf8_copy(src, src_len, output) \ + cef_string_utf8_set(src, src_len, output, true) +#define cef_string_utf16_copy(src, src_len, output) \ + cef_string_utf16_set(src, src_len, output, true) + + +/// +// These functions clear string values. The structure itself is not freed. +/// + +CEF_EXPORT void cef_string_wide_clear(cef_string_wide_t* str); +CEF_EXPORT void cef_string_utf8_clear(cef_string_utf8_t* str); +CEF_EXPORT void cef_string_utf16_clear(cef_string_utf16_t* str); + + +/// +// These functions compare two string values with the same results as strcmp(). +/// + +CEF_EXPORT int cef_string_wide_cmp(const cef_string_wide_t* str1, + const cef_string_wide_t* str2); +CEF_EXPORT int cef_string_utf8_cmp(const cef_string_utf8_t* str1, + const cef_string_utf8_t* str2); +CEF_EXPORT int cef_string_utf16_cmp(const cef_string_utf16_t* str1, + const cef_string_utf16_t* str2); + + +/// +// These functions convert between UTF-8, -16, and -32 strings. They are +// potentially slow so unnecessary conversions should be avoided. The best +// possible result will always be written to |output| with the boolean return +// value indicating whether the conversion is 100% valid. +/// + +CEF_EXPORT int cef_string_wide_to_utf8(const wchar_t* src, size_t src_len, + cef_string_utf8_t* output); +CEF_EXPORT int cef_string_utf8_to_wide(const char* src, size_t src_len, + cef_string_wide_t* output); + +CEF_EXPORT int cef_string_wide_to_utf16(const wchar_t* src, size_t src_len, + cef_string_utf16_t* output); +CEF_EXPORT int cef_string_utf16_to_wide(const char16* src, size_t src_len, + cef_string_wide_t* output); + +CEF_EXPORT int cef_string_utf8_to_utf16(const char* src, size_t src_len, + cef_string_utf16_t* output); +CEF_EXPORT int cef_string_utf16_to_utf8(const char16* src, size_t src_len, + cef_string_utf8_t* output); + + +/// +// These functions convert an ASCII string, typically a hardcoded constant, to a +// Wide/UTF16 string. Use instead of the UTF8 conversion routines if you know +// the string is ASCII. +/// + +CEF_EXPORT int cef_string_ascii_to_wide(const char* src, size_t src_len, + cef_string_wide_t* output); +CEF_EXPORT int cef_string_ascii_to_utf16(const char* src, size_t src_len, + cef_string_utf16_t* output); + + + +/// +// It is sometimes necessary for the system to allocate string structures with +// the expectation that the user will free them. The userfree types act as a +// hint that the user is responsible for freeing the structure. +/// + +typedef cef_string_wide_t* cef_string_userfree_wide_t; +typedef cef_string_utf8_t* cef_string_userfree_utf8_t; +typedef cef_string_utf16_t* cef_string_userfree_utf16_t; + + +/// +// These functions allocate a new string structure. They must be freed by +// calling the associated free function. +/// + +CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc(); +CEF_EXPORT cef_string_userfree_utf8_t cef_string_userfree_utf8_alloc(); +CEF_EXPORT cef_string_userfree_utf16_t cef_string_userfree_utf16_alloc(); + + +/// +// These functions free the string structure allocated by the associated +// alloc function. Any string contents will first be cleared. +/// + +CEF_EXPORT void cef_string_userfree_wide_free(cef_string_userfree_wide_t str); +CEF_EXPORT void cef_string_userfree_utf8_free(cef_string_userfree_utf8_t str); +CEF_EXPORT void cef_string_userfree_utf16_free(cef_string_userfree_utf16_t str); + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_ diff --git a/include/internal/cef_string_wrappers.h b/include/internal/cef_string_wrappers.h new file mode 100644 index 000000000..060c3c89f --- /dev/null +++ b/include/internal/cef_string_wrappers.h @@ -0,0 +1,715 @@ +// Copyright (c) 2010 Marshall A. Greenblatt. 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_INTERNAL_CEF_STRING_WRAPPERS_H_ +#define CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ +#pragma once + +#include +#include + +#include "include/base/cef_string16.h" +#include "include/internal/cef_string_types.h" + +/// +// Traits implementation for wide character strings. +/// +struct CefStringTraitsWide { + typedef wchar_t char_type; + typedef cef_string_wide_t struct_type; + typedef cef_string_userfree_wide_t userfree_struct_type; + + static inline void clear(struct_type *s) { cef_string_wide_clear(s); } + static inline int set(const char_type* src, size_t src_size, + struct_type* output, int copy) { + return cef_string_wide_set(src, src_size, output, copy); + } + static inline int compare(const struct_type* s1, const struct_type* s2) { + return cef_string_wide_cmp(s1, s2); + } + static inline userfree_struct_type userfree_alloc() { + return cef_string_userfree_wide_alloc(); + } + static inline void userfree_free(userfree_struct_type ufs) { + return cef_string_userfree_wide_free(ufs); + } + + // Conversion methods. + static inline bool from_ascii(const char* str, size_t len, struct_type *s) { + return cef_string_ascii_to_wide(str, len, s) ? true : false; + } + static inline std::string to_string(const struct_type *s) { + cef_string_utf8_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_wide_to_utf8(s->str, s->length, &cstr); + std::string str; + if (cstr.length > 0) + str = std::string(cstr.str, cstr.length); + cef_string_utf8_clear(&cstr); + return str; + } + static inline bool from_string(const std::string& str, struct_type *s) { + return cef_string_utf8_to_wide(str.c_str(), str.length(), s) ? true : false; + } + static inline std::wstring to_wstring(const struct_type *s) { + return std::wstring(s->str, s->length); + } + static inline bool from_wstring(const std::wstring& str, struct_type *s) { + return cef_string_wide_set(str.c_str(), str.length(), s, true) ? + true : false; + } +#if defined(WCHAR_T_IS_UTF32) + static inline base::string16 to_string16(const struct_type *s) { + cef_string_utf16_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_wide_to_utf16(s->str, s->length, &cstr); + base::string16 str; + if (cstr.length > 0) + str = base::string16(cstr.str, cstr.length); + cef_string_utf16_clear(&cstr); + return str; + } + static inline bool from_string16(const base::string16& str, + struct_type *s) { + return cef_string_utf16_to_wide(str.c_str(), str.length(), s) ? + true : false; + } +#else // WCHAR_T_IS_UTF32 + static inline base::string16 to_string16(const struct_type *s) { + return base::string16(s->str, s->length); + } + static inline bool from_string16(const base::string16& str, struct_type *s) { + return cef_string_wide_set(str.c_str(), str.length(), s, true) ? + true : false; + } +#endif // WCHAR_T_IS_UTF32 +}; + +/// +// Traits implementation for utf8 character strings. +/// +struct CefStringTraitsUTF8 { + typedef char char_type; + typedef cef_string_utf8_t struct_type; + typedef cef_string_userfree_utf8_t userfree_struct_type; + + static inline void clear(struct_type *s) { cef_string_utf8_clear(s); } + static inline int set(const char_type* src, size_t src_size, + struct_type* output, int copy) { + return cef_string_utf8_set(src, src_size, output, copy); + } + static inline int compare(const struct_type* s1, const struct_type* s2) { + return cef_string_utf8_cmp(s1, s2); + } + static inline userfree_struct_type userfree_alloc() { + return cef_string_userfree_utf8_alloc(); + } + static inline void userfree_free(userfree_struct_type ufs) { + return cef_string_userfree_utf8_free(ufs); + } + + // Conversion methods. + static inline bool from_ascii(const char* str, size_t len, struct_type* s) { + return cef_string_utf8_copy(str, len, s) ? true : false; + } + static inline std::string to_string(const struct_type* s) { + return std::string(s->str, s->length); + } + static inline bool from_string(const std::string& str, struct_type* s) { + return cef_string_utf8_copy(str.c_str(), str.length(), s) ? true : false; + } + static inline std::wstring to_wstring(const struct_type* s) { + cef_string_wide_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_utf8_to_wide(s->str, s->length, &cstr); + std::wstring str; + if (cstr.length > 0) + str = std::wstring(cstr.str, cstr.length); + cef_string_wide_clear(&cstr); + return str; + } + static inline bool from_wstring(const std::wstring& str, struct_type* s) { + return cef_string_wide_to_utf8(str.c_str(), str.length(), s) ? true : false; + } + static inline base::string16 to_string16(const struct_type* s) { + cef_string_utf16_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_utf8_to_utf16(s->str, s->length, &cstr); + base::string16 str; + if (cstr.length > 0) + str = base::string16(cstr.str, cstr.length); + cef_string_utf16_clear(&cstr); + return str; + } + static inline bool from_string16(const base::string16& str, struct_type* s) { + return cef_string_utf16_to_utf8(str.c_str(), str.length(), s) ? + true : false; + } +}; + +/// +// Traits implementation for utf16 character strings. +/// +struct CefStringTraitsUTF16 { + typedef char16 char_type; + typedef cef_string_utf16_t struct_type; + typedef cef_string_userfree_utf16_t userfree_struct_type; + + static inline void clear(struct_type *s) { cef_string_utf16_clear(s); } + static inline int set(const char_type* src, size_t src_size, + struct_type* output, int copy) { + return cef_string_utf16_set(src, src_size, output, copy); + } + static inline int compare(const struct_type* s1, const struct_type* s2) { + return cef_string_utf16_cmp(s1, s2); + } + static inline userfree_struct_type userfree_alloc() { + return cef_string_userfree_utf16_alloc(); + } + static inline void userfree_free(userfree_struct_type ufs) { + return cef_string_userfree_utf16_free(ufs); + } + + // Conversion methods. + static inline bool from_ascii(const char* str, size_t len, struct_type* s) { + return cef_string_ascii_to_utf16(str, len, s) ? true : false; + } + static inline std::string to_string(const struct_type* s) { + cef_string_utf8_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_utf16_to_utf8(s->str, s->length, &cstr); + std::string str; + if (cstr.length > 0) + str = std::string(cstr.str, cstr.length); + cef_string_utf8_clear(&cstr); + return str; + } + static inline bool from_string(const std::string& str, struct_type* s) { + return cef_string_utf8_to_utf16(str.c_str(), str.length(), s) ? + true : false; + } +#if defined(WCHAR_T_IS_UTF32) + static inline std::wstring to_wstring(const struct_type* s) { + cef_string_wide_t cstr; + memset(&cstr, 0, sizeof(cstr)); + cef_string_utf16_to_wide(s->str, s->length, &cstr); + std::wstring str; + if (cstr.length > 0) + str = std::wstring(cstr.str, cstr.length); + cef_string_wide_clear(&cstr); + return str; + } + static inline bool from_wstring(const std::wstring& str, struct_type* s) { + return cef_string_wide_to_utf16(str.c_str(), str.length(), s) ? + true : false; + } +#else // WCHAR_T_IS_UTF32 + static inline std::wstring to_wstring(const struct_type* s) { + return std::wstring(s->str, s->length); + } + static inline bool from_wstring(const std::wstring& str, struct_type* s) { + return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? + true : false; + } +#endif // WCHAR_T_IS_UTF32 + static inline base::string16 to_string16(const struct_type* s) { + return base::string16(s->str, s->length); + } + static inline bool from_string16(const base::string16& str, struct_type* s) { + return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? + true : false; + } +}; + +/// +// CEF string classes can convert between all supported string types. For +// example, the CefStringWide class uses wchar_t as the underlying character +// type and provides two approaches for converting data to/from a UTF8 string +// (std::string). +//

+// 1. Implicit conversion using the assignment operator overload. +//

+//   CefStringWide aCefString;
+//   std::string aUTF8String;
+//   aCefString = aUTF8String; // Assign std::string to CefStringWide
+//   aUTF8String = aCefString; // Assign CefStringWide to std::string
+// 
+// 2. Explicit conversion using the FromString/ToString methods. +//
+//   CefStringWide aCefString;
+//   std::string aUTF8String;
+//   aCefString.FromString(aUTF8String); // Assign std::string to CefStringWide
+//   aUTF8String = aCefString.ToString(); // Assign CefStringWide to std::string
+// 
+// Conversion will only occur if the assigned value is a different string type. +// Assigning a std::string to a CefStringUTF8, for example, will copy the data +// without performing a conversion. +//

+// CEF string classes are safe for reading from multiple threads but not for +// modification. It is the user's responsibility to provide synchronization if +// modifying CEF strings from multiple threads. +/// +template +class CefStringBase { + public: + typedef typename traits::char_type char_type; + typedef typename traits::struct_type struct_type; + typedef typename traits::userfree_struct_type userfree_struct_type; + + /// + // Default constructor. + /// + CefStringBase() : string_(NULL), owner_(false) {} + + /// + // Create a new string from an existing string. Data will always be copied. + /// + CefStringBase(const CefStringBase& str) + : string_(NULL), owner_(false) { + FromString(str.c_str(), str.length(), true); + } + + /// + // Create a new string from an existing std::string. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + CefStringBase(const std::string& src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + FromString(src); + } + CefStringBase(const char* src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + if (src) + FromString(std::string(src)); + } + + /// + // Create a new string from an existing std::wstring. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + CefStringBase(const std::wstring& src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + FromWString(src); + } + CefStringBase(const wchar_t* src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + if (src) + FromWString(std::wstring(src)); + } + +#if defined(WCHAR_T_IS_UTF32) + /// + // Create a new string from an existing string16. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + CefStringBase(const base::string16& src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + FromString16(src); + } + CefStringBase(const char16* src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + if (src) + FromString16(base::string16(src)); + } +#endif // WCHAR_T_IS_UTF32 + + /// + // Create a new string from an existing character array. If |copy| is true + // this class will copy the data. Otherwise, this class will reference the + // existing data. Referenced data must exist for the lifetime of this class + // and will not be freed by this class. + /// + CefStringBase(const char_type* src, size_t src_len, bool copy) + : string_(NULL), owner_(false) { + if (src && src_len > 0) + FromString(src, src_len, copy); + } + + /// + // Create a new string referencing an existing string structure without taking + // ownership. Referenced structures must exist for the lifetime of this class + // and will not be freed by this class. + /// + CefStringBase(const struct_type* src) // NOLINT(runtime/explicit) + : string_(NULL), owner_(false) { + if (!src) + return; + // Reference the existing structure without taking ownership. + Attach(const_cast(src), false); + } + + virtual ~CefStringBase() { ClearAndFree(); } + + + // The following methods are named for compatibility with the standard library + // string template types. + + /// + // Return a read-only pointer to the string data. + /// + const char_type* c_str() const { return (string_ ? string_->str : NULL); } + + /// + // Return the length of the string data. + /// + size_t length() const { return (string_ ? string_->length : 0); } + + /// + // Return the length of the string data. + /// + inline size_t size() const { return length(); } + + /// + // Returns true if the string is empty. + /// + bool empty() const { return (string_ == NULL || string_->length == 0); } + + /// + // Compare this string to the specified string. + /// + int compare(const CefStringBase& str) const { + if (empty() && str.empty()) + return 0; + if (empty()) + return -1; + if (str.empty()) + return 1; + return traits::compare(string_, str.GetStruct()); + } + + /// + // Clear the string data. + /// + void clear() { + if (string_) + traits::clear(string_); + } + + /// + // Swap this string's contents with the specified string. + /// + void swap(CefStringBase& str) { + struct_type* tmp_string = string_; + bool tmp_owner = owner_; + string_ = str.string_; + owner_ = str.owner_; + str.string_ = tmp_string; + str.owner_ = tmp_owner; + } + + + // The following methods are unique to CEF string template types. + + /// + // Returns true if this class owns the underlying string structure. + /// + bool IsOwner() const { return owner_; } + + /// + // Returns a read-only pointer to the underlying string structure. May return + // NULL if no structure is currently allocated. + /// + const struct_type* GetStruct() const { return string_; } + + /// + // Returns a writable pointer to the underlying string structure. Will never + // return NULL. + /// + struct_type* GetWritableStruct() { + AllocIfNeeded(); + return string_; + } + + /// + // Clear the state of this class. The underlying string structure and data + // will be freed if this class owns the structure. + /// + void ClearAndFree() { + if (!string_) + return; + if (owner_) { + clear(); + delete string_; + } + string_ = NULL; + owner_ = false; + } + + /// + // Attach to the specified string structure. If |owner| is true this class + // will take ownership of the structure. + /// + void Attach(struct_type* str, bool owner) { + // Free the previous structure and data, if any. + ClearAndFree(); + + string_ = str; + owner_ = owner; + } + + /// + // Take ownership of the specified userfree structure's string data. The + // userfree structure itself will be freed. Only use this method with userfree + // structures. + /// + void AttachToUserFree(userfree_struct_type str) { + // Free the previous structure and data, if any. + ClearAndFree(); + + if (!str) + return; + + AllocIfNeeded(); + owner_ = true; + memcpy(string_, str, sizeof(struct_type)); + + // Free the |str| structure but not the data. + memset(str, 0, sizeof(struct_type)); + traits::userfree_free(str); + } + + /// + // Detach from the underlying string structure. To avoid memory leaks only use + // this method if you already hold a pointer to the underlying string + // structure. + /// + void Detach() { + string_ = NULL; + owner_ = false; + } + + /// + // Create a userfree structure and give it ownership of this class' string + // data. This class will be disassociated from the data. May return NULL if + // this string class currently contains no data. + /// + userfree_struct_type DetachToUserFree() { + if (empty()) + return NULL; + + userfree_struct_type str = traits::userfree_alloc(); + memcpy(str, string_, sizeof(struct_type)); + + // Free this class' structure but not the data. + memset(string_, 0, sizeof(struct_type)); + ClearAndFree(); + + return str; + } + + /// + // Set this string's data to the specified character array. If |copy| is true + // this class will copy the data. Otherwise, this class will reference the + // existing data. Referenced data must exist for the lifetime of this class + // and will not be freed by this class. + /// + bool FromString(const char_type* src, size_t src_len, bool copy) { + if (src == NULL || src_len == 0) { + clear(); + return true; + } + AllocIfNeeded(); + return traits::set(src, src_len, string_, copy) ? true : false; + } + + /// + // Set this string's data from an existing ASCII string. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + bool FromASCII(const char* str) { + size_t len = str ? strlen(str) : 0; + if (len == 0) { + clear(); + return true; + } + AllocIfNeeded(); + return traits::from_ascii(str, len, string_); + } + + /// + // Return this string's data as a std::string. Translation will occur if + // necessary based on the underlying string type. + /// + std::string ToString() const { + if (empty()) + return std::string(); + return traits::to_string(string_); + } + + /// + // Set this string's data from an existing std::string. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + bool FromString(const std::string& str) { + if (str.empty()) { + clear(); + return true; + } + AllocIfNeeded(); + return traits::from_string(str, string_); + } + + /// + // Return this string's data as a std::wstring. Translation will occur if + // necessary based on the underlying string type. + /// + std::wstring ToWString() const { + if (empty()) + return std::wstring(); + return traits::to_wstring(string_); + } + + /// + // Set this string's data from an existing std::wstring. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + bool FromWString(const std::wstring& str) { + if (str.empty()) { + clear(); + return true; + } + AllocIfNeeded(); + return traits::from_wstring(str, string_); + } + + /// + // Return this string's data as a string16. Translation will occur if + // necessary based on the underlying string type. + /// + base::string16 ToString16() const { + if (empty()) + return base::string16(); + return traits::to_string16(string_); + } + + /// + // Set this string's data from an existing string16. Data will be always + // copied. Translation will occur if necessary based on the underlying string + // type. + /// + bool FromString16(const base::string16& str) { + if (str.empty()) { + clear(); + return true; + } + AllocIfNeeded(); + return traits::from_string16(str, string_); + } + + /// + // Comparison operator overloads. + /// + bool operator<(const CefStringBase& str) const { + return (compare(str) < 0); + } + bool operator<=(const CefStringBase& str) const { + return (compare(str) <= 0); + } + bool operator>(const CefStringBase& str) const { + return (compare(str) > 0); + } + bool operator>=(const CefStringBase& str) const { + return (compare(str) >= 0); + } + bool operator==(const CefStringBase& str) const { + return (compare(str) == 0); + } + bool operator!=(const CefStringBase& str) const { + return (compare(str) != 0); + } + + /// + // Assignment operator overloads. + /// + CefStringBase& operator=(const CefStringBase& str) { + FromString(str.c_str(), str.length(), true); + return *this; + } + operator std::string() const { + return ToString(); + } + CefStringBase& operator=(const std::string& str) { + FromString(str); + return *this; + } + CefStringBase& operator=(const char* str) { + FromString(std::string(str)); + return *this; + } + operator std::wstring() const { + return ToWString(); + } + CefStringBase& operator=(const std::wstring& str) { + FromWString(str); + return *this; + } + CefStringBase& operator=(const wchar_t* str) { + FromWString(std::wstring(str)); + return *this; + } +#if defined(WCHAR_T_IS_UTF32) + operator base::string16() const { + return ToString16(); + } + CefStringBase& operator=(const base::string16& str) { + FromString16(str); + return *this; + } + CefStringBase& operator=(const char16* str) { + FromString16(base::string16(str)); + return *this; + } +#endif // WCHAR_T_IS_UTF32 + + private: + // Allocate the string structure if it doesn't already exist. + void AllocIfNeeded() { + if (string_ == NULL) { + string_ = new struct_type; + memset(string_, 0, sizeof(struct_type)); + owner_ = true; + } + } + + struct_type* string_; + bool owner_; +}; + + +typedef CefStringBase CefStringWide; +typedef CefStringBase CefStringUTF8; +typedef CefStringBase CefStringUTF16; + +#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ diff --git a/include/internal/cef_thread_internal.h b/include/internal/cef_thread_internal.h new file mode 100644 index 000000000..eee2b2ae4 --- /dev/null +++ b/include/internal/cef_thread_internal.h @@ -0,0 +1,74 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_THREAD_INTERNAL_H_ +#define CEF_INCLUDE_INTERNAL_CEF_THREAD_INTERNAL_H_ +#pragma once + +#if defined(OS_WIN) +#include +#elif defined(OS_POSIX) +#include +#include +#endif + +#include "include/internal/cef_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(OS_WIN) +typedef DWORD cef_platform_thread_id_t; +#elif defined(OS_POSIX) +typedef pid_t cef_platform_thread_id_t; +#endif + +/// +// Returns the current platform thread ID. +/// +CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id(); + +#if defined(OS_WIN) +typedef DWORD cef_platform_thread_handle_t; +#elif defined(OS_POSIX) +typedef pthread_t cef_platform_thread_handle_t; +#endif + +/// +// Returns the current platform thread handle. +/// +CEF_EXPORT cef_platform_thread_handle_t + cef_get_current_platform_thread_handle(); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // CEF_INCLUDE_INTERNAL_CEF_THREAD_INTERNAL_H_ diff --git a/include/internal/cef_time.h b/include/internal/cef_time.h new file mode 100644 index 000000000..64e601fe0 --- /dev/null +++ b/include/internal/cef_time.h @@ -0,0 +1,88 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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_INTERNAL_CEF_TIME_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TIME_H_ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "include/internal/cef_export.h" +#include + +/// +// Time information. Values should always be in UTC. +/// +typedef struct _cef_time_t { + int year; // Four digit year "2007" + int month; // 1-based month (values 1 = January, etc.) + int day_of_week; // 0-based day of week (0 = Sunday, etc.) + int day_of_month; // 1-based day of month (1-31) + int hour; // Hour within the current day (0-23) + int minute; // Minute within the current hour (0-59) + int second; // Second within the current minute (0-59 plus leap + // seconds which may take it up to 60). + int millisecond; // Milliseconds within the current second (0-999) +} cef_time_t; + +/// +// Converts cef_time_t to/from time_t. Returns true (1) on success and false (0) +// on failure. +/// +CEF_EXPORT int cef_time_to_timet(const cef_time_t* cef_time, time_t* time); +CEF_EXPORT int cef_time_from_timet(time_t time, cef_time_t* cef_time); + +/// +// Converts cef_time_t to/from a double which is the number of seconds since +// epoch (Jan 1, 1970). Webkit uses this format to represent time. A value of 0 +// means "not initialized". Returns true (1) on success and false (0) on +// failure. +/// +CEF_EXPORT int cef_time_to_doublet(const cef_time_t* cef_time, double* time); +CEF_EXPORT int cef_time_from_doublet(double time, cef_time_t* cef_time); + +/// +// Retrieve the current system time. +// +CEF_EXPORT int cef_time_now(cef_time_t* cef_time); + +/// +// Retrieve the delta in milliseconds between two time values. +// +CEF_EXPORT int cef_time_delta(const cef_time_t* cef_time1, + const cef_time_t* cef_time2, + long long* delta); + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_TIME_H_ diff --git a/include/internal/cef_trace_event_internal.h b/include/internal/cef_trace_event_internal.h new file mode 100644 index 000000000..6df870717 --- /dev/null +++ b/include/internal/cef_trace_event_internal.h @@ -0,0 +1,124 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_TRACE_EVENT_INTERNAL_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TRACE_EVENT_INTERNAL_H_ +#pragma once + +#include "include/internal/cef_export.h" +#include "include/internal/cef_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// See include/base/cef_trace_event.h for macros and intended usage. + +// Functions for tracing counters and functions; called from macros. +// - |category| string must have application lifetime (static or literal). They +// may not include "(quotes) chars. +// - |argX_name|, |argX_val|, |valueX_name|, |valeX_val| are optional parameters +// and represent pairs of name and values of arguments +// - |copy| is used to avoid memory scoping issues with the |name| and +// |arg_name| parameters by copying them +// - |id| is used to disambiguate counters with the same name, or match async +// trace events + +CEF_EXPORT void cef_trace_event_instant(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy); +CEF_EXPORT void cef_trace_event_begin(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy); +CEF_EXPORT void cef_trace_event_end(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy); +CEF_EXPORT void cef_trace_counter(const char* category, + const char* name, + const char* value1_name, + uint64 value1_val, + const char* value2_name, + uint64 value2_val, + int copy); +CEF_EXPORT void cef_trace_counter_id(const char* category, + const char* name, + uint64 id, + const char* value1_name, + uint64 value1_val, + const char* value2_name, + uint64 value2_val, + int copy); +CEF_EXPORT void cef_trace_event_async_begin(const char* category, + const char* name, + uint64 id, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy); +CEF_EXPORT void cef_trace_event_async_step_into(const char* category, + const char* name, + uint64 id, + uint64 step, + const char* arg1_name, + uint64 arg1_val, + int copy); +CEF_EXPORT void cef_trace_event_async_step_past(const char* category, + const char* name, + uint64 id, + uint64 step, + const char* arg1_name, + uint64 arg1_val, + int copy); +CEF_EXPORT void cef_trace_event_async_end(const char* category, + const char* name, + uint64 id, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // CEF_INCLUDE_INTERNAL_CEF_TRACE_EVENT_INTERNAL_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h new file mode 100644 index 000000000..4f636eeaa --- /dev/null +++ b/include/internal/cef_types.h @@ -0,0 +1,1805 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_TYPES_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_H_ +#pragma once + +#include "include/base/cef_build.h" +#include "include/internal/cef_string.h" +#include "include/internal/cef_string_list.h" +#include "include/internal/cef_time.h" + +// Bring in platform-specific definitions. +#if defined(OS_WIN) +#include "include/internal/cef_types_win.h" +#elif defined(OS_MACOSX) +#include "include/internal/cef_types_mac.h" +#elif defined(OS_LINUX) +#include "include/internal/cef_types_linux.h" +#endif + +#include // For UINT_MAX +#include // For size_t + +// 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 +// 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 + +// UTF-16 character type +#ifndef char16 +#if defined(WIN32) +typedef wchar_t char16; +#else +typedef unsigned short char16; +#endif +#endif + +// 32-bit ARGB color value, not premultiplied. The color components are always +// in a known order. Equivalent to the SkColor type. +typedef uint32 cef_color_t; + +// Return the alpha byte from a cef_color_t value. +#define CefColorGetA(color) (((color) >> 24) & 0xFF) +// Return the red byte from a cef_color_t value. +#define CefColorGetR(color) (((color) >> 16) & 0xFF) +// Return the green byte from a cef_color_t value. +#define CefColorGetG(color) (((color) >> 8) & 0xFF) +// Return the blue byte from a cef_color_t value. +#define CefColorGetB(color) (((color) >> 0) & 0xFF) + +// Return an cef_color_t value with the specified byte component values. +#define CefColorSetARGB(a, r, g, b) \ + static_cast( \ + (static_cast(a) << 24) | \ + (static_cast(r) << 16) | \ + (static_cast(g) << 8) | \ + (static_cast(b) << 0)) + +// Return an int64 value with the specified low and high int32 component values. +#define CefInt64Set(int32_low, int32_high) \ + static_cast((static_cast(int32_low)) | \ + (static_cast(static_cast(int32_high))) << 32) + +// Return the low int32 value from an int64 value. +#define CefInt64GetLow(int64_val) static_cast(int64_val) +// Return the high int32 value from an int64 value. +#define CefInt64GetHigh(int64_val) \ + static_cast((static_cast(int64_val) >> 32) & 0xFFFFFFFFL) + + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// Log severity levels. +/// +typedef enum { + /// + // Default logging (currently INFO logging). + /// + LOGSEVERITY_DEFAULT, + + /// + // Verbose logging. + /// + LOGSEVERITY_VERBOSE, + + /// + // INFO logging. + /// + LOGSEVERITY_INFO, + + /// + // WARNING logging. + /// + LOGSEVERITY_WARNING, + + /// + // ERROR logging. + /// + LOGSEVERITY_ERROR, + + /// + // Completely disable logging. + /// + LOGSEVERITY_DISABLE = 99 +} cef_log_severity_t; + +/// +// Represents the state of a setting. +/// +typedef enum { + /// + // Use the default state for the setting. + /// + STATE_DEFAULT = 0, + + /// + // Enable or allow the setting. + /// + STATE_ENABLED, + + /// + // Disable or disallow the setting. + /// + STATE_DISABLED, +} cef_state_t; + +/// +// Initialization settings. Specify NULL or 0 to get the recommended default +// values. Many of these and other settings can also configured using command- +// line switches. +/// +typedef struct _cef_settings_t { + /// + // Size of this structure. + /// + size_t size; + + /// + // Set to true (1) to use a single process for the browser and renderer. This + // run mode is not officially supported by Chromium and is less stable than + // the multi-process default. Also configurable using the "single-process" + // command-line switch. + /// + int single_process; + + /// + // Set to true (1) to disable the sandbox for sub-processes. See + // cef_sandbox_win.h for requirements to enable the sandbox on Windows. Also + // configurable using the "no-sandbox" command-line switch. + /// + int no_sandbox; + + /// + // The path to a separate executable that will be launched for sub-processes. + // By default the browser process executable is used. See the comments on + // CefExecuteProcess() for details. Also configurable using the + // "browser-subprocess-path" command-line switch. + /// + cef_string_t browser_subprocess_path; + + /// + // Set to true (1) to have the browser process message loop run in a separate + // thread. If false (0) than the CefDoMessageLoopWork() function must be + // called from your application message loop. + /// + int multi_threaded_message_loop; + + /// + // Set to true (1) to enable windowless (off-screen) rendering support. Do not + // enable this value if the application does not use windowless rendering as + // it may reduce rendering performance on some systems. + /// + int windowless_rendering_enabled; + + /// + // Set to true (1) to disable configuration of browser process features using + // standard CEF and Chromium command-line arguments. Configuration can still + // be specified using CEF data structures or via the + // CefApp::OnBeforeCommandLineProcessing() method. + /// + int command_line_args_disabled; + + /// + // The location where cache data will be stored on disk. If empty an in-memory + // cache will be used for some features and a temporary disk cache for others. + // HTML5 databases such as localStorage will only persist across sessions if a + // cache path is specified. + /// + cef_string_t cache_path; + + /// + // To persist session cookies (cookies without an expiry date or validity + // interval) by default when using the global cookie manager set this value to + // true. Session cookies are generally intended to be transient and most Web + // browsers do not persist them. A |cache_path| value must also be specified to + // enable this feature. Also configurable using the "persist-session-cookies" + // command-line switch. + /// + int persist_session_cookies; + + /// + // Value that will be returned as the User-Agent HTTP header. If empty the + // default User-Agent string will be used. Also configurable using the + // "user-agent" command-line switch. + /// + cef_string_t user_agent; + + /// + // Value that will be inserted as the product portion of the default + // User-Agent string. If empty the Chromium product version will be used. If + // |userAgent| is specified this value will be ignored. Also configurable + // using the "product-version" command-line switch. + /// + cef_string_t product_version; + + /// + // The locale string that will be passed to WebKit. If empty the default + // locale of "en-US" will be used. This value is ignored on Linux where locale + // is determined using environment variable parsing with the precedence order: + // LANGUAGE, LC_ALL, LC_MESSAGES and LANG. Also configurable using the "lang" + // command-line switch. + /// + cef_string_t locale; + + /// + // The directory and file name to use for the debug log. If empty, the + // default name of "debug.log" will be used and the file will be written + // to the application directory. Also configurable using the "log-file" + // command-line switch. + /// + cef_string_t log_file; + + /// + // The log severity. Only messages of this severity level or higher will be + // logged. Also configurable using the "log-severity" command-line switch with + // a value of "verbose", "info", "warning", "error", "error-report" or + // "disable". + /// + cef_log_severity_t log_severity; + + /// + // Custom flags that will be used when initializing the V8 JavaScript engine. + // The consequences of using custom flags may not be well tested. Also + // configurable using the "js-flags" command-line switch. + /// + cef_string_t javascript_flags; + + /// + // The fully qualified path for the resources directory. If this value is + // empty the cef.pak and/or devtools_resources.pak files must be located in + // the module directory on Windows/Linux or the app bundle Resources directory + // on Mac OS X. Also configurable using the "resources-dir-path" command-line + // switch. + /// + cef_string_t resources_dir_path; + + /// + // The fully qualified path for the locales directory. If this value is empty + // the locales directory must be located in the module directory. This value + // is ignored on Mac OS X where pack files are always loaded from the app + // bundle Resources directory. Also configurable using the "locales-dir-path" + // command-line switch. + /// + cef_string_t locales_dir_path; + + /// + // Set to true (1) to disable loading of pack files for resources and locales. + // A resource bundle handler must be provided for the browser and render + // processes via CefApp::GetResourceBundleHandler() if loading of pack files + // is disabled. Also configurable using the "disable-pack-loading" command- + // line switch. + /// + int pack_loading_disabled; + + /// + // Set to a value between 1024 and 65535 to enable remote debugging on the + // specified port. For example, if 8080 is specified the remote debugging URL + // will be http://localhost:8080. CEF can be remotely debugged from any CEF or + // Chrome browser window. Also configurable using the "remote-debugging-port" + // command-line switch. + /// + int remote_debugging_port; + + /// + // The number of stack trace frames to capture for uncaught exceptions. + // Specify a positive value to enable the CefV8ContextHandler:: + // OnUncaughtException() callback. Specify 0 (default value) and + // OnUncaughtException() will not be called. Also configurable using the + // "uncaught-exception-stack-size" command-line switch. + /// + int uncaught_exception_stack_size; + + /// + // By default CEF V8 references will be invalidated (the IsValid() method will + // return false) after the owning context has been released. This reduces the + // need for external record keeping and avoids crashes due to the use of V8 + // references after the associated context has been released. + // + // CEF currently offers two context safety implementations with different + // performance characteristics. The default implementation (value of 0) uses a + // map of hash values and should provide better performance in situations with + // a small number contexts. The alternate implementation (value of 1) uses a + // hidden value attached to each context and should provide better performance + // in situations with a large number of contexts. + // + // If you need better performance in the creation of V8 references and you + // plan to manually track context lifespan you can disable context safety by + // specifying a value of -1. + // + // Also configurable using the "context-safety-implementation" command-line + // switch. + /// + int context_safety_implementation; + + /// + // Set to true (1) to ignore errors related to invalid SSL certificates. + // Enabling this setting can lead to potential security vulnerabilities like + // "man in the middle" attacks. Applications that load content from the + // internet should not enable this setting. Also configurable using the + // "ignore-certificate-errors" command-line switch. + /// + int ignore_certificate_errors; + + /// + // Opaque background color used for accelerated content. By default the + // background color will be white. Only the RGB compontents of the specified + // value will be used. The alpha component must greater than 0 to enable use + // of the background color but will be otherwise ignored. + /// + cef_color_t background_color; +} cef_settings_t; + +/// +// Browser initialization settings. Specify NULL or 0 to get the recommended +// default values. The consequences of using custom values may not be well +// tested. Many of these and other settings can also configured using command- +// line switches. +/// +typedef struct _cef_browser_settings_t { + /// + // Size of this structure. + /// + size_t size; + + /// + // The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint + // will be called for a windowless browser. The actual fps may be lower if + // the browser cannot generate frames at the requested rate. The minimum + // value is 1 and the maximum value is 60 (default 30). + /// + int windowless_frame_rate; + + // The below values map to WebPreferences settings. + + /// + // Font settings. + /// + cef_string_t standard_font_family; + cef_string_t fixed_font_family; + cef_string_t serif_font_family; + cef_string_t sans_serif_font_family; + cef_string_t cursive_font_family; + cef_string_t fantasy_font_family; + int default_font_size; + int default_fixed_font_size; + int minimum_font_size; + int minimum_logical_font_size; + + /// + // Default encoding for Web content. If empty "ISO-8859-1" will be used. Also + // configurable using the "default-encoding" command-line switch. + /// + cef_string_t default_encoding; + + /// + // Controls the loading of fonts from remote sources. Also configurable using + // the "disable-remote-fonts" command-line switch. + /// + cef_state_t remote_fonts; + + /// + // Controls whether JavaScript can be executed. Also configurable using the + // "disable-javascript" command-line switch. + /// + cef_state_t javascript; + + /// + // Controls whether JavaScript can be used for opening windows. Also + // configurable using the "disable-javascript-open-windows" command-line + // switch. + /// + cef_state_t javascript_open_windows; + + /// + // Controls whether JavaScript can be used to close windows that were not + // opened via JavaScript. JavaScript can still be used to close windows that + // were opened via JavaScript. Also configurable using the + // "disable-javascript-close-windows" command-line switch. + /// + cef_state_t javascript_close_windows; + + /// + // Controls whether JavaScript can access the clipboard. Also configurable + // using the "disable-javascript-access-clipboard" command-line switch. + /// + cef_state_t javascript_access_clipboard; + + /// + // Controls whether DOM pasting is supported in the editor via + // execCommand("paste"). The |javascript_access_clipboard| setting must also + // be enabled. Also configurable using the "disable-javascript-dom-paste" + // command-line switch. + /// + cef_state_t javascript_dom_paste; + + /// + // Controls whether the caret position will be drawn. Also configurable using + // the "enable-caret-browsing" command-line switch. + /// + cef_state_t caret_browsing; + + /// + // Controls whether the Java plugin will be loaded. Also configurable using + // the "disable-java" command-line switch. + /// + cef_state_t java; + + /// + // Controls whether any plugins will be loaded. Also configurable using the + // "disable-plugins" command-line switch. + /// + cef_state_t plugins; + + /// + // Controls whether file URLs will have access to all URLs. Also configurable + // using the "allow-universal-access-from-files" command-line switch. + /// + cef_state_t universal_access_from_file_urls; + + /// + // Controls whether file URLs will have access to other file URLs. Also + // configurable using the "allow-access-from-files" command-line switch. + /// + cef_state_t file_access_from_file_urls; + + /// + // Controls whether web security restrictions (same-origin policy) will be + // enforced. Disabling this setting is not recommend as it will allow risky + // security behavior such as cross-site scripting (XSS). Also configurable + // using the "disable-web-security" command-line switch. + /// + cef_state_t web_security; + + /// + // Controls whether image URLs will be loaded from the network. A cached image + // will still be rendered if requested. Also configurable using the + // "disable-image-loading" command-line switch. + /// + cef_state_t image_loading; + + /// + // Controls whether standalone images will be shrunk to fit the page. Also + // configurable using the "image-shrink-standalone-to-fit" command-line + // switch. + /// + cef_state_t image_shrink_standalone_to_fit; + + /// + // Controls whether text areas can be resized. Also configurable using the + // "disable-text-area-resize" command-line switch. + /// + cef_state_t text_area_resize; + + /// + // Controls whether the tab key can advance focus to links. Also configurable + // using the "disable-tab-to-links" command-line switch. + /// + cef_state_t tab_to_links; + + /// + // Controls whether local storage can be used. Also configurable using the + // "disable-local-storage" command-line switch. + /// + cef_state_t local_storage; + + /// + // Controls whether databases can be used. Also configurable using the + // "disable-databases" command-line switch. + /// + cef_state_t databases; + + /// + // Controls whether the application cache can be used. Also configurable using + // the "disable-application-cache" command-line switch. + /// + cef_state_t application_cache; + + /// + // Controls whether WebGL can be used. Note that WebGL requires hardware + // support and may not work on all systems even when enabled. Also + // configurable using the "disable-webgl" command-line switch. + /// + cef_state_t webgl; + + /// + // Opaque background color used for the browser before a document is loaded + // and when no document color is specified. By default the background color + // will be the same as CefSettings.background_color. Only the RGB compontents + // of the specified value will be used. The alpha component must greater than + // 0 to enable use of the background color but will be otherwise ignored. + /// + cef_color_t background_color; +} cef_browser_settings_t; + +/// +// URL component parts. +/// +typedef struct _cef_urlparts_t { + /// + // The complete URL specification. + /// + cef_string_t spec; + + /// + // Scheme component not including the colon (e.g., "http"). + /// + cef_string_t scheme; + + /// + // User name component. + /// + cef_string_t username; + + /// + // Password component. + /// + cef_string_t password; + + /// + // Host component. This may be a hostname, an IPv4 address or an IPv6 literal + // surrounded by square brackets (e.g., "[2001:db8::1]"). + /// + cef_string_t host; + + /// + // Port number component. + /// + cef_string_t port; + + /// + // Origin contains just the scheme, host, and port from a URL. Equivalent to + // clearing any username and password, replacing the path with a slash, and + // clearing everything after that. This value will be empty for non-standard + // URLs. + /// + cef_string_t origin; + + /// + // Path component including the first slash following the host. + /// + cef_string_t path; + + /// + // Query string component (i.e., everything following the '?'). + /// + cef_string_t query; +} cef_urlparts_t; + +/// +// Cookie information. +/// +typedef struct _cef_cookie_t { + /// + // The cookie name. + /// + cef_string_t name; + + /// + // The cookie value. + /// + cef_string_t value; + + /// + // If |domain| is empty a host cookie will be created instead of a domain + // cookie. Domain cookies are stored with a leading "." and are visible to + // sub-domains whereas host cookies are not. + /// + cef_string_t domain; + + /// + // If |path| is non-empty only URLs at or below the path will get the cookie + // value. + /// + cef_string_t path; + + /// + // If |secure| is true the cookie will only be sent for HTTPS requests. + /// + int secure; + + /// + // If |httponly| is true the cookie will only be sent for HTTP requests. + /// + int httponly; + + /// + // The cookie creation date. This is automatically populated by the system on + // cookie creation. + /// + cef_time_t creation; + + /// + // The cookie last access date. This is automatically populated by the system + // on access. + /// + cef_time_t last_access; + + /// + // The cookie expiration date is only valid if |has_expires| is true. + /// + int has_expires; + cef_time_t expires; +} cef_cookie_t; + +/// +// Process termination status values. +/// +typedef enum { + /// + // Non-zero exit status. + /// + TS_ABNORMAL_TERMINATION, + + /// + // SIGKILL or task manager kill. + /// + TS_PROCESS_WAS_KILLED, + + /// + // Segmentation fault. + /// + TS_PROCESS_CRASHED, +} cef_termination_status_t; + +/// +// Path key values. +/// +typedef enum { + /// + // Current directory. + /// + PK_DIR_CURRENT, + + /// + // Directory containing PK_FILE_EXE. + /// + PK_DIR_EXE, + + /// + // Directory containing PK_FILE_MODULE. + /// + PK_DIR_MODULE, + + /// + // Temporary directory. + /// + PK_DIR_TEMP, + + /// + // Path and filename of the current executable. + /// + PK_FILE_EXE, + + /// + // Path and filename of the module containing the CEF code (usually the libcef + // module). + /// + PK_FILE_MODULE, +} cef_path_key_t; + +/// +// Storage types. +/// +typedef enum { + ST_LOCALSTORAGE = 0, + ST_SESSIONSTORAGE, +} cef_storage_type_t; + +/// +// Supported error code values. See net\base\net_error_list.h for complete +// descriptions of the error codes. +/// +typedef enum { + ERR_NONE = 0, + ERR_FAILED = -2, + ERR_ABORTED = -3, + ERR_INVALID_ARGUMENT = -4, + ERR_INVALID_HANDLE = -5, + ERR_FILE_NOT_FOUND = -6, + ERR_TIMED_OUT = -7, + ERR_FILE_TOO_BIG = -8, + ERR_UNEXPECTED = -9, + ERR_ACCESS_DENIED = -10, + ERR_NOT_IMPLEMENTED = -11, + ERR_CONNECTION_CLOSED = -100, + ERR_CONNECTION_RESET = -101, + ERR_CONNECTION_REFUSED = -102, + ERR_CONNECTION_ABORTED = -103, + ERR_CONNECTION_FAILED = -104, + ERR_NAME_NOT_RESOLVED = -105, + ERR_INTERNET_DISCONNECTED = -106, + ERR_SSL_PROTOCOL_ERROR = -107, + ERR_ADDRESS_INVALID = -108, + ERR_ADDRESS_UNREACHABLE = -109, + ERR_SSL_CLIENT_AUTH_CERT_NEEDED = -110, + ERR_TUNNEL_CONNECTION_FAILED = -111, + ERR_NO_SSL_VERSIONS_ENABLED = -112, + ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113, + ERR_SSL_RENEGOTIATION_REQUESTED = -114, + ERR_CERT_COMMON_NAME_INVALID = -200, + ERR_CERT_DATE_INVALID = -201, + ERR_CERT_AUTHORITY_INVALID = -202, + ERR_CERT_CONTAINS_ERRORS = -203, + ERR_CERT_NO_REVOCATION_MECHANISM = -204, + ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205, + ERR_CERT_REVOKED = -206, + ERR_CERT_INVALID = -207, + ERR_CERT_END = -208, + ERR_INVALID_URL = -300, + ERR_DISALLOWED_URL_SCHEME = -301, + ERR_UNKNOWN_URL_SCHEME = -302, + ERR_TOO_MANY_REDIRECTS = -310, + ERR_UNSAFE_REDIRECT = -311, + ERR_UNSAFE_PORT = -312, + ERR_INVALID_RESPONSE = -320, + ERR_INVALID_CHUNKED_ENCODING = -321, + ERR_METHOD_NOT_SUPPORTED = -322, + ERR_UNEXPECTED_PROXY_AUTH = -323, + ERR_EMPTY_RESPONSE = -324, + ERR_RESPONSE_HEADERS_TOO_BIG = -325, + ERR_CACHE_MISS = -400, + ERR_INSECURE_RESPONSE = -501, +} cef_errorcode_t; + +/// +// "Verb" of a drag-and-drop operation as negotiated between the source and +// destination. These constants match their equivalents in WebCore's +// DragActions.h and should not be renumbered. +/// +typedef enum { + DRAG_OPERATION_NONE = 0, + DRAG_OPERATION_COPY = 1, + DRAG_OPERATION_LINK = 2, + DRAG_OPERATION_GENERIC = 4, + DRAG_OPERATION_PRIVATE = 8, + DRAG_OPERATION_MOVE = 16, + DRAG_OPERATION_DELETE = 32, + DRAG_OPERATION_EVERY = UINT_MAX +} cef_drag_operations_mask_t; + +/// +// V8 access control values. +/// +typedef enum { + V8_ACCESS_CONTROL_DEFAULT = 0, + V8_ACCESS_CONTROL_ALL_CAN_READ = 1, + V8_ACCESS_CONTROL_ALL_CAN_WRITE = 1 << 1, + V8_ACCESS_CONTROL_PROHIBITS_OVERWRITING = 1 << 2 +} cef_v8_accesscontrol_t; + +/// +// V8 property attribute values. +/// +typedef enum { + V8_PROPERTY_ATTRIBUTE_NONE = 0, // Writeable, Enumerable, + // Configurable + V8_PROPERTY_ATTRIBUTE_READONLY = 1 << 0, // Not writeable + V8_PROPERTY_ATTRIBUTE_DONTENUM = 1 << 1, // Not enumerable + V8_PROPERTY_ATTRIBUTE_DONTDELETE = 1 << 2 // Not configurable +} cef_v8_propertyattribute_t; + +/// +// Post data elements may represent either bytes or files. +/// +typedef enum { + PDE_TYPE_EMPTY = 0, + PDE_TYPE_BYTES, + PDE_TYPE_FILE, +} cef_postdataelement_type_t; + +/// +// Resource type for a request. +/// +typedef enum { + /// + // Top level page. + /// + RT_MAIN_FRAME = 0, + + /// + // Frame or iframe. + /// + RT_SUB_FRAME, + + /// + // CSS stylesheet. + /// + RT_STYLESHEET, + + /// + // External script. + /// + RT_SCRIPT, + + /// + // Image (jpg/gif/png/etc). + /// + RT_IMAGE, + + /// + // Font. + /// + RT_FONT_RESOURCE, + + /// + // Some other subresource. This is the default type if the actual type is + // unknown. + /// + RT_SUB_RESOURCE, + + /// + // Object (or embed) tag for a plugin, or a resource that a plugin requested. + /// + RT_OBJECT, + + /// + // Media resource. + /// + RT_MEDIA, + + /// + // Main resource of a dedicated worker. + /// + RT_WORKER, + + /// + // Main resource of a shared worker. + /// + RT_SHARED_WORKER, + + /// + // Explicitly requested prefetch. + /// + RT_PREFETCH, + + /// + // Favicon. + /// + RT_FAVICON, + + /// + // XMLHttpRequest. + /// + RT_XHR, +} cef_resource_type_t; + +/// +// Transition type for a request. Made up of one source value and 0 or more +// qualifiers. +/// +typedef enum { + /// + // Source is a link click or the JavaScript window.open function. This is + // also the default value for requests like sub-resource loads that are not + // navigations. + /// + TT_LINK = 0, + + /// + // Source is some other "explicit" navigation action such as creating a new + // browser or using the LoadURL function. This is also the default value + // for navigations where the actual type is unknown. + /// + TT_EXPLICIT = 1, + + /// + // Source is a subframe navigation. This is any content that is automatically + // loaded in a non-toplevel frame. For example, if a page consists of several + // frames containing ads, those ad URLs will have this transition type. + // The user may not even realize the content in these pages is a separate + // frame, so may not care about the URL. + /// + TT_AUTO_SUBFRAME = 3, + + /// + // Source is a subframe navigation explicitly requested by the user that will + // generate new navigation entries in the back/forward list. These are + // probably more important than frames that were automatically loaded in + // the background because the user probably cares about the fact that this + // link was loaded. + /// + TT_MANUAL_SUBFRAME = 4, + + /// + // Source is a form submission by the user. NOTE: In some situations + // submitting a form does not result in this transition type. This can happen + // if the form uses a script to submit the contents. + /// + TT_FORM_SUBMIT = 7, + + /// + // Source is a "reload" of the page via the Reload function or by re-visiting + // the same URL. NOTE: This is distinct from the concept of whether a + // particular load uses "reload semantics" (i.e. bypasses cached data). + /// + TT_RELOAD = 8, + + /// + // General mask defining the bits used for the source values. + /// + TT_SOURCE_MASK = 0xFF, + + // Qualifiers. + // Any of the core values above can be augmented by one or more qualifiers. + // These qualifiers further define the transition. + + /// + // Attempted to visit a URL but was blocked. + /// + TT_BLOCKED_FLAG = 0x00800000, + + /// + // Used the Forward or Back function to navigate among browsing history. + /// + TT_FORWARD_BACK_FLAG = 0x01000000, + + /// + // The beginning of a navigation chain. + /// + TT_CHAIN_START_FLAG = 0x10000000, + + /// + // The last transition in a redirect chain. + /// + TT_CHAIN_END_FLAG = 0x20000000, + + /// + // Redirects caused by JavaScript or a meta refresh tag on the page. + /// + TT_CLIENT_REDIRECT_FLAG = 0x40000000, + + /// + // Redirects sent from the server by HTTP headers. + /// + TT_SERVER_REDIRECT_FLAG = 0x80000000, + + /// + // Used to test whether a transition involves a redirect. + /// + TT_IS_REDIRECT_MASK = 0xC0000000, + + /// + // General mask defining the bits used for the qualifiers. + /// + TT_QUALIFIER_MASK = 0xFFFFFF00, +} cef_transition_type_t; + +/// +// Flags used to customize the behavior of CefURLRequest. +/// +typedef enum { + /// + // Default behavior. + /// + UR_FLAG_NONE = 0, + + /// + // If set the cache will be skipped when handling the request. + /// + UR_FLAG_SKIP_CACHE = 1 << 0, + + /// + // If set user name, password, and cookies may be sent with the request, and + // cookies may be saved from the response. + /// + UR_FLAG_ALLOW_CACHED_CREDENTIALS = 1 << 1, + + /// + // If set upload progress events will be generated when a request has a body. + /// + UR_FLAG_REPORT_UPLOAD_PROGRESS = 1 << 3, + + /// + // If set load timing info will be collected for the request. + /// + UR_FLAG_REPORT_LOAD_TIMING = 1 << 4, + + /// + // If set the headers sent and received for the request will be recorded. + /// + UR_FLAG_REPORT_RAW_HEADERS = 1 << 5, + + /// + // If set the CefURLRequestClient::OnDownloadData method will not be called. + /// + UR_FLAG_NO_DOWNLOAD_DATA = 1 << 6, + + /// + // If set 5XX redirect errors will be propagated to the observer instead of + // automatically re-tried. This currently only applies for requests + // originated in the browser process. + /// + UR_FLAG_NO_RETRY_ON_5XX = 1 << 7, +} cef_urlrequest_flags_t; + +/// +// Flags that represent CefURLRequest status. +/// +typedef enum { + /// + // Unknown status. + /// + UR_UNKNOWN = 0, + + /// + // Request succeeded. + /// + UR_SUCCESS, + + /// + // An IO request is pending, and the caller will be informed when it is + // completed. + /// + UR_IO_PENDING, + + /// + // Request was canceled programatically. + /// + UR_CANCELED, + + /// + // Request failed for some reason. + /// + UR_FAILED, +} cef_urlrequest_status_t; + +/// +// Structure representing a rectangle. +/// +typedef struct _cef_rect_t { + int x; + int y; + int width; + int height; +} cef_rect_t; + +/// +// Structure representing a size. +/// +typedef struct _cef_size_t { + int width; + int height; +} cef_size_t; + +/// +// Existing process IDs. +/// +typedef enum { + /// + // Browser process. + /// + PID_BROWSER, + /// + // Renderer process. + /// + PID_RENDERER, +} cef_process_id_t; + +/// +// Existing thread IDs. +/// +typedef enum { +// BROWSER PROCESS THREADS -- Only available in the browser process. + + /// + // The main thread in the browser. This will be the same as the main + // application thread if CefInitialize() is called with a + // CefSettings.multi_threaded_message_loop value of false. + /// + TID_UI, + + /// + // Used to interact with the database. + /// + TID_DB, + + /// + // Used to interact with the file system. + /// + TID_FILE, + + /// + // Used for file system operations that block user interactions. + // Responsiveness of this thread affects users. + /// + TID_FILE_USER_BLOCKING, + + /// + // Used to launch and terminate browser processes. + /// + TID_PROCESS_LAUNCHER, + + /// + // Used to handle slow HTTP cache operations. + /// + TID_CACHE, + + /// + // Used to process IPC and network messages. + /// + TID_IO, + +// RENDER PROCESS THREADS -- Only available in the render process. + + /// + // The main thread in the renderer. Used for all WebKit and V8 interaction. + /// + TID_RENDERER, +} cef_thread_id_t; + +/// +// Supported value types. +/// +typedef enum { + VTYPE_INVALID = 0, + VTYPE_NULL, + VTYPE_BOOL, + VTYPE_INT, + VTYPE_DOUBLE, + VTYPE_STRING, + VTYPE_BINARY, + VTYPE_DICTIONARY, + VTYPE_LIST, +} cef_value_type_t; + +/// +// Supported JavaScript dialog types. +/// +typedef enum { + JSDIALOGTYPE_ALERT = 0, + JSDIALOGTYPE_CONFIRM, + JSDIALOGTYPE_PROMPT, +} cef_jsdialog_type_t; + +/// +// Screen information used when window rendering is disabled. This structure is +// passed as a parameter to CefRenderHandler::GetScreenInfo and should be filled +// in by the client. +/// +typedef struct _cef_screen_info_t { + /// + // Device scale factor. Specifies the ratio between physical and logical + // pixels. + /// + float device_scale_factor; + + /// + // The screen depth in bits per pixel. + /// + int depth; + + /// + // The bits per color component. This assumes that the colors are balanced + // equally. + /// + int depth_per_component; + + /// + // This can be true for black and white printers. + /// + int is_monochrome; + + /// + // This is set from the rcMonitor member of MONITORINFOEX, to whit: + // "A RECT structure that specifies the display monitor rectangle, + // expressed in virtual-screen coordinates. Note that if the monitor + // is not the primary display monitor, some of the rectangle's + // coordinates may be negative values." + // + // The |rect| and |available_rect| properties are used to determine the + // available surface for rendering popup views. + /// + cef_rect_t rect; + + /// + // This is set from the rcWork member of MONITORINFOEX, to whit: + // "A RECT structure that specifies the work area rectangle of the + // display monitor that can be used by applications, expressed in + // virtual-screen coordinates. Windows uses this rectangle to + // maximize an application on the monitor. The rest of the area in + // rcMonitor contains system windows such as the task bar and side + // bars. Note that if the monitor is not the primary display monitor, + // some of the rectangle's coordinates may be negative values". + // + // The |rect| and |available_rect| properties are used to determine the + // available surface for rendering popup views. + /// + cef_rect_t available_rect; +} cef_screen_info_t; + +/// +// Supported menu IDs. Non-English translations can be provided for the +// IDS_MENU_* strings in CefResourceBundleHandler::GetLocalizedString(). +/// +typedef enum { + // Navigation. + MENU_ID_BACK = 100, + MENU_ID_FORWARD = 101, + MENU_ID_RELOAD = 102, + MENU_ID_RELOAD_NOCACHE = 103, + MENU_ID_STOPLOAD = 104, + + // Editing. + MENU_ID_UNDO = 110, + MENU_ID_REDO = 111, + MENU_ID_CUT = 112, + MENU_ID_COPY = 113, + MENU_ID_PASTE = 114, + MENU_ID_DELETE = 115, + MENU_ID_SELECT_ALL = 116, + + // Miscellaneous. + MENU_ID_FIND = 130, + MENU_ID_PRINT = 131, + MENU_ID_VIEW_SOURCE = 132, + + // All user-defined menu IDs should come between MENU_ID_USER_FIRST and + // MENU_ID_USER_LAST to avoid overlapping the Chromium and CEF ID ranges + // defined in the tools/gritsettings/resource_ids file. + MENU_ID_USER_FIRST = 26500, + MENU_ID_USER_LAST = 28500, +} cef_menu_id_t; + +/// +// Mouse button types. +/// +typedef enum { + MBT_LEFT = 0, + MBT_MIDDLE, + MBT_RIGHT, +} cef_mouse_button_type_t; + +/// +// Structure representing mouse event information. +/// +typedef struct _cef_mouse_event_t { + /// + // X coordinate relative to the left side of the view. + /// + int x; + + /// + // Y coordinate relative to the top side of the view. + /// + int y; + + /// + // Bit flags describing any pressed modifier keys. See + // cef_event_flags_t for values. + /// + uint32 modifiers; +} cef_mouse_event_t; + +/// +// Paint element types. +/// +typedef enum { + PET_VIEW = 0, + PET_POPUP, +} cef_paint_element_type_t; + +/// +// Supported event bit flags. +/// +typedef enum { + EVENTFLAG_NONE = 0, + EVENTFLAG_CAPS_LOCK_ON = 1 << 0, + EVENTFLAG_SHIFT_DOWN = 1 << 1, + EVENTFLAG_CONTROL_DOWN = 1 << 2, + EVENTFLAG_ALT_DOWN = 1 << 3, + EVENTFLAG_LEFT_MOUSE_BUTTON = 1 << 4, + EVENTFLAG_MIDDLE_MOUSE_BUTTON = 1 << 5, + EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6, + // Mac OS-X command key. + EVENTFLAG_COMMAND_DOWN = 1 << 7, + EVENTFLAG_NUM_LOCK_ON = 1 << 8, + EVENTFLAG_IS_KEY_PAD = 1 << 9, + EVENTFLAG_IS_LEFT = 1 << 10, + EVENTFLAG_IS_RIGHT = 1 << 11, +} cef_event_flags_t; + +/// +// Supported menu item types. +/// +typedef enum { + MENUITEMTYPE_NONE, + MENUITEMTYPE_COMMAND, + MENUITEMTYPE_CHECK, + MENUITEMTYPE_RADIO, + MENUITEMTYPE_SEPARATOR, + MENUITEMTYPE_SUBMENU, +} cef_menu_item_type_t; + +/// +// Supported context menu type flags. +/// +typedef enum { + /// + // No node is selected. + /// + CM_TYPEFLAG_NONE = 0, + /// + // The top page is selected. + /// + CM_TYPEFLAG_PAGE = 1 << 0, + /// + // A subframe page is selected. + /// + CM_TYPEFLAG_FRAME = 1 << 1, + /// + // A link is selected. + /// + CM_TYPEFLAG_LINK = 1 << 2, + /// + // A media node is selected. + /// + CM_TYPEFLAG_MEDIA = 1 << 3, + /// + // There is a textual or mixed selection that is selected. + /// + CM_TYPEFLAG_SELECTION = 1 << 4, + /// + // An editable element is selected. + /// + CM_TYPEFLAG_EDITABLE = 1 << 5, +} cef_context_menu_type_flags_t; + +/// +// Supported context menu media types. +/// +typedef enum { + /// + // No special node is in context. + /// + CM_MEDIATYPE_NONE, + /// + // An image node is selected. + /// + CM_MEDIATYPE_IMAGE, + /// + // A video node is selected. + /// + CM_MEDIATYPE_VIDEO, + /// + // An audio node is selected. + /// + CM_MEDIATYPE_AUDIO, + /// + // A file node is selected. + /// + CM_MEDIATYPE_FILE, + /// + // A plugin node is selected. + /// + CM_MEDIATYPE_PLUGIN, +} cef_context_menu_media_type_t; + +/// +// Supported context menu media state bit flags. +/// +typedef enum { + CM_MEDIAFLAG_NONE = 0, + CM_MEDIAFLAG_ERROR = 1 << 0, + CM_MEDIAFLAG_PAUSED = 1 << 1, + CM_MEDIAFLAG_MUTED = 1 << 2, + CM_MEDIAFLAG_LOOP = 1 << 3, + CM_MEDIAFLAG_CAN_SAVE = 1 << 4, + CM_MEDIAFLAG_HAS_AUDIO = 1 << 5, + CM_MEDIAFLAG_HAS_VIDEO = 1 << 6, + CM_MEDIAFLAG_CONTROL_ROOT_ELEMENT = 1 << 7, + CM_MEDIAFLAG_CAN_PRINT = 1 << 8, + CM_MEDIAFLAG_CAN_ROTATE = 1 << 9, +} cef_context_menu_media_state_flags_t; + +/// +// Supported context menu edit state bit flags. +/// +typedef enum { + CM_EDITFLAG_NONE = 0, + CM_EDITFLAG_CAN_UNDO = 1 << 0, + CM_EDITFLAG_CAN_REDO = 1 << 1, + CM_EDITFLAG_CAN_CUT = 1 << 2, + CM_EDITFLAG_CAN_COPY = 1 << 3, + CM_EDITFLAG_CAN_PASTE = 1 << 4, + CM_EDITFLAG_CAN_DELETE = 1 << 5, + CM_EDITFLAG_CAN_SELECT_ALL = 1 << 6, + CM_EDITFLAG_CAN_TRANSLATE = 1 << 7, +} cef_context_menu_edit_state_flags_t; + +/// +// Key event types. +/// +typedef enum { + KEYEVENT_RAWKEYDOWN = 0, + KEYEVENT_KEYDOWN, + KEYEVENT_KEYUP, + KEYEVENT_CHAR +} cef_key_event_type_t; + +/// +// Structure representing keyboard event information. +/// +typedef struct _cef_key_event_t { + /// + // The type of keyboard event. + /// + cef_key_event_type_t type; + + /// + // Bit flags describing any pressed modifier keys. See + // cef_event_flags_t for values. + /// + uint32 modifiers; + + /// + // The Windows key code for the key event. This value is used by the DOM + // specification. Sometimes it comes directly from the event (i.e. on + // Windows) and sometimes it's determined using a mapping function. See + // WebCore/platform/chromium/KeyboardCodes.h for the list of values. + /// + int windows_key_code; + + /// + // The actual key code genenerated by the platform. + /// + int native_key_code; + + /// + // Indicates whether the event is considered a "system key" event (see + // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details). + // This value will always be false on non-Windows platforms. + /// + int is_system_key; + + /// + // The character generated by the keystroke. + /// + char16 character; + + /// + // Same as |character| but unmodified by any concurrently-held modifiers + // (except shift). This is useful for working out shortcut keys. + /// + char16 unmodified_character; + + /// + // True if the focus is currently on an editable field on the page. This is + // useful for determining if standard key events should be intercepted. + /// + int focus_on_editable_field; +} cef_key_event_t; + +/// +// Focus sources. +/// +typedef enum { + /// + // The source is explicit navigation via the API (LoadURL(), etc). + /// + FOCUS_SOURCE_NAVIGATION = 0, + /// + // The source is a system-generated focus event. + /// + FOCUS_SOURCE_SYSTEM, +} cef_focus_source_t; + +/// +// Navigation types. +/// +typedef enum { + NAVIGATION_LINK_CLICKED = 0, + NAVIGATION_FORM_SUBMITTED, + NAVIGATION_BACK_FORWARD, + NAVIGATION_RELOAD, + NAVIGATION_FORM_RESUBMITTED, + NAVIGATION_OTHER, +} cef_navigation_type_t; + +/// +// Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and +// UTF16 (LE and BE) by default. All other types must be translated to UTF8 +// before being passed to the parser. If a BOM is detected and the correct +// decoder is available then that decoder will be used automatically. +/// +typedef enum { + XML_ENCODING_NONE = 0, + XML_ENCODING_UTF8, + XML_ENCODING_UTF16LE, + XML_ENCODING_UTF16BE, + XML_ENCODING_ASCII, +} cef_xml_encoding_type_t; + +/// +// XML node types. +/// +typedef enum { + XML_NODE_UNSUPPORTED = 0, + XML_NODE_PROCESSING_INSTRUCTION, + XML_NODE_DOCUMENT_TYPE, + XML_NODE_ELEMENT_START, + XML_NODE_ELEMENT_END, + XML_NODE_ATTRIBUTE, + XML_NODE_TEXT, + XML_NODE_CDATA, + XML_NODE_ENTITY_REFERENCE, + XML_NODE_WHITESPACE, + XML_NODE_COMMENT, +} cef_xml_node_type_t; + +/// +// Popup window features. +/// +typedef struct _cef_popup_features_t { + int x; + int xSet; + int y; + int ySet; + int width; + int widthSet; + int height; + int heightSet; + + int menuBarVisible; + int statusBarVisible; + int toolBarVisible; + int locationBarVisible; + int scrollbarsVisible; + int resizable; + + int fullscreen; + int dialog; + cef_string_list_t additionalFeatures; +} cef_popup_features_t; + +/// +// DOM document types. +/// +typedef enum { + DOM_DOCUMENT_TYPE_UNKNOWN = 0, + DOM_DOCUMENT_TYPE_HTML, + DOM_DOCUMENT_TYPE_XHTML, + DOM_DOCUMENT_TYPE_PLUGIN, +} cef_dom_document_type_t; + +/// +// DOM event category flags. +/// +typedef enum { + DOM_EVENT_CATEGORY_UNKNOWN = 0x0, + DOM_EVENT_CATEGORY_UI = 0x1, + DOM_EVENT_CATEGORY_MOUSE = 0x2, + DOM_EVENT_CATEGORY_MUTATION = 0x4, + DOM_EVENT_CATEGORY_KEYBOARD = 0x8, + DOM_EVENT_CATEGORY_TEXT = 0x10, + DOM_EVENT_CATEGORY_COMPOSITION = 0x20, + DOM_EVENT_CATEGORY_DRAG = 0x40, + DOM_EVENT_CATEGORY_CLIPBOARD = 0x80, + DOM_EVENT_CATEGORY_MESSAGE = 0x100, + DOM_EVENT_CATEGORY_WHEEL = 0x200, + DOM_EVENT_CATEGORY_BEFORE_TEXT_INSERTED = 0x400, + DOM_EVENT_CATEGORY_OVERFLOW = 0x800, + DOM_EVENT_CATEGORY_PAGE_TRANSITION = 0x1000, + DOM_EVENT_CATEGORY_POPSTATE = 0x2000, + DOM_EVENT_CATEGORY_PROGRESS = 0x4000, + DOM_EVENT_CATEGORY_XMLHTTPREQUEST_PROGRESS = 0x8000, +} cef_dom_event_category_t; + +/// +// DOM event processing phases. +/// +typedef enum { + DOM_EVENT_PHASE_UNKNOWN = 0, + DOM_EVENT_PHASE_CAPTURING, + DOM_EVENT_PHASE_AT_TARGET, + DOM_EVENT_PHASE_BUBBLING, +} cef_dom_event_phase_t; + +/// +// DOM node types. +/// +typedef enum { + DOM_NODE_TYPE_UNSUPPORTED = 0, + DOM_NODE_TYPE_ELEMENT, + DOM_NODE_TYPE_ATTRIBUTE, + DOM_NODE_TYPE_TEXT, + DOM_NODE_TYPE_CDATA_SECTION, + DOM_NODE_TYPE_PROCESSING_INSTRUCTIONS, + DOM_NODE_TYPE_COMMENT, + DOM_NODE_TYPE_DOCUMENT, + DOM_NODE_TYPE_DOCUMENT_TYPE, + DOM_NODE_TYPE_DOCUMENT_FRAGMENT, +} cef_dom_node_type_t; + +/// +// Supported file dialog modes. +/// +typedef enum { + /// + // Requires that the file exists before allowing the user to pick it. + /// + FILE_DIALOG_OPEN = 0, + + /// + // Like Open, but allows picking multiple files to open. + /// + FILE_DIALOG_OPEN_MULTIPLE, + + /// + // Allows picking a nonexistent file, and prompts to overwrite if the file + // already exists. + /// + FILE_DIALOG_SAVE, +} cef_file_dialog_mode_t; + +/// +// Geoposition error codes. +/// +typedef enum { + GEOPOSITON_ERROR_NONE = 0, + GEOPOSITON_ERROR_PERMISSION_DENIED, + GEOPOSITON_ERROR_POSITION_UNAVAILABLE, + GEOPOSITON_ERROR_TIMEOUT, +} cef_geoposition_error_code_t; + +/// +// Structure representing geoposition information. The properties of this +// structure correspond to those of the JavaScript Position object although +// their types may differ. +/// +typedef struct _cef_geoposition_t { + /// + // Latitude in decimal degrees north (WGS84 coordinate frame). + /// + double latitude; + + /// + // Longitude in decimal degrees west (WGS84 coordinate frame). + /// + double longitude; + + /// + // Altitude in meters (above WGS84 datum). + /// + double altitude; + + /// + // Accuracy of horizontal position in meters. + /// + double accuracy; + + /// + // Accuracy of altitude in meters. + /// + double altitude_accuracy; + + /// + // Heading in decimal degrees clockwise from true north. + /// + double heading; + + /// + // Horizontal component of device velocity in meters per second. + /// + double speed; + + /// + // Time of position measurement in miliseconds since Epoch in UTC time. This + // is taken from the host computer's system clock. + /// + cef_time_t timestamp; + + /// + // Error code, see enum above. + /// + cef_geoposition_error_code_t error_code; + + /// + // Human-readable error message. + /// + cef_string_t error_message; +} cef_geoposition_t; + +/// +// Print job color mode values. +/// +typedef enum { + COLOR_MODEL_UNKNOWN, + COLOR_MODEL_GRAY, + COLOR_MODEL_COLOR, + COLOR_MODEL_CMYK, + COLOR_MODEL_CMY, + COLOR_MODEL_KCMY, + COLOR_MODEL_CMY_K, // CMY_K represents CMY+K. + COLOR_MODEL_BLACK, + COLOR_MODEL_GRAYSCALE, + COLOR_MODEL_RGB, + COLOR_MODEL_RGB16, + COLOR_MODEL_RGBA, + COLOR_MODEL_COLORMODE_COLOR, // Used in samsung printer ppds. + COLOR_MODEL_COLORMODE_MONOCHROME, // Used in samsung printer ppds. + COLOR_MODEL_HP_COLOR_COLOR, // Used in HP color printer ppds. + COLOR_MODEL_HP_COLOR_BLACK, // Used in HP color printer ppds. + COLOR_MODEL_PRINTOUTMODE_NORMAL, // Used in foomatic ppds. + COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY, // Used in foomatic ppds. + COLOR_MODEL_PROCESSCOLORMODEL_CMYK, // Used in canon printer ppds. + COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE, // Used in canon printer ppds. + COLOR_MODEL_PROCESSCOLORMODEL_RGB, // Used in canon printer ppds +} cef_color_model_t; + +/// +// Print job duplex mode values. +/// +typedef enum { + DUPLEX_MODE_UNKNOWN = -1, + DUPLEX_MODE_SIMPLEX, + DUPLEX_MODE_LONG_EDGE, + DUPLEX_MODE_SHORT_EDGE, +} cef_duplex_mode_t; + +/// +// Structure representing a print job page range. +/// +typedef struct _cef_page_range_t { + int from; + int to; +} cef_page_range_t; + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_H_ diff --git a/include/internal/cef_types_linux.h b/include/internal/cef_types_linux.h new file mode 100644 index 000000000..3fb896dd0 --- /dev/null +++ b/include/internal/cef_types_linux.h @@ -0,0 +1,119 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_TYPES_LINUX_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_ +#pragma once + +#include "include/base/cef_build.h" + +#if defined(OS_LINUX) + +typedef union _XEvent XEvent; +typedef struct _XDisplay XDisplay; + +#include "include/internal/cef_export.h" +#include "include/internal/cef_string.h" + +// Handle types. +#define cef_cursor_handle_t unsigned long +#define cef_event_handle_t XEvent* +#define cef_window_handle_t unsigned long + +#define kNullCursorHandle 0 +#define kNullEventHandle NULL +#define kNullWindowHandle 0 + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// Return the singleton X11 display shared with Chromium. The display is not +// thread-safe and must only be accessed on the browser process UI thread. +/// +CEF_EXPORT XDisplay* cef_get_xdisplay(); +#define cef_text_input_context_t void* + +/// +// Structure representing CefExecuteProcess arguments. +/// +typedef struct _cef_main_args_t { + int argc; + char** argv; +} cef_main_args_t; + +/// +// Class representing window information. +/// +typedef struct _cef_window_info_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + + /// + // Pointer for the parent window. + /// + cef_window_handle_t parent_window; + + /// + // Set to true (1) to create the browser using windowless (off-screen) + // rendering. No window will be created for the browser and all rendering will + // occur via the CefRenderHandler interface. The |parent_window| value will be + // used to identify monitor info and to act as the parent window for dialogs, + // context menus, etc. If |parent_window| is not provided then the main screen + // monitor will be used and some functionality that requires a parent window + // may not function correctly. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + int windowless_rendering_enabled; + + /// + // Set to true (1) to enable transparent painting in combination with + // windowless rendering. When this value is true a transparent background + // color will be used (RGBA=0x00000000). When this value is false the + // background will be white and opaque. + /// + int transparent_painting_enabled; + + /// + // Pointer for the new browser window. Only used with windowed rendering. + /// + cef_window_handle_t window; +} cef_window_info_t; + +#ifdef __cplusplus +} +#endif + +#endif // OS_LINUX + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_ diff --git a/include/internal/cef_types_mac.h b/include/internal/cef_types_mac.h new file mode 100644 index 000000000..9603fc60a --- /dev/null +++ b/include/internal/cef_types_mac.h @@ -0,0 +1,132 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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_INTERNAL_CEF_TYPES_MAC_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_ +#pragma once + +#include "include/base/cef_build.h" + +#if defined(OS_MACOSX) +#include "include/internal/cef_string.h" + +// Handle types. +#ifdef __cplusplus +#ifdef __OBJC__ +@class NSCursor; +@class NSEvent; +@class NSView; +@class NSTextInputContext; +#else +class NSCursor; +class NSEvent; +struct NSView; +class NSTextInputContext; +#endif +#define cef_cursor_handle_t NSCursor* +#define cef_event_handle_t NSEvent* +#define cef_window_handle_t NSView* +#define cef_text_input_context_t NSTextInputContext* +#else +#define cef_cursor_handle_t void* +#define cef_event_handle_t void* +#define cef_window_handle_t void* +#define cef_text_input_context_t void* +#endif + +#define kNullCursorHandle NULL +#define kNullEventHandle NULL +#define kNullWindowHandle NULL + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// Structure representing CefExecuteProcess arguments. +/// +typedef struct _cef_main_args_t { + int argc; + char** argv; +} cef_main_args_t; + +/// +// Class representing window information. +/// +typedef struct _cef_window_info_t { + cef_string_t window_name; + int x; + int y; + int width; + int height; + + /// + // Set to true (1) to create the view initially hidden. + /// + int hidden; + + /// + // NSView pointer for the parent view. + /// + cef_window_handle_t parent_view; + + /// + // Set to true (1) to create the browser using windowless (off-screen) + // rendering. No view will be created for the browser and all rendering will + // occur via the CefRenderHandler interface. The |parent_view| value will be + // used to identify monitor info and to act as the parent view for dialogs, + // context menus, etc. If |parent_view| is not provided then the main screen + // monitor will be used and some functionality that requires a parent view + // may not function correctly. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + int windowless_rendering_enabled; + + /// + // Set to true (1) to enable transparent painting in combination with + // windowless rendering. When this value is true a transparent background + // color will be used (RGBA=0x00000000). When this value is false the + // background will be white and opaque. + /// + int transparent_painting_enabled; + + /// + // NSView pointer for the new browser view. Only used with windowed rendering. + /// + cef_window_handle_t view; +} cef_window_info_t; + +#ifdef __cplusplus +} +#endif + +#endif // OS_MACOSX + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_ diff --git a/include/internal/cef_types_win.h b/include/internal/cef_types_win.h new file mode 100644 index 000000000..27bf6053b --- /dev/null +++ b/include/internal/cef_types_win.h @@ -0,0 +1,109 @@ +// Copyright (c) 2009 Marshall A. Greenblatt. 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_INTERNAL_CEF_TYPES_WIN_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_ +#pragma once + +#include "include/base/cef_build.h" + +#if defined(OS_WIN) +#include +#include "include/internal/cef_string.h" + +// Handle types. +#define cef_cursor_handle_t HCURSOR +#define cef_event_handle_t MSG* +#define cef_window_handle_t HWND +#define cef_text_input_context_t void* + +#define kNullCursorHandle NULL +#define kNullEventHandle NULL +#define kNullWindowHandle NULL + +#ifdef __cplusplus +extern "C" { +#endif + +/// +// Structure representing CefExecuteProcess arguments. +/// +typedef struct _cef_main_args_t { + HINSTANCE instance; +} cef_main_args_t; + +/// +// Structure representing window information. +/// +typedef struct _cef_window_info_t { + // Standard parameters required by CreateWindowEx() + DWORD ex_style; + cef_string_t window_name; + DWORD style; + int x; + int y; + int width; + int height; + cef_window_handle_t parent_window; + HMENU menu; + + /// + // Set to true (1) to create the browser using windowless (off-screen) + // rendering. No window will be created for the browser and all rendering will + // occur via the CefRenderHandler interface. The |parent_window| value will be + // used to identify monitor info and to act as the parent window for dialogs, + // context menus, etc. If |parent_window| is not provided then the main screen + // monitor will be used and some functionality that requires a parent window + // may not function correctly. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + int windowless_rendering_enabled; + + /// + // Set to true (1) to enable transparent painting in combination with + // windowless rendering. When this value is true a transparent background + // color will be used (RGBA=0x00000000). When this value is false the + // background will be white and opaque. + /// + int transparent_painting_enabled; + + /// + // Handle for the new browser window. Only used with windowed rendering. + /// + cef_window_handle_t window; +} cef_window_info_t; + +#ifdef __cplusplus +} +#endif + +#endif // OS_WIN + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_ diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h new file mode 100644 index 000000000..1f1779fe6 --- /dev/null +++ b/include/internal/cef_types_wrappers.h @@ -0,0 +1,718 @@ +// Copyright (c) 2013 Marshall A. Greenblatt. 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_INTERNAL_CEF_TYPES_WRAPPERS_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ +#pragma once + +#include "include/internal/cef_string.h" +#include "include/internal/cef_string_list.h" +#include "include/internal/cef_types.h" + +/// +// Template class that provides common functionality for CEF structure wrapping. +/// +template +class CefStructBase : public traits::struct_type { + public: + typedef typename traits::struct_type struct_type; + + CefStructBase() : attached_to_(NULL) { + Init(); + } + virtual ~CefStructBase() { + // Only clear this object's data if it isn't currently attached to a + // structure. + if (!attached_to_) + Clear(this); + } + + CefStructBase(const CefStructBase& r) { + Init(); + *this = r; + } + CefStructBase(const struct_type& r) { // NOLINT(runtime/explicit) + Init(); + *this = r; + } + + /// + // Clear this object's values. + /// + void Reset() { + Clear(this); + Init(); + } + + /// + // Attach to the source structure's existing values. DetachTo() can be called + // to insert the values back into the existing structure. + /// + void AttachTo(struct_type& source) { + // Only clear this object's data if it isn't currently attached to a + // structure. + if (!attached_to_) + Clear(this); + + // This object is now attached to the new structure. + attached_to_ = &source; + + // Transfer ownership of the values from the source structure. + memcpy(static_cast(this), &source, sizeof(struct_type)); + } + + /// + // Relinquish ownership of values to the target structure. + /// + void DetachTo(struct_type& target) { + if (attached_to_ != &target) { + // Clear the target structure's values only if we are not currently + // attached to that structure. + Clear(&target); + } + + // Transfer ownership of the values to the target structure. + memcpy(&target, static_cast(this), sizeof(struct_type)); + + // Remove the references from this object. + Init(); + } + + /// + // Set this object's values. If |copy| is true the source structure's values + // will be copied instead of referenced. + /// + void Set(const struct_type& source, bool copy) { + traits::set(&source, this, copy); + } + + CefStructBase& operator=(const CefStructBase& s) { + return operator=(static_cast(s)); + } + + CefStructBase& operator=(const struct_type& s) { + Set(s, true); + return *this; + } + + protected: + void Init() { + memset(static_cast(this), 0, sizeof(struct_type)); + attached_to_ = NULL; + traits::init(this); + } + + static void Clear(struct_type* s) { traits::clear(s); } + + struct_type* attached_to_; +}; + + +struct CefRectTraits { + typedef cef_rect_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + *target = *src; + } +}; + +/// +// Class representing a rectangle. +/// +class CefRect : public CefStructBase { + public: + typedef CefStructBase parent; + + CefRect() : parent() {} + CefRect(const cef_rect_t& r) : parent(r) {} // NOLINT(runtime/explicit) + CefRect(const CefRect& r) : parent(r) {} // NOLINT(runtime/explicit) + CefRect(int x, int y, int width, int height) : parent() { + Set(x, y, width, height); + } + + bool IsEmpty() const { return width <= 0 || height <= 0; } + void Set(int x, int y, int width, int height) { + this->x = x, this->y = y, this->width = width, this->height = height; + } +}; + +inline bool operator==(const CefRect& a, const CefRect& b) { + return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; +} + +inline bool operator!=(const CefRect& a, const CefRect& b) { + return !(a == b); +} + + +struct CefSizeTraits { + typedef cef_size_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + *target = *src; + } +}; + +/// +// Class representing a size. +/// +class CefSize : public CefStructBase { + public: + typedef CefStructBase parent; + + CefSize() : parent() {} + CefSize(const cef_size_t& r) : parent(r) {} // NOLINT(runtime/explicit) + CefSize(const CefSize& r) : parent(r) {} // NOLINT(runtime/explicit) + CefSize(int width, int height) : parent() { + Set(width, height); + } + + bool IsEmpty() const { return width <= 0 || height <= 0; } + void Set(int width, int height) { + this->width = width, this->height = height; + } +}; + +inline bool operator==(const CefSize& a, const CefSize& b) { + return a.width == b.width && a.height == b.height; +} + +inline bool operator!=(const CefSize& a, const CefSize& b) { + return !(a == b); +} + + +struct CefScreenInfoTraits { + typedef cef_screen_info_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->device_scale_factor = src->device_scale_factor; + target->depth = src->depth; + target->depth_per_component = src->depth_per_component; + target->is_monochrome = src->is_monochrome; + target->rect = src->rect; + target->available_rect = src->available_rect; + } +}; + +/// +// Class representing the virtual screen information for use when window rendering +// is disabled. +/// +class CefScreenInfo : public CefStructBase { + public: + typedef CefStructBase parent; + + CefScreenInfo() : parent() {} + CefScreenInfo(const cef_screen_info_t& r) : parent(r) {} // NOLINT(runtime/explicit) + CefScreenInfo(const CefScreenInfo& r) : parent(r) {} // NOLINT(runtime/explicit) + CefScreenInfo(float device_scale_factor, + int depth, + int depth_per_component, + bool is_monochrome, + const CefRect& rect, + const CefRect& available_rect) : parent() { + Set(device_scale_factor, depth, depth_per_component, + is_monochrome, rect, available_rect); + } + + void Set(float device_scale_factor, + int depth, + int depth_per_component, + bool is_monochrome, + const CefRect& rect, + const CefRect& available_rect) { + this->device_scale_factor = device_scale_factor; + this->depth = depth; + this->depth_per_component = depth_per_component; + this->is_monochrome = is_monochrome; + this->rect = rect; + this->available_rect = available_rect; + } +}; + + +struct CefKeyEventTraits { + typedef cef_key_event_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->type = src->type; + target->modifiers = src->modifiers; + target->windows_key_code = src->windows_key_code; + target->native_key_code = src->native_key_code; + target->is_system_key = src->is_system_key; + target->character = src->character; + target->unmodified_character = src->unmodified_character; + target->focus_on_editable_field = src->focus_on_editable_field; + } +}; + +/// +// Class representing a a keyboard event. +/// +typedef CefStructBase CefKeyEvent; + + +struct CefMouseEventTraits { + typedef cef_mouse_event_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->x = src->x; + target->y = src->y; + target->modifiers = src->modifiers; + } +}; + +/// +// Class representing a mouse event. +/// +typedef CefStructBase CefMouseEvent; + + +struct CefPopupFeaturesTraits { + typedef cef_popup_features_t struct_type; + + static inline void init(struct_type* s) { + s->menuBarVisible = true; + s->statusBarVisible = true; + s->toolBarVisible = true; + s->locationBarVisible = true; + s->scrollbarsVisible = true; + s->resizable = true; + } + + static inline void clear(struct_type* s) { + if (s->additionalFeatures) + cef_string_list_free(s->additionalFeatures); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + if (target->additionalFeatures) + cef_string_list_free(target->additionalFeatures); + target->additionalFeatures = src->additionalFeatures ? + cef_string_list_copy(src->additionalFeatures) : NULL; + + target->x = src->x; + target->xSet = src->xSet; + target->y = src->y; + target->ySet = src->ySet; + target->width = src->width; + target->widthSet = src->widthSet; + target->height = src->height; + target->heightSet = src->heightSet; + target->menuBarVisible = src->menuBarVisible; + target->statusBarVisible = src->statusBarVisible; + target->toolBarVisible = src->toolBarVisible; + target->locationBarVisible = src->locationBarVisible; + target->scrollbarsVisible = src->scrollbarsVisible; + target->resizable = src->resizable; + target->fullscreen = src->fullscreen; + target->dialog = src->dialog; + } +}; + +/// +// Class representing popup window features. +/// +typedef CefStructBase CefPopupFeatures; + + +struct CefSettingsTraits { + typedef cef_settings_t struct_type; + + static inline void init(struct_type* s) { + s->size = sizeof(struct_type); + } + + static inline void clear(struct_type* s) { + cef_string_clear(&s->browser_subprocess_path); + cef_string_clear(&s->cache_path); + cef_string_clear(&s->user_agent); + cef_string_clear(&s->product_version); + cef_string_clear(&s->locale); + cef_string_clear(&s->log_file); + cef_string_clear(&s->javascript_flags); + cef_string_clear(&s->resources_dir_path); + cef_string_clear(&s->locales_dir_path); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->single_process = src->single_process; + target->no_sandbox = src->no_sandbox; + cef_string_set(src->browser_subprocess_path.str, + src->browser_subprocess_path.length, + &target->browser_subprocess_path, copy); + target->multi_threaded_message_loop = src->multi_threaded_message_loop; + target->windowless_rendering_enabled = src->windowless_rendering_enabled; + target->command_line_args_disabled = src->command_line_args_disabled; + + cef_string_set(src->cache_path.str, src->cache_path.length, + &target->cache_path, copy); + target->persist_session_cookies = src->persist_session_cookies; + + cef_string_set(src->user_agent.str, src->user_agent.length, + &target->user_agent, copy); + cef_string_set(src->product_version.str, src->product_version.length, + &target->product_version, copy); + cef_string_set(src->locale.str, src->locale.length, &target->locale, copy); + + cef_string_set(src->log_file.str, src->log_file.length, &target->log_file, + copy); + target->log_severity = src->log_severity; + cef_string_set(src->javascript_flags.str, src->javascript_flags.length, + &target->javascript_flags, copy); + + cef_string_set(src->resources_dir_path.str, src->resources_dir_path.length, + &target->resources_dir_path, copy); + cef_string_set(src->locales_dir_path.str, src->locales_dir_path.length, + &target->locales_dir_path, copy); + target->pack_loading_disabled = src->pack_loading_disabled; + target->remote_debugging_port = src->remote_debugging_port; + target->uncaught_exception_stack_size = src->uncaught_exception_stack_size; + target->context_safety_implementation = src->context_safety_implementation; + target->ignore_certificate_errors = src->ignore_certificate_errors; + target->background_color = src->background_color; + } +}; + +/// +// Class representing initialization settings. +/// +typedef CefStructBase CefSettings; + + +struct CefBrowserSettingsTraits { + typedef cef_browser_settings_t struct_type; + + static inline void init(struct_type* s) { + s->size = sizeof(struct_type); + } + + static inline void clear(struct_type* s) { + cef_string_clear(&s->standard_font_family); + cef_string_clear(&s->fixed_font_family); + cef_string_clear(&s->serif_font_family); + cef_string_clear(&s->sans_serif_font_family); + cef_string_clear(&s->cursive_font_family); + cef_string_clear(&s->fantasy_font_family); + cef_string_clear(&s->default_encoding); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->windowless_frame_rate = src->windowless_frame_rate; + + cef_string_set(src->standard_font_family.str, + src->standard_font_family.length, &target->standard_font_family, copy); + cef_string_set(src->fixed_font_family.str, src->fixed_font_family.length, + &target->fixed_font_family, copy); + cef_string_set(src->serif_font_family.str, src->serif_font_family.length, + &target->serif_font_family, copy); + cef_string_set(src->sans_serif_font_family.str, + src->sans_serif_font_family.length, &target->sans_serif_font_family, + copy); + cef_string_set(src->cursive_font_family.str, + src->cursive_font_family.length, &target->cursive_font_family, copy); + cef_string_set(src->fantasy_font_family.str, + src->fantasy_font_family.length, &target->fantasy_font_family, copy); + + target->default_font_size = src->default_font_size; + target->default_fixed_font_size = src->default_fixed_font_size; + target->minimum_font_size = src->minimum_font_size; + target->minimum_logical_font_size = src->minimum_logical_font_size; + + cef_string_set(src->default_encoding.str, src->default_encoding.length, + &target->default_encoding, copy); + + target->remote_fonts = src->remote_fonts; + target->javascript = src->javascript; + target->javascript_open_windows = src->javascript_open_windows; + target->javascript_close_windows = src->javascript_close_windows; + target->javascript_access_clipboard = src->javascript_access_clipboard; + target->javascript_dom_paste = src->javascript_dom_paste; + target->caret_browsing = src->caret_browsing; + target->java = src->java; + target->plugins = src->plugins; + target->universal_access_from_file_urls = + src->universal_access_from_file_urls; + target->file_access_from_file_urls = src->file_access_from_file_urls; + target->web_security = src->web_security; + target->image_loading = src->image_loading; + target->image_shrink_standalone_to_fit = + src->image_shrink_standalone_to_fit; + target->text_area_resize = src->text_area_resize; + target->tab_to_links = src->tab_to_links; + target->local_storage = src->local_storage; + target->databases= src->databases; + target->application_cache = src->application_cache; + target->webgl = src->webgl; + + target->background_color = src->background_color; + } +}; + +/// +// Class representing browser initialization settings. +/// +typedef CefStructBase CefBrowserSettings; + + +struct CefURLPartsTraits { + typedef cef_urlparts_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) { + cef_string_clear(&s->spec); + cef_string_clear(&s->scheme); + cef_string_clear(&s->username); + cef_string_clear(&s->password); + cef_string_clear(&s->host); + cef_string_clear(&s->port); + cef_string_clear(&s->origin); + cef_string_clear(&s->path); + cef_string_clear(&s->query); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + cef_string_set(src->spec.str, src->spec.length, &target->spec, copy); + cef_string_set(src->scheme.str, src->scheme.length, &target->scheme, copy); + cef_string_set(src->username.str, src->username.length, &target->username, + copy); + cef_string_set(src->password.str, src->password.length, &target->password, + copy); + cef_string_set(src->host.str, src->host.length, &target->host, copy); + cef_string_set(src->port.str, src->port.length, &target->port, copy); + cef_string_set(src->origin.str, src->origin.length, &target->origin, copy); + cef_string_set(src->path.str, src->path.length, &target->path, copy); + cef_string_set(src->query.str, src->query.length, &target->query, copy); + } +}; + +/// +// Class representing a URL's component parts. +/// +typedef CefStructBase CefURLParts; + + +struct CefTimeTraits { + typedef cef_time_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + *target = *src; + } +}; + +/// +// Class representing a time. +/// +class CefTime : public CefStructBase { + public: + typedef CefStructBase parent; + + CefTime() : parent() {} + CefTime(const cef_time_t& r) : parent(r) {} // NOLINT(runtime/explicit) + CefTime(const CefTime& r) : parent(r) {} // NOLINT(runtime/explicit) + explicit CefTime(time_t r) : parent() { SetTimeT(r); } + explicit CefTime(double r) : parent() { SetDoubleT(r); } + + // Converts to/from time_t. + void SetTimeT(time_t r) { + cef_time_from_timet(r, this); + } + time_t GetTimeT() const { + time_t time = 0; + cef_time_to_timet(this, &time); + return time; + } + + // Converts to/from a double which is the number of seconds since epoch + // (Jan 1, 1970). Webkit uses this format to represent time. A value of 0 + // means "not initialized". + void SetDoubleT(double r) { + cef_time_from_doublet(r, this); + } + double GetDoubleT() const { + double time = 0; + cef_time_to_doublet(this, &time); + return time; + } + + // Set this object to now. + void Now() { + cef_time_now(this); + } + + // Return the delta between this object and |other| in milliseconds. + long long Delta(const CefTime& other) { + long long delta = 0; + cef_time_delta(this, &other, &delta); + return delta; + } +}; + + +struct CefCookieTraits { + typedef cef_cookie_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) { + cef_string_clear(&s->name); + cef_string_clear(&s->value); + cef_string_clear(&s->domain); + cef_string_clear(&s->path); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + cef_string_set(src->name.str, src->name.length, &target->name, copy); + cef_string_set(src->value.str, src->value.length, &target->value, copy); + cef_string_set(src->domain.str, src->domain.length, &target->domain, copy); + cef_string_set(src->path.str, src->path.length, &target->path, copy); + target->secure = src->secure; + target->httponly = src->httponly; + target->creation = src->creation; + target->last_access = src->last_access; + target->has_expires = src->has_expires; + target->expires = src->expires; + } +}; + +/// +// Class representing a cookie. +/// +typedef CefStructBase CefCookie; + + +struct CefGeopositionTraits { + typedef cef_geoposition_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) { + cef_string_clear(&s->error_message); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->latitude = src->latitude; + target->longitude = src->longitude; + target->altitude = src->altitude; + target->accuracy = src->accuracy; + target->altitude_accuracy = src->altitude_accuracy; + target->heading = src->heading; + target->speed = src->speed; + target->timestamp = src->timestamp; + target->error_code = src->error_code; + cef_string_set(src->error_message.str, src->error_message.length, + &target->error_message, copy); + } +}; + +/// +// Class representing a geoposition. +/// +typedef CefStructBase CefGeoposition; + + +struct CefPageRangeTraits { + typedef cef_page_range_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + *target = *src; + } +}; + +/// +// Class representing a print job page range. +/// +class CefPageRange : public CefStructBase { + public: + typedef CefStructBase parent; + + CefPageRange() : parent() {} + CefPageRange(const cef_page_range_t& r) // NOLINT(runtime/explicit) + : parent(r) {} + CefPageRange(const CefPageRange& r) // NOLINT(runtime/explicit) + : parent(r) {} + CefPageRange(int from, int to) : parent() { + Set(from, to); + } + + void Set(int from, int to) { + this->from = from, this->to = to; + } +}; + +inline bool operator==(const CefPageRange& a, const CefPageRange& b) { + return a.from == b.from && a.to == b.to; +} + +inline bool operator!=(const CefPageRange& a, const CefPageRange& b) { + return !(a == b); +} + + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ diff --git a/include/internal/cef_win.h b/include/internal/cef_win.h new file mode 100644 index 000000000..7361a3ce4 --- /dev/null +++ b/include/internal/cef_win.h @@ -0,0 +1,156 @@ +// Copyright (c) 2008 Marshall A. Greenblatt. 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_INTERNAL_CEF_WIN_H_ +#define CEF_INCLUDE_INTERNAL_CEF_WIN_H_ +#pragma once + +#include "include/internal/cef_types_win.h" +#include "include/internal/cef_types_wrappers.h" + +/// +// Handle types. +/// +#define CefCursorHandle cef_cursor_handle_t +#define CefEventHandle cef_event_handle_t +#define CefWindowHandle cef_window_handle_t +#define CefTextInputContext cef_text_input_context_t + +struct CefMainArgsTraits { + typedef cef_main_args_t struct_type; + + static inline void init(struct_type* s) {} + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->instance = src->instance; + } +}; + +// Class representing CefExecuteProcess arguments. +class CefMainArgs : public CefStructBase { + public: + typedef CefStructBase parent; + + CefMainArgs() : parent() {} + explicit CefMainArgs(const cef_main_args_t& r) : parent(r) {} + explicit CefMainArgs(const CefMainArgs& r) : parent(r) {} + explicit CefMainArgs(HINSTANCE hInstance) : parent() { + instance = hInstance; + } +}; + +struct CefWindowInfoTraits { + typedef cef_window_info_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) { + cef_string_clear(&s->window_name); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->ex_style = src->ex_style; + cef_string_set(src->window_name.str, src->window_name.length, + &target->window_name, copy); + target->style = src->style; + target->x = src->x; + target->y = src->y; + target->width = src->width; + target->height = src->height; + target->parent_window = src->parent_window; + target->menu = src->menu; + target->transparent_painting_enabled = src->transparent_painting_enabled; + target->windowless_rendering_enabled = src->windowless_rendering_enabled; + target->window = src->window; + } +}; + +/// +// Class representing window information. +/// +class CefWindowInfo : public CefStructBase { + public: + typedef CefStructBase parent; + + CefWindowInfo() : parent() {} + explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} + explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + + /// + // Create the browser as a child window. + /// + void SetAsChild(CefWindowHandle parent, RECT windowRect) { + style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP | + WS_VISIBLE; + parent_window = parent; + x = windowRect.left; + y = windowRect.top; + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + + /// + // Create the browser as a popup window. + /// + void SetAsPopup(CefWindowHandle parent, const CefString& windowName) { + style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | + WS_VISIBLE; + parent_window = parent; + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + width = CW_USEDEFAULT; + height = CW_USEDEFAULT; + + cef_string_copy(windowName.c_str(), windowName.length(), &window_name); + } + + /// + // Create the browser using windowless (off-screen) rendering. No window + // will be created for the browser and all rendering will occur via the + // CefRenderHandler interface. The |parent| value will be used to identify + // monitor info and to act as the parent window for dialogs, context menus, + // etc. If |parent| is not provided then the main screen monitor will be used + // and some functionality that requires a parent window may not function + // correctly. If |transparent| is true a transparent background color will be + // used (RGBA=0x00000000). If |transparent| is false the background will be + // white and opaque. In order to create windowless browsers the + // CefSettings.windowless_rendering_enabled value must be set to true. + /// + void SetAsWindowless(CefWindowHandle parent, bool transparent) { + windowless_rendering_enabled = TRUE; + parent_window = parent; + transparent_painting_enabled = transparent; + } +}; + +#endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_ diff --git a/include/wrapper/cef_byte_read_handler.h b/include/wrapper/cef_byte_read_handler.h new file mode 100644 index 000000000..559cdd818 --- /dev/null +++ b/include/wrapper/cef_byte_read_handler.h @@ -0,0 +1,79 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ +#define CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ +#pragma once + +#include "include/base/cef_lock.h" +#include "include/base/cef_macros.h" +#include "include/cef_base.h" +#include "include/cef_stream.h" + +/// +// Thread safe implementation of the CefReadHandler class for reading an +// in-memory array of bytes. +/// +class CefByteReadHandler : public CefReadHandler { + public: + /// + // Create a new object for reading an array of bytes. An optional |source| + // reference can be kept to keep the underlying data source from being + // released while the reader exists. + /// + CefByteReadHandler(const unsigned char* bytes, + size_t size, + CefRefPtr source); + + // CefReadHandler methods. + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Eof() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return false; } + + private: + const unsigned char* bytes_; + int64 size_; + int64 offset_; + CefRefPtr source_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefByteReadHandler); + DISALLOW_COPY_AND_ASSIGN(CefByteReadHandler); +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ diff --git a/include/wrapper/cef_closure_task.h b/include/wrapper/cef_closure_task.h new file mode 100644 index 000000000..8828c6566 --- /dev/null +++ b/include/wrapper/cef_closure_task.h @@ -0,0 +1,101 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_ +#define CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_ +#pragma once + +#include "include/base/cef_callback_forward.h" +#include "include/base/cef_macros.h" +#include "include/cef_task.h" + +/// +// Helpers for asynchronously executing a base::Closure (bound function or +// method) on a CEF thread. Creation of base::Closures can be facilitated using +// base::Bind. See include/base/cef_callback.h for complete usage instructions. +// +// TO use these helpers you should include this header and the header that +// defines base::Bind. +// +// #include "include/base/cef_bind.h" +// #include "include/wrapper/cef_closure_task.h" +// +// Example of executing a bound function: +// +// // Define a function. +// void MyFunc(int arg) { /* do something with |arg| on the UI thread */ } +// +// // Post a task that will execute MyFunc on the UI thread and pass an |arg| +// // value of 5. +// CefPostTask(TID_UI, base::Bind(&MyFunc, 5)); +// +// Example of executing a bound method: +// +// // Define a class. +// class MyClass : public CefBase { +// public: +// MyClass() {} +// void MyMethod(int arg) { /* do something with |arg| on the UI thread */ } +// private: +// IMPLEMENT_REFCOUNTING(MyClass); +// }; +// +// // Create an instance of MyClass. +// CefRefPtr instance = new MyClass(); +// +// // Post a task that will execute MyClass::MyMethod on the UI thread and pass +// // an |arg| value of 5. |instance| will be kept alive until after the task +// // completes. +// CefPostTask(TID_UI, base::Bind(&MyClass::MyMethod, instance, 5)); +/// + +/// +// Create a CefTask that wraps a base::Closure. Can be used in combination with +// CefTaskRunner. +/// +CefRefPtr CefCreateClosureTask(const base::Closure& closure); + +/// +// Post a Closure for execution on the specified thread. +/// +bool CefPostTask(CefThreadId threadId, const base::Closure& closure); + +/// +// Post a Closure for delayed execution on the specified thread. +/// +bool CefPostDelayedTask(CefThreadId threadId, const base::Closure& closure, + int64 delay_ms); + +#endif // CEF_INCLUDE_WRAPPER_CEF_CLOSURE_TASK_H_ diff --git a/include/wrapper/cef_helpers.h b/include/wrapper/cef_helpers.h new file mode 100644 index 000000000..3624c74db --- /dev/null +++ b/include/wrapper/cef_helpers.h @@ -0,0 +1,81 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ +#define CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ +#pragma once + +#include +#include +#include + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_task.h" + +#define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI)); +#define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO)); +#define CEF_REQUIRE_FILE_THREAD() DCHECK(CefCurrentlyOn(TID_FILE)); +#define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER)); + +/// +// Helper class to manage a scoped copy of |argv|. +/// +class CefScopedArgArray { + public: + CefScopedArgArray(int argc, char* argv[]) { + array_ = new char*[argc]; + for (int i = 0; i < argc; ++i) { + values_.push_back(argv[i]); + array_[i] = const_cast(values_[i].c_str()); + } + } + ~CefScopedArgArray() { + delete [] array_; + } + + char** array() const { return array_; } + + private: + char** array_; + + // Keep values in a vector separate from |array_| because various users may + // modify |array_| and we still want to clean up memory properly. + std::vector values_; + + DISALLOW_COPY_AND_ASSIGN(CefScopedArgArray); +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ diff --git a/include/wrapper/cef_message_router.h b/include/wrapper/cef_message_router.h new file mode 100644 index 000000000..2a6fcfe6f --- /dev/null +++ b/include/wrapper/cef_message_router.h @@ -0,0 +1,428 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_MESSAGE_ROUTER_H_ +#define CEF_INCLUDE_WRAPPER_CEF_MESSAGE_ROUTER_H_ +#pragma once + +#include "include/base/cef_ref_counted.h" +#include "include/cef_base.h" +#include "include/cef_browser.h" +#include "include/cef_process_message.h" +#include "include/cef_v8.h" + +// The below classes implement support for routing aynchronous messages between +// JavaScript running in the renderer process and C++ running in the browser +// process. An application interacts with the router by passing it data from +// standard CEF C++ callbacks (OnBeforeBrowse, OnProcessMessageRecieved, +// OnContextCreated, etc). The renderer-side router supports generic JavaScript +// callback registration and execution while the browser-side router supports +// application-specific logic via one or more application-provided Handler +// instances. +// +// The renderer-side router implementation exposes a query function and a cancel +// function via the JavaScript 'window' object: +// +// // Create and send a new query. +// var request_id = window.cefQuery({ +// request: 'my_request', +// persistent: false, +// onSuccess: function(response) {}, +// onFailure: function(error_code, error_message) {} +// }); +// +// // Optionally cancel the query. +// window.cefQueryCancel(request_id); +// +// When |window.cefQuery| is executed the request is sent asynchronously to one +// or more C++ Handler objects registered in the browser process. Each C++ +// Handler can choose to either handle or ignore the query in the +// Handler::OnQuery callback. If a Handler chooses to handle the query then it +// should execute Callback::Success when a response is available or +// Callback::Failure if an error occurs. This will result in asynchronous +// execution of the associated JavaScript callback in the renderer process. Any +// queries unhandled by C++ code in the browser process will be automatically +// canceled and the associated JavaScript onFailure callback will be executed +// with an error code of -1. +// +// Queries can be either persistent or non-persistent. If the query is +// persistent than the callbacks will remain registered until one of the +// following conditions are met: +// +// A. The query is canceled in JavaScript using the |window.cefQueryCancel| +// function. +// B. The query is canceled in C++ code using the Callback::Failure function. +// C. The context associated with the query is released due to browser +// destruction, navigation or renderer process termination. +// +// If the query is non-persistent then the registration will be removed after +// the JavaScript callback is executed a single time. If a query is canceled for +// a reason other than Callback::Failure being executed then the associated +// Handler's OnQueryCanceled method will be called. +// +// Some possible usage patterns include: +// +// One-time Request. Use a non-persistent query to send a JavaScript request. +// The Handler evaluates the request and returns the response. The query is +// then discarded. +// +// Broadcast. Use a persistent query to register as a JavaScript broadcast +// receiver. The Handler keeps track of all registered Callbacks and executes +// them sequentially to deliver the broadcast message. +// +// Subscription. Use a persistent query to register as a JavaScript subscription +// receiver. The Handler initiates the subscription feed on the first request +// and delivers responses to all registered subscribers as they become +// available. The Handler cancels the subscription feed when there are no +// longer any registered JavaScript receivers. +// +// Message routing occurs on a per-browser and per-context basis. Consequently, +// additional application logic can be applied by restricting which browser or +// context instances are passed into the router. If you choose to use this +// approach do so cautiously. In order for the router to function correctly any +// browser or context instance passed into a single router callback must then +// be passed into all router callbacks. +// +// There is generally no need to have multiple renderer-side routers unless you +// wish to have multiple bindings with different JavaScript function names. It +// can be useful to have multiple browser-side routers with different client- +// provided Handler instances when implementing different behaviors on a per- +// browser basis. +// +// This implementation places no formatting restrictions on payload content. +// An application may choose to exchange anything from simple formatted +// strings to serialized XML or JSON data. +// +// +// EXAMPLE USAGE +// +// 1. Define the router configuration. You can optionally specify settings +// like the JavaScript function names. The configuration must be the same in +// both the browser and renderer processes. If using multiple routers in the +// same application make sure to specify unique function names for each +// router configuration. +// +// // Example config object showing the default values. +// CefMessageRouterConfig config; +// config.js_query_function = "cefQuery"; +// config.js_cancel_function = "cefQueryCancel"; +// +// 2. Create an instance of CefMessageRouterBrowserSide in the browser process. +// You might choose to make it a member of your CefClient implementation, +// for example. +// +// browser_side_router_ = CefMessageRouterBrowserSide::Create(config); +// +// 3. Register one or more Handlers. The Handler instances must either outlive +// the router or be removed from the router before they're deleted. +// +// browser_side_router_->AddHandler(my_handler); +// +// 4. Call all required CefMessageRouterBrowserSide methods from other callbacks +// in your CefClient implementation (OnBeforeClose, etc). See the +// CefMessageRouterBrowserSide class documentation for the complete list of +// methods. +// +// 5. Create an instance of CefMessageRouterRendererSide in the renderer process. +// You might choose to make it a member of your CefApp implementation, for +// example. +// +// renderer_side_router_ = CefMessageRouterRendererSide::Create(config); +// +// 6. Call all required CefMessageRouterRendererSide methods from other +// callbacks in your CefRenderProcessHandler implementation +// (OnContextCreated, etc). See the CefMessageRouterRendererSide class +// documentation for the complete list of methods. +// +// 7. Execute the query function from JavaScript code. +// +// window.cefQuery({request: 'my_request', +// persistent: false, +// onSuccess: function(response) { print(response); }, +// onFailure: function(error_code, error_message) {} }); +// +// 8. Handle the query in your Handler::OnQuery implementation and execute the +// appropriate callback either immediately or asynchronously. +// +// void MyHandler::OnQuery(int64 query_id, +// CefRefPtr browser, +// CefRefPtr frame, +// const CefString& request, +// bool persistent, +// CefRefPtr callback) { +// if (request == "my_request") { +// callback->Continue("my_response"); +// return true; +// } +// return false; // Not handled. +// } +// +// 9. Notice that the onSuccess callback is executed in JavaScript. + +/// +// Used to configure the query router. The same values must be passed to both +// CefMessageRouterBrowserSide and CefMessageRouterRendererSide. If using multiple +// router pairs make sure to choose values that do not conflict. +/// +struct CefMessageRouterConfig { + CefMessageRouterConfig(); + + // Name of the JavaScript function that will be added to the 'window' object + // for sending a query. The default value is "cefQuery". + CefString js_query_function; + + // Name of the JavaScript function that will be added to the 'window' object + // for canceling a pending query. The default value is "cefQueryCancel". + CefString js_cancel_function; +}; + +/// +// Implements the browser side of query routing. The methods of this class may +// be called on any browser process thread unless otherwise indicated. +/// +class CefMessageRouterBrowserSide : + public base::RefCountedThreadSafe { + public: + /// + // Callback associated with a single pending asynchronous query. Execute the + // Success or Failure method to send an asynchronous response to the + // associated JavaScript handler. It is a runtime error to destroy a Callback + // object associated with an uncanceled query without first executing one of + // the callback methods. The methods of this class may be called on any + // browser process thread. + /// + class Callback : public CefBase { + public: + /// + // Notify the associated JavaScript onSuccess callback that the query has + // completed successfully with the specified |response|. + /// + virtual void Success(const CefString& response) =0; + + /// + // Notify the associated JavaScript onFailure callback that the query has + // failed with the specified |error_code| and |error_message|. + /// + virtual void Failure(int error_code, const CefString& error_message) =0; + }; + + /// + // Implement this interface to handle queries. All methods will be executed on + // the browser process UI thread. + /// + class Handler { + public: + typedef CefMessageRouterBrowserSide::Callback Callback; + + /// + // Executed when a new query is received. |query_id| uniquely identifies the + // query for the life span of the router. Return true to handle the query + // or false to propagate the query to other registered handlers, if any. If + // no handlers return true from this method then the query will be + // automatically canceled with an error code of -1 delivered to the + // JavaScript onFailure callback. If this method returns true then a + // Callback method must be executed either in this method or asynchronously + // to complete the query. + /// + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) { + return false; + } + + /// + // Executed when a query has been canceled either explicitly using the + // JavaScript cancel function or implicitly due to browser destruction, + // navigation or renderer process termination. It will only be called for + // the single handler that returned true from OnQuery for the same + // |query_id|. No references to the associated Callback object should be + // kept after this method is called, nor should any Callback methods be + // executed. + /// + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) {} + + virtual ~Handler() {} + }; + + /// + // Create a new router with the specified configuration. + /// + static CefRefPtr Create( + const CefMessageRouterConfig& config); + + /// + // Add a new query handler. If |first| is true it will be added as the first + // handler, otherwise it will be added as the last handler. Returns true if + // the handler is added successfully or false if the handler has already been + // added. Must be called on the browser process UI thread. The Handler object + // must either outlive the router or be removed before deletion. + /// + virtual bool AddHandler(Handler* handler, bool first) =0; + + /// + // Remove an existing query handler. Any pending queries associated with the + // handler will be canceled. Handler::OnQueryCanceled will be called and the + // associated JavaScript onFailure callback will be executed with an error + // code of -1. Returns true if the handler is removed successfully or false + // if the handler is not found. Must be called on the browser process UI + // thread. + /// + virtual bool RemoveHandler(Handler* handler) =0; + + /// + // Cancel all pending queries associated with either |browser| or |handler|. + // If both |browser| and |handler| are NULL all pending queries will be + // canceled. Handler::OnQueryCanceled will be called and the associated + // JavaScript onFailure callback will be executed in all cases with an error + // code of -1. + /// + virtual void CancelPending(CefRefPtr browser, + Handler* handler) =0; + + /// + // Returns the number of queries currently pending for the specified |browser| + // and/or |handler|. Either or both values may be empty. Must be called on the + // browser process UI thread. + /// + virtual int GetPendingCount(CefRefPtr browser, + Handler* handler) =0; + + + // The below methods should be called from other CEF handlers. They must be + // called exactly as documented for the router to function correctly. + + /// + // Call from CefLifeSpanHandler::OnBeforeClose. Any pending queries associated + // with |browser| will be canceled and Handler::OnQueryCanceled will be called. + // No JavaScript callbacks will be executed since this indicates destruction + // of the browser. + /// + virtual void OnBeforeClose(CefRefPtr browser) =0; + + /// + // Call from CefRequestHandler::OnRenderProcessTerminated. Any pending queries + // associated with |browser| will be canceled and Handler::OnQueryCanceled + // will be called. No JavaScript callbacks will be executed since this + // indicates destruction of the context. + /// + virtual void OnRenderProcessTerminated(CefRefPtr browser) =0; + + /// + // Call from CefRequestHandler::OnBeforeBrowse only if the navigation is + // allowed to proceed. If |frame| is the main frame then any pending queries + // associated with |browser| will be canceled and Handler::OnQueryCanceled + // will be called. No JavaScript callbacks will be executed since this + // indicates destruction of the context. + /// + virtual void OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame) =0; + + /// + // Call from CefClient::OnProcessMessageReceived. Returns true if the message + // is handled by this router or false otherwise. + /// + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) =0; + + protected: + // Protect against accidental deletion of this object. + friend class base::RefCountedThreadSafe; + virtual ~CefMessageRouterBrowserSide() {} +}; + +/// +// Implements the renderer side of query routing. The methods of this class must +// be called on the render process main thread. +/// +class CefMessageRouterRendererSide : + public base::RefCountedThreadSafe { + public: + /// + // Create a new router with the specified configuration. + /// + static CefRefPtr Create( + const CefMessageRouterConfig& config); + + /// + // Returns the number of queries currently pending for the specified |browser| + // and/or |context|. Either or both values may be empty. + /// + virtual int GetPendingCount(CefRefPtr browser, + CefRefPtr context) =0; + + + // The below methods should be called from other CEF handlers. They must be + // called exactly as documented for the router to function correctly. + + /// + // Call from CefRenderProcessHandler::OnContextCreated. Registers the + // JavaScripts functions with the new context. + /// + virtual void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) =0; + + /// + // Call from CefRenderProcessHandler::OnContextReleased. Any pending queries + // associated with the released context will be canceled and + // Handler::OnQueryCanceled will be called in the browser process. + /// + virtual void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) =0; + + /// + // Call from CefRenderProcessHandler::OnProcessMessageReceived. Returns true + // if the message is handled by this router or false otherwise. + /// + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) =0; + + protected: + // Protect against accidental deletion of this object. + friend class base::RefCountedThreadSafe; + virtual ~CefMessageRouterRendererSide() {} +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_MESSAGE_ROUTER_H_ diff --git a/include/wrapper/cef_stream_resource_handler.h b/include/wrapper/cef_stream_resource_handler.h new file mode 100644 index 000000000..6a9a69814 --- /dev/null +++ b/include/wrapper/cef_stream_resource_handler.h @@ -0,0 +1,104 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_ +#define CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_ +#pragma once + +#include "include/base/cef_macros.h" +#include "include/base/cef_scoped_ptr.h" +#include "include/cef_base.h" +#include "include/cef_resource_handler.h" +#include "include/cef_response.h" + +class CefStreamReader; + +/// +// Implementation of the CefResourceHandler class for reading from a CefStream. +/// +class CefStreamResourceHandler : public CefResourceHandler { + public: + /// + // Create a new object with default response values. + /// + CefStreamResourceHandler(const CefString& mime_type, + CefRefPtr stream); + /// + // Create a new object with explicit response values. + /// + CefStreamResourceHandler(int status_code, + const CefString& status_text, + const CefString& mime_type, + CefResponse::HeaderMap header_map, + CefRefPtr stream); + + virtual ~CefStreamResourceHandler(); + + // CefResourceHandler methods. + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) OVERRIDE; + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE; + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) OVERRIDE; + virtual void Cancel() OVERRIDE; + + private: + void ReadOnFileThread(int bytes_to_read, + CefRefPtr callback); + + const int status_code_; + const CefString status_text_; + const CefString mime_type_; + const CefResponse::HeaderMap header_map_; + const CefRefPtr stream_; + bool read_on_file_thread_; + + class Buffer; + scoped_ptr buffer_; +#ifndef NDEBUG + // Used in debug builds to verify that |buffer_| isn't being accessed on + // multiple threads at the same time. + bool buffer_owned_by_file_thread_; +#endif + + IMPLEMENT_REFCOUNTING(CefStreamResourceHandler); + DISALLOW_COPY_AND_ASSIGN(CefStreamResourceHandler); +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_STREAM_RESOURCE_HANDLER_H_ diff --git a/include/wrapper/cef_xml_object.h b/include/wrapper/cef_xml_object.h new file mode 100644 index 000000000..bf1755432 --- /dev/null +++ b/include/wrapper/cef_xml_object.h @@ -0,0 +1,196 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ +#define CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ +#pragma once + +#include +#include + +#include "include/base/cef_lock.h" +#include "include/base/cef_macros.h" +#include "include/base/cef_ref_counted.h" +#include "include/cef_base.h" +#include "include/cef_xml_reader.h" + +class CefStreamReader; + +/// +// Thread safe class for representing XML data as a structured object. This +// class should not be used with large XML documents because all data will be +// resident in memory at the same time. This implementation supports a +// restricted set of XML features: +//
+// (1) Processing instructions, whitespace and comments are ignored.
+// (2) Elements and attributes must always be referenced using the fully
+//     qualified name (ie, namespace:localname).
+// (3) Empty elements () and elements with zero-length values ()
+//     are considered the same.
+// (4) Element nodes are considered part of a value if:
+//     (a) The element node follows a non-element node at the same depth
+//         (see 5), or
+//     (b) The element node does not have a namespace and the parent node does.
+// (5) Mixed node types at the same depth are combined into a single element
+//     value as follows:
+//     (a) All node values are concatenated to form a single string value.
+//     (b) Entity reference nodes are resolved to the corresponding entity
+//         value.
+//     (c) Element nodes are represented by their outer XML string.
+// 
+/// +class CefXmlObject : public base::RefCountedThreadSafe { + public: + typedef std::vector > ObjectVector; + typedef std::map AttributeMap; + + /// + // Create a new object with the specified name. An object name must always be + // at least one character long. + /// + explicit CefXmlObject(const CefString& name); + + /// + // Load the contents of the specified XML stream into this object. The + // existing children and attributes, if any, will first be cleared. + /// + bool Load(CefRefPtr stream, + CefXmlReader::EncodingType encodingType, + const CefString& URI, CefString* loadError); + + /// + // Set the name, children and attributes of this object to a duplicate of the + // specified object's contents. The existing children and attributes, if any, + // will first be cleared. + /// + void Set(CefRefPtr object); + + /// + // Append a duplicate of the children and attributes of the specified object + // to this object. If |overwriteAttributes| is true then any attributes in + // this object that also exist in the specified object will be overwritten + // with the new values. The name of this object is not changed. + /// + void Append(CefRefPtr object, bool overwriteAttributes); + + /// + // Return a new object with the same name, children and attributes as this + // object. The parent of the new object will be NULL. + /// + CefRefPtr Duplicate(); + + /// + // Clears this object's children and attributes. The name and parenting of + // this object are not changed. + /// + void Clear(); + + /// + // Access the object's name. An object name must always be at least one + // character long. + /// + CefString GetName(); + bool SetName(const CefString& name); + + /// + // Access the object's parent. The parent can be NULL if this object has not + // been added as the child on another object. + /// + bool HasParent(); + CefRefPtr GetParent(); + + /// + // Access the object's value. An object cannot have a value if it also has + // children. Attempting to set the value while children exist will fail. + /// + bool HasValue(); + CefString GetValue(); + bool SetValue(const CefString& value); + + /// + // Access the object's attributes. Attributes must have unique names. + /// + bool HasAttributes(); + size_t GetAttributeCount(); + bool HasAttribute(const CefString& name); + CefString GetAttributeValue(const CefString& name); + bool SetAttributeValue(const CefString& name, const CefString& value); + size_t GetAttributes(AttributeMap& attributes); + void ClearAttributes(); + + /// + // Access the object's children. Each object can only have one parent so + // attempting to add an object that already has a parent will fail. Removing a + // child will set the child's parent to NULL. Adding a child will set the + // child's parent to this object. This object's value, if any, will be cleared + // if a child is added. + /// + bool HasChildren(); + size_t GetChildCount(); + bool HasChild(CefRefPtr child); + bool AddChild(CefRefPtr child); + bool RemoveChild(CefRefPtr child); + size_t GetChildren(ObjectVector& children); + void ClearChildren(); + + /// + // Find the first child with the specified name. + /// + CefRefPtr FindChild(const CefString& name); + + /// + // Find all children with the specified name. + /// + size_t FindChildren(const CefString& name, ObjectVector& children); + + private: + // Protect against accidental deletion of this object. + friend class base::RefCountedThreadSafe; + ~CefXmlObject(); + + void SetParent(CefXmlObject* parent); + + CefString name_; + CefXmlObject* parent_; + CefString value_; + AttributeMap attributes_; + ObjectVector children_; + + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(CefXmlObject); +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ diff --git a/include/wrapper/cef_zip_archive.h b/include/wrapper/cef_zip_archive.h new file mode 100644 index 000000000..7ad10bda8 --- /dev/null +++ b/include/wrapper/cef_zip_archive.h @@ -0,0 +1,143 @@ +// Copyright (c) 2011 Marshall A. Greenblatt. 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. +// +// --------------------------------------------------------------------------- +// +// The contents of this file are only available to applications that link +// against the libcef_dll_wrapper target. +// + +#ifndef CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ +#define CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ +#pragma once + +#include + +#include "include/base/cef_lock.h" +#include "include/base/cef_macros.h" +#include "include/base/cef_ref_counted.h" +#include "include/cef_base.h" + +class CefStreamReader; + +/// +// Thread-safe class for accessing zip archive file contents. This class should +// not be used with large archive files because all data will be resident in +// memory at the same time. This implementation supports a restricted set of zip +// archive features: +// (1) All file names are stored and compared in lower case. +// (2) File ordering from the original zip archive is not maintained. This +// means that files from the same folder may not be located together in the +// file content map. +/// +class CefZipArchive : public base::RefCountedThreadSafe { + public: + /// + // Class representing a file in the archive. Accessing the file data from + // multiple threads is safe provided a reference to the File object is kept. + /// + class File : public CefBase { + public: + /// + // Returns the read-only data contained in the file. + /// + virtual const unsigned char* GetData() const =0; + + /// + // Returns the size of the data in the file. + /// + virtual size_t GetDataSize() const =0; + + /// + // Returns a CefStreamReader object for streaming the contents of the file. + /// + virtual CefRefPtr GetStreamReader() const =0; + }; + + typedef std::map > FileMap; + + /// + // Create a new object. + /// + CefZipArchive(); + + /// + // Load the contents of the specified zip archive stream into this object. + // If the zip archive requires a password then provide it via |password|. + // If |overwriteExisting| is true then any files in this object that also + // exist in the specified archive will be replaced with the new files. + // Returns the number of files successfully loaded. + /// + size_t Load(CefRefPtr stream, + const CefString& password, + bool overwriteExisting); + + /// + // Clears the contents of this object. + /// + void Clear(); + + /// + // Returns the number of files in the archive. + /// + size_t GetFileCount() const; + + /// + // Returns true if the specified file exists and has contents. + /// + bool HasFile(const CefString& fileName) const; + + /// + // Returns the specified file. + /// + CefRefPtr GetFile(const CefString& fileName) const; + + /// + // Removes the specified file. + /// + bool RemoveFile(const CefString& fileName); + + /// + // Returns the map of all files. + /// + size_t GetFiles(FileMap& map) const; + + private: + // Protect against accidental deletion of this object. + friend class base::RefCountedThreadSafe; + ~CefZipArchive(); + + FileMap contents_; + + mutable base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(CefZipArchive); +}; + +#endif // CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ diff --git a/libcef/browser/browser_context.h b/libcef/browser/browser_context.h new file mode 100644 index 000000000..6d90d4df6 --- /dev/null +++ b/libcef/browser/browser_context.h @@ -0,0 +1,24 @@ +// 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_LIBCEF_BROWSER_BROWSER_CONTEXT_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_H_ +#pragma once + +#include "content/public/browser/browser_context.h" +#include "content/public/browser/content_browser_client.h" + +class CefBrowserContext : public content::BrowserContext { + public: + virtual net::URLRequestContextGetter* CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) = 0; + virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) = 0; +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_H_ diff --git a/libcef/browser/browser_context_impl.cc b/libcef/browser/browser_context_impl.cc new file mode 100644 index 000000000..70a2652a2 --- /dev/null +++ b/libcef/browser/browser_context_impl.cc @@ -0,0 +1,155 @@ +// 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 "libcef/browser/browser_context_impl.h" + +#include + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/context.h" +#include "libcef/browser/download_manager_delegate.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_context_getter.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/threading/thread.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_context.h" +#include "content/public/browser/storage_partition.h" + +using content::BrowserThread; + +class CefBrowserContextImpl::CefResourceContext : public content::ResourceContext { + public: + CefResourceContext() : getter_(NULL) {} + virtual ~CefResourceContext() {} + + // ResourceContext implementation: + virtual net::HostResolver* GetHostResolver() OVERRIDE { + CHECK(getter_); + return getter_->host_resolver(); + } + virtual net::URLRequestContext* GetRequestContext() OVERRIDE { + CHECK(getter_); + return getter_->GetURLRequestContext(); + } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { + return true; + } + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { + return true; + } + + void set_url_request_context_getter(CefURLRequestContextGetter* getter) { + getter_ = getter; + } + + private: + CefURLRequestContextGetter* getter_; + + DISALLOW_COPY_AND_ASSIGN(CefResourceContext); +}; + +CefBrowserContextImpl::CefBrowserContextImpl() + : resource_context_(new CefResourceContext) { +} + +CefBrowserContextImpl::~CefBrowserContextImpl() { + // Delete the download manager delegate here because otherwise we'll crash + // when it's accessed from the content::BrowserContext destructor. + if (download_manager_delegate_.get()) + download_manager_delegate_.reset(NULL); + + if (resource_context_.get()) { + BrowserThread::DeleteSoon( + BrowserThread::IO, FROM_HERE, resource_context_.release()); + } +} + +base::FilePath CefBrowserContextImpl::GetPath() const { + return CefContext::Get()->cache_path(); +} + +bool CefBrowserContextImpl::IsOffTheRecord() const { + return false; +} + +content::DownloadManagerDelegate* + CefBrowserContextImpl::GetDownloadManagerDelegate() { + DCHECK(!download_manager_delegate_.get()); + + content::DownloadManager* manager = BrowserContext::GetDownloadManager(this); + download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager)); + return download_manager_delegate_.get(); +} + +net::URLRequestContextGetter* CefBrowserContextImpl::GetRequestContext() { + CEF_REQUIRE_UIT(); + return GetDefaultStoragePartition(this)->GetURLRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextImpl::GetRequestContextForRenderProcess( + int renderer_child_id) { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextImpl::GetMediaRequestContext() { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextImpl::GetMediaRequestContextForRenderProcess( + int renderer_child_id) { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextImpl::GetMediaRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory) { + return GetRequestContext(); +} + +content::ResourceContext* CefBrowserContextImpl::GetResourceContext() { + return resource_context_.get(); +} + +content::BrowserPluginGuestManager* CefBrowserContextImpl::GetGuestManager() { + return NULL; +} + +quota::SpecialStoragePolicy* CefBrowserContextImpl::GetSpecialStoragePolicy() { + return NULL; +} + +content::PushMessagingService* + CefBrowserContextImpl::GetPushMessagingService() { + return NULL; +} + +net::URLRequestContextGetter* CefBrowserContextImpl::CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + DCHECK(!url_request_getter_); + url_request_getter_ = new CefURLRequestContextGetter( + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE), + protocol_handlers, + request_interceptors.Pass()); + resource_context_->set_url_request_context_getter(url_request_getter_.get()); + return url_request_getter_.get(); +} + +net::URLRequestContextGetter* + CefBrowserContextImpl::CreateRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + return NULL; +} diff --git a/libcef/browser/browser_context_impl.h b/libcef/browser/browser_context_impl.h new file mode 100644 index 000000000..46029e5c9 --- /dev/null +++ b/libcef/browser/browser_context_impl.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_IMPL_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_IMPL_H_ +#pragma once + +#include "libcef/browser/browser_context.h" + +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace content { +class DownloadManagerDelegate; +class SpeechRecognitionPreferences; +} + +class CefDownloadManagerDelegate; +class CefURLRequestContextGetter; + +class CefBrowserContextImpl : public CefBrowserContext { + public: + CefBrowserContextImpl(); + virtual ~CefBrowserContextImpl(); + + // BrowserContext methods. + virtual base::FilePath GetPath() const OVERRIDE; + virtual bool IsOffTheRecord() const OVERRIDE; + virtual content::DownloadManagerDelegate* GetDownloadManagerDelegate() OVERRIDE; + virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE; + virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess( + int renderer_child_id) OVERRIDE; + virtual net::URLRequestContextGetter* GetMediaRequestContext() OVERRIDE; + virtual net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess( + int renderer_child_id) OVERRIDE; + virtual net::URLRequestContextGetter* + GetMediaRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory) OVERRIDE; + virtual content::ResourceContext* GetResourceContext() OVERRIDE; + virtual content::BrowserPluginGuestManager* GetGuestManager() OVERRIDE; + virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE; + virtual content::PushMessagingService* GetPushMessagingService() OVERRIDE; + + // CefBrowserContext methods. + virtual net::URLRequestContextGetter* CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + + private: + class CefResourceContext; + + scoped_ptr resource_context_; + scoped_ptr download_manager_delegate_; + scoped_refptr url_request_getter_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserContextImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_IMPL_H_ diff --git a/libcef/browser/browser_context_proxy.cc b/libcef/browser/browser_context_proxy.cc new file mode 100644 index 000000000..2188c7b6e --- /dev/null +++ b/libcef/browser/browser_context_proxy.cc @@ -0,0 +1,152 @@ +// 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 "libcef/browser/browser_context_proxy.h" + +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/download_manager_delegate.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_context_getter.h" +#include "libcef/browser/url_request_context_getter_proxy.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/threading/thread.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_context.h" +#include "content/public/browser/storage_partition.h" + +using content::BrowserThread; + +class CefBrowserContextProxy::CefResourceContext : public content::ResourceContext { + public: + CefResourceContext() : getter_(NULL) {} + virtual ~CefResourceContext() {} + + // ResourceContext implementation: + virtual net::HostResolver* GetHostResolver() OVERRIDE { + CHECK(getter_); + return getter_->GetHostResolver(); + } + virtual net::URLRequestContext* GetRequestContext() OVERRIDE { + CHECK(getter_); + return getter_->GetURLRequestContext(); + } + virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { + return true; + } + virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { + return true; + } + + void set_url_request_context_getter(CefURLRequestContextGetterProxy* getter) { + getter_ = getter; + } + + private: + CefURLRequestContextGetterProxy* getter_; + + DISALLOW_COPY_AND_ASSIGN(CefResourceContext); +}; + +CefBrowserContextProxy::CefBrowserContextProxy( + CefRefPtr handler, + CefBrowserContext* parent) + : refct_(0), + handler_(handler), + parent_(parent), + resource_context_(new CefResourceContext) { +} + +CefBrowserContextProxy::~CefBrowserContextProxy() { + if (resource_context_.get()) { + BrowserThread::DeleteSoon( + BrowserThread::IO, FROM_HERE, resource_context_.release()); + } +} + +base::FilePath CefBrowserContextProxy::GetPath() const { + return parent_->GetPath(); +} + +bool CefBrowserContextProxy::IsOffTheRecord() const { + return parent_->IsOffTheRecord(); +} + +content::DownloadManagerDelegate* + CefBrowserContextProxy::GetDownloadManagerDelegate() { + DCHECK(!download_manager_delegate_.get()); + + content::DownloadManager* manager = BrowserContext::GetDownloadManager(this); + download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager)); + return download_manager_delegate_.get(); +} + +net::URLRequestContextGetter* CefBrowserContextProxy::GetRequestContext() { + CEF_REQUIRE_UIT(); + return GetDefaultStoragePartition(this)->GetURLRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextProxy::GetRequestContextForRenderProcess( + int renderer_child_id) { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextProxy::GetMediaRequestContext() { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextProxy::GetMediaRequestContextForRenderProcess( + int renderer_child_id) { + return GetRequestContext(); +} + +net::URLRequestContextGetter* + CefBrowserContextProxy::GetMediaRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory) { + return GetRequestContext(); +} + +content::ResourceContext* CefBrowserContextProxy::GetResourceContext() { + return resource_context_.get(); +} + +content::BrowserPluginGuestManager* CefBrowserContextProxy::GetGuestManager() { + return parent_->GetGuestManager(); +} + +quota::SpecialStoragePolicy* + CefBrowserContextProxy::GetSpecialStoragePolicy() { + return parent_->GetSpecialStoragePolicy(); +} + +content::PushMessagingService* + CefBrowserContextProxy::GetPushMessagingService() { + return parent_->GetPushMessagingService(); +} + +net::URLRequestContextGetter* CefBrowserContextProxy::CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + DCHECK(!url_request_getter_); + url_request_getter_ = + new CefURLRequestContextGetterProxy(handler_, + static_cast( + CefContentBrowserClient::Get()->request_context().get())); + resource_context_->set_url_request_context_getter(url_request_getter_.get()); + return url_request_getter_.get(); +} + +net::URLRequestContextGetter* + CefBrowserContextProxy::CreateRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + return NULL; +} diff --git a/libcef/browser/browser_context_proxy.h b/libcef/browser/browser_context_proxy.h new file mode 100644 index 000000000..03efe1170 --- /dev/null +++ b/libcef/browser/browser_context_proxy.h @@ -0,0 +1,82 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_PROXY_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_PROXY_H_ +#pragma once + +#include "include/cef_request_context_handler.h" +#include "libcef/browser/browser_context.h" + +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace content { +class DownloadManagerDelegate; +class SpeechRecognitionPreferences; +} + +class CefDownloadManagerDelegate; +class CefURLRequestContextGetterProxy; + +// This class is only accessed on the UI thread. +class CefBrowserContextProxy : public CefBrowserContext { + public: + CefBrowserContextProxy(CefRefPtr handler, + CefBrowserContext* parent); + virtual ~CefBrowserContextProxy(); + + // Reference counting and object life span is managed by + // CefContentBrowserClient. + void AddRef() { refct_++; } + bool Release() { return (--refct_ == 0); } + + // BrowserContext methods. + virtual base::FilePath GetPath() const OVERRIDE; + virtual bool IsOffTheRecord() const OVERRIDE; + virtual content::DownloadManagerDelegate* GetDownloadManagerDelegate() OVERRIDE; + virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE; + virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess( + int renderer_child_id) OVERRIDE; + virtual net::URLRequestContextGetter* GetMediaRequestContext() OVERRIDE; + virtual net::URLRequestContextGetter* GetMediaRequestContextForRenderProcess( + int renderer_child_id) OVERRIDE; + virtual net::URLRequestContextGetter* + GetMediaRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory) OVERRIDE; + virtual content::ResourceContext* GetResourceContext() OVERRIDE; + virtual content::BrowserPluginGuestManager* GetGuestManager() OVERRIDE; + virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE; + virtual content::PushMessagingService* GetPushMessagingService() OVERRIDE; + + // CefBrowserContext methods. + virtual net::URLRequestContextGetter* CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition( + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + + CefRefPtr handler() const { return handler_; } + + private: + class CefResourceContext; + + int refct_; + CefRefPtr handler_; + CefBrowserContext* parent_; + scoped_ptr resource_context_; + scoped_ptr download_manager_delegate_; + scoped_refptr url_request_getter_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserContextProxy); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_PROXY_H_ diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc new file mode 100644 index 000000000..83efb14b3 --- /dev/null +++ b/libcef/browser/browser_host_impl.cc @@ -0,0 +1,2955 @@ +// Copyright (c) 2012 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 "libcef/browser/browser_host_impl.h" + +#include +#include + +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/browser_pref_store.h" +#include "libcef/browser/chrome_scheme_handler.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/devtools_delegate.h" +#include "libcef/browser/devtools_frontend.h" +#include "libcef/browser/media_capture_devices_dispatcher.h" +#include "libcef/browser/navigate_params.h" +#include "libcef/browser/printing/print_view_manager.h" +#include "libcef/browser/render_widget_host_view_osr.h" +#include "libcef/browser/request_context_impl.h" +#include "libcef/browser/scheme_handler.h" +#include "libcef/browser/web_contents_view_osr.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/cef_messages.h" +#include "libcef/common/cef_switches.h" +#include "libcef/common/drag_data_impl.h" +#include "libcef/common/http_header_utils.h" +#include "libcef/common/main_delegate.h" +#include "libcef/common/process_message_impl.h" +#include "libcef/common/request_impl.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" +#include "content/browser/gpu/compositor_util.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/common/view_messages.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_url_parameters.h" +#include "content/public/browser/host_zoom_map.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/common/file_chooser_params.h" +#include "third_party/WebKit/public/web/WebFindOptions.h" +#include "ui/shell_dialogs/selected_file_info.h" + +#if defined(OS_LINUX) || defined(OS_ANDROID) +#include "ui/gfx/font_render_params_linux.h" +#endif + +#if defined(USE_AURA) +#include "ui/views/widget/widget.h" +#endif + +namespace { + +class CreateBrowserHelper { + public: + CreateBrowserHelper(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context) + : window_info_(windowInfo), + client_(client), + url_(url), + settings_(settings), + request_context_(request_context) {} + + CefWindowInfo window_info_; + CefRefPtr client_; + CefString url_; + CefBrowserSettings settings_; + CefRefPtr request_context_; +}; + +void CreateBrowserWithHelper(CreateBrowserHelper* helper) { + CefBrowserHost::CreateBrowserSync(helper->window_info_, helper->client_, + helper->url_, helper->settings_, helper->request_context_); + delete helper; +} + +class ShowDevToolsHelper { + public: + ShowDevToolsHelper(CefRefPtr browser, + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) + : browser_(browser), + window_info_(windowInfo), + client_(client), + settings_(settings) {} + + CefRefPtr browser_; + CefWindowInfo window_info_; + CefRefPtr client_; + CefBrowserSettings settings_; +}; + +void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) { + helper->browser_->ShowDevTools(helper->window_info_, helper->client_, + helper->settings_); + delete helper; +} + +// Convert a NativeWebKeyboardEvent to a CefKeyEvent. +bool GetCefKeyEvent(const content::NativeWebKeyboardEvent& event, + CefKeyEvent& cef_event) { + switch (event.type) { + case blink::WebKeyboardEvent::RawKeyDown: + cef_event.type = KEYEVENT_RAWKEYDOWN; + break; + case blink::WebKeyboardEvent::KeyDown: + cef_event.type = KEYEVENT_KEYDOWN; + break; + case blink::WebKeyboardEvent::KeyUp: + cef_event.type = KEYEVENT_KEYUP; + break; + case blink::WebKeyboardEvent::Char: + cef_event.type = KEYEVENT_CHAR; + break; + default: + return false; + } + + cef_event.modifiers = 0; + if (event.modifiers & blink::WebKeyboardEvent::ShiftKey) + cef_event.modifiers |= EVENTFLAG_SHIFT_DOWN; + if (event.modifiers & blink::WebKeyboardEvent::ControlKey) + cef_event.modifiers |= EVENTFLAG_CONTROL_DOWN; + if (event.modifiers & blink::WebKeyboardEvent::AltKey) + cef_event.modifiers |= EVENTFLAG_ALT_DOWN; + if (event.modifiers & blink::WebKeyboardEvent::MetaKey) + cef_event.modifiers |= EVENTFLAG_COMMAND_DOWN; + if (event.modifiers & blink::WebKeyboardEvent::IsKeyPad) + cef_event.modifiers |= EVENTFLAG_IS_KEY_PAD; + + cef_event.windows_key_code = event.windowsKeyCode; + cef_event.native_key_code = event.nativeKeyCode; + cef_event.is_system_key = event.isSystemKey; + cef_event.character = event.text[0]; + cef_event.unmodified_character = event.unmodifiedText[0]; + + return true; +} + +// Returns the OS event handle, if any, associated with |event|. +CefEventHandle GetCefEventHandle(const content::NativeWebKeyboardEvent& event) { +#if defined(USE_AURA) + if (!event.os_event) + return NULL; +#if defined(OS_WIN) + return const_cast(&event.os_event->native_event()); +#else + return const_cast(event.os_event->native_event()); +#endif +#else // !defined(USE_AURA) + return event.os_event; +#endif // !defined(USE_AURA) +} + +class CefFileDialogCallbackImpl : public CefFileDialogCallback { + public: + explicit CefFileDialogCallbackImpl( + const CefBrowserHostImpl::RunFileChooserCallback& callback) + : callback_(callback) { + } + ~CefFileDialogCallbackImpl() { + if (!callback_.is_null()) { + // The callback is still pending. Cancel it now. + if (CEF_CURRENTLY_ON_UIT()) { + CancelNow(callback_); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefFileDialogCallbackImpl::CancelNow, callback_)); + } + } + } + + virtual void Continue(const std::vector& file_paths) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + std::vector vec; + if (!file_paths.empty()) { + std::vector::const_iterator it = file_paths.begin(); + for (; it != file_paths.end(); ++it) + vec.push_back(base::FilePath(*it)); + } + callback_.Run(vec); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefFileDialogCallbackImpl::Continue, this, file_paths)); + } + } + + virtual void Cancel() OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + CancelNow(callback_); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefFileDialogCallbackImpl::Cancel, this)); + } + } + + bool IsConnected() { + return !callback_.is_null(); + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void CancelNow( + const CefBrowserHostImpl::RunFileChooserCallback& callback) { + CEF_REQUIRE_UIT(); + std::vector file_paths; + callback.Run(file_paths); + } + + CefBrowserHostImpl::RunFileChooserCallback callback_; + + IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl); +}; + +class CefRunFileDialogCallbackWrapper + : public base::RefCountedThreadSafe { + public: + CefRunFileDialogCallbackWrapper(CefRefPtr host, + CefRefPtr callback) + : host_(host), + callback_(callback) { + } + + void Callback(const std::vector& file_paths) { + std::vector paths; + if (file_paths.size() > 0) { + for (size_t i = 0; i < file_paths.size(); ++i) + paths.push_back(file_paths[i].value()); + } + callback_->OnFileDialogDismissed(host_, paths); + } + + private: + CefRefPtr host_; + CefRefPtr callback_; +}; + +} // namespace + + +// CefBrowserHost static methods. +// ----------------------------------------------------------------------------- + +// static +bool CefBrowserHost::CreateBrowser( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return false; + } + + // Verify that the settings structure is a valid size. + if (settings.size != sizeof(cef_browser_settings_t)) { + NOTREACHED() << "invalid CefBrowserSettings structure size"; + return false; + } + + // Verify windowless rendering requirements. + if (windowInfo.windowless_rendering_enabled) { + if (!client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return false; + } + if (!content::IsDelegatedRendererEnabled()) { + NOTREACHED() << "Delegated renderer must be enabled"; + return false; + } + } + + // Create the browser on the UI thread. + CreateBrowserHelper* helper = + new CreateBrowserHelper(windowInfo, client, url, settings, + request_context); + CEF_POST_TASK(CEF_UIT, base::Bind(CreateBrowserWithHelper, helper)); + + return true; +} + +// static +CefRefPtr CefBrowserHost::CreateBrowserSync( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + // Verify that the settings structure is a valid size. + if (settings.size != sizeof(cef_browser_settings_t)) { + NOTREACHED() << "invalid CefBrowserSettings structure size"; + return NULL; + } + + // Verify that this method is being called on the UI thread. + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return NULL; + } + + CefRefPtr browser = + CefBrowserHostImpl::Create(windowInfo, client, url, settings, + kNullWindowHandle, false, request_context); + return browser.get(); +} + + +// CefBrowserHostImpl static methods. +// ----------------------------------------------------------------------------- + +// static +CefRefPtr CefBrowserHostImpl::Create( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefWindowHandle opener, + bool is_popup, + CefRefPtr request_context) { + // Verify windowless rendering requirements. + if (windowInfo.windowless_rendering_enabled) { + if (!client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return NULL; + } + if (!content::IsDelegatedRendererEnabled()) { + NOTREACHED() << "Delegated renderer must be enabled"; + return NULL; + } + } + + scoped_refptr info = + CefContentBrowserClient::Get()->CreateBrowserInfo(is_popup); + info->set_windowless(windowInfo.windowless_rendering_enabled ? true : false); + + CefRefPtr browser = + CefBrowserHostImpl::CreateInternal(windowInfo, settings, client, NULL, + info, opener, request_context); + if (browser && !url.empty()) { + browser->LoadURL(CefFrameHostImpl::kMainFrameId, url, content::Referrer(), + content::PAGE_TRANSITION_TYPED, std::string()); + } + return browser.get(); +} + +// static +CefRefPtr CefBrowserHostImpl::CreateInternal( + const CefWindowInfo& window_info, + const CefBrowserSettings& settings, + CefRefPtr client, + content::WebContents* web_contents, + scoped_refptr browser_info, + CefWindowHandle opener, + CefRefPtr request_context) { + CEF_REQUIRE_UIT(); + DCHECK(browser_info.get()); + + // If |opener| is non-NULL it must be a popup window. + DCHECK(opener == kNullWindowHandle || browser_info->is_popup()); + + if (!web_contents) { + CefBrowserContext* browser_context = NULL; + if (request_context.get()) { + CefRequestContextImpl* request_context_impl = + static_cast(request_context.get()); + browser_context = request_context_impl->GetOrCreateBrowserContext(); + } else { + browser_context = CefContentBrowserClient::Get()->browser_context(); + } + DCHECK(browser_context); + + content::WebContents::CreateParams create_params( + browser_context); + + if (window_info.windowless_rendering_enabled) { + // Use the OSR view instead of the default view. + CefWebContentsViewOSR* view_or = new CefWebContentsViewOSR( + web_contents, + CefContentBrowserClient::Get()->GetWebContentsViewDelegate( + web_contents)); + create_params.view = view_or; + create_params.delegate_view = view_or; + } + web_contents = content::WebContents::Create(create_params); + } + + CefRefPtr browser = + new CefBrowserHostImpl(window_info, settings, client, web_contents, + browser_info, opener); + if (!browser->IsWindowless() && !browser->PlatformCreateWindow()) + return NULL; + +#if defined(OS_LINUX) || defined(OS_ANDROID) + content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs(); + const gfx::FontRenderParams& params = gfx::GetDefaultWebKitFontRenderParams(); + prefs->should_antialias_text = params.antialiasing; + prefs->use_subpixel_positioning = params.subpixel_positioning; + switch (params.hinting) { + case gfx::FontRenderParams::HINTING_NONE: + prefs->hinting = content::RENDERER_PREFERENCES_HINTING_NONE; + break; + case gfx::FontRenderParams::HINTING_SLIGHT: + prefs->hinting = content::RENDERER_PREFERENCES_HINTING_SLIGHT; + break; + case gfx::FontRenderParams::HINTING_MEDIUM: + prefs->hinting = content::RENDERER_PREFERENCES_HINTING_MEDIUM; + break; + case gfx::FontRenderParams::HINTING_FULL: + prefs->hinting = content::RENDERER_PREFERENCES_HINTING_FULL; + break; + default: + NOTREACHED() << "Unhandled hinting style " << params.hinting; + prefs->hinting = content::RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT; + break; + } + prefs->use_autohinter = params.autohinter; + prefs->use_bitmaps = params.use_bitmaps; + switch (params.subpixel_rendering) { + case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE: + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE; + break; + case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB: + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB; + break; + case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR: + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR; + break; + case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB: + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB; + break; + case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR: + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR; + break; + default: + NOTREACHED() << "Unhandled subpixel rendering style " + << params.subpixel_rendering; + prefs->subpixel_rendering = + content::RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT; + break; + } + web_contents->GetRenderViewHost()->SyncRendererPrefs(); +#endif // defined(OS_LINUX) || defined(OS_ANDROID) + + if (client.get()) { + CefRefPtr handler = client->GetLifeSpanHandler(); + if (handler.get()) + handler->OnAfterCreated(browser.get()); + } + + return browser; +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForHost( + const content::RenderViewHost* host) { + DCHECK(host); + CEF_REQUIRE_UIT(); + content::WebContents* web_contents = + content::WebContents::FromRenderViewHost(host); + if (web_contents) + return static_cast(web_contents->GetDelegate()); + return NULL; +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForHost( + const content::RenderFrameHost* host) { + DCHECK(host); + CEF_REQUIRE_UIT(); + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost( + const_cast(host)); + if (web_contents) + return static_cast(web_contents->GetDelegate()); + return NULL; +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForContents( + content::WebContents* contents) { + DCHECK(contents); + CEF_REQUIRE_UIT(); + return static_cast(contents->GetDelegate()); +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForRequest( + net::URLRequest* request) { + DCHECK(request); + CEF_REQUIRE_IOT(); + int render_process_id = -1; + int render_frame_id = MSG_ROUTING_NONE; + + if (!content::ResourceRequestInfo::GetRenderFrameForRequest( + request, &render_process_id, &render_frame_id) || + render_process_id == -1 || + render_frame_id == MSG_ROUTING_NONE) { + return NULL; + } + + return GetBrowserForFrame(render_process_id, render_frame_id); +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForView( + int render_process_id, int render_routing_id) { + if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE) + return NULL; + + if (CEF_CURRENTLY_ON_UIT()) { + // Use the non-thread-safe but potentially faster approach. + content::RenderViewHost* render_view_host = + content::RenderViewHost::FromID(render_process_id, render_routing_id); + if (!render_view_host) + return NULL; + return GetBrowserForHost(render_view_host); + } else { + // Use the thread-safe approach. + scoped_refptr info = + CefContentBrowserClient::Get()->GetBrowserInfoForView( + render_process_id, + render_routing_id); + if (info.get()) { + CefRefPtr browser = info->browser(); + if (!browser.get()) { + LOG(WARNING) << "Found browser id " << info->browser_id() << + " but no browser object matching view process id " << + render_process_id << " and routing id " << + render_routing_id; + } + return browser; + } + return NULL; + } +} + +// static +CefRefPtr CefBrowserHostImpl::GetBrowserForFrame( + int render_process_id, int render_routing_id) { + if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE) + return NULL; + + if (CEF_CURRENTLY_ON_UIT()) { + // Use the non-thread-safe but potentially faster approach. + content::RenderFrameHost* render_frame_host = + content::RenderFrameHost::FromID(render_process_id, render_routing_id); + if (!render_frame_host) + return NULL; + return GetBrowserForHost(render_frame_host); + } else { + // Use the thread-safe approach. + scoped_refptr info = + CefContentBrowserClient::Get()->GetBrowserInfoForFrame( + render_process_id, + render_routing_id); + if (info.get()) { + CefRefPtr browser = info->browser(); + if (!browser.get()) { + LOG(WARNING) << "Found browser id " << info->browser_id() << + " but no browser object matching frame process id " << + render_process_id << " and routing id " << + render_routing_id; + } + return browser; + } + return NULL; + } +} + + +// CefBrowserHostImpl methods. +// ----------------------------------------------------------------------------- + +// WebContentsObserver that will be notified when the frontend WebContents is +// destroyed so that the inspected browser can clear its DevTools references. +class CefBrowserHostImpl::DevToolsWebContentsObserver : + public content::WebContentsObserver { + public: + DevToolsWebContentsObserver(CefBrowserHostImpl* browser, + content::WebContents* frontend_web_contents) + : WebContentsObserver(frontend_web_contents), + browser_(browser) { + } + + // WebContentsObserver methods: + virtual void WebContentsDestroyed() OVERRIDE { + browser_->OnDevToolsWebContentsDestroyed(); + } + + private: + CefBrowserHostImpl* browser_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver); +}; + +CefBrowserHostImpl::~CefBrowserHostImpl() { + // All weak pointer references should be removed in DestroyBrowser(). + DCHECK(!weak_ptr_factory_.HasWeakPtrs()); +} + +CefRefPtr CefBrowserHostImpl::GetBrowser() { + return this; +} + +void CefBrowserHostImpl::CloseBrowser(bool force_close) { + if (CEF_CURRENTLY_ON_UIT()) { + // Exit early if a close attempt is already pending and this method is + // called again from somewhere other than WindowDestroyed(). + if (destruction_state_ >= DESTRUCTION_STATE_PENDING && + (IsWindowless() || !window_destroyed_)) { + if (force_close && destruction_state_ == DESTRUCTION_STATE_PENDING) { + // Upgrade the destruction state. + destruction_state_ = DESTRUCTION_STATE_ACCEPTED; + } + return; + } + + if (destruction_state_ < DESTRUCTION_STATE_ACCEPTED) { + destruction_state_ = (force_close ? DESTRUCTION_STATE_ACCEPTED : + DESTRUCTION_STATE_PENDING); + } + + content::WebContents* contents = web_contents(); + if (contents && contents->NeedToFireBeforeUnload()) { + // Will result in a call to BeforeUnloadFired() and, if the close isn't + // canceled, CloseContents(). + contents->DispatchBeforeUnload(false); + } else { + CloseContents(contents); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::CloseBrowser, this, force_close)); + } +} + +void CefBrowserHostImpl::SetFocus(bool focus) { + if (focus) { + OnSetFocus(FOCUS_SOURCE_SYSTEM); + } else { + if (CEF_CURRENTLY_ON_UIT()) { + PlatformSetFocus(false); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::PlatformSetFocus, this, false)); + } + } +} + +void CefBrowserHostImpl::SetWindowVisibility(bool visible) { +#if defined(OS_MACOSX) + if (CEF_CURRENTLY_ON_UIT()) { + PlatformSetWindowVisibility(visible); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::PlatformSetWindowVisibility, + this, visible)); + } +#endif +} + +CefWindowHandle CefBrowserHostImpl::GetWindowHandle() { + return PlatformGetWindowHandle(); +} + +CefWindowHandle CefBrowserHostImpl::GetOpenerWindowHandle() { + return opener_; +} + +CefRefPtr CefBrowserHostImpl::GetClient() { + return client_; +} + +CefRefPtr CefBrowserHostImpl::GetRequestContext() { + return request_context_; +} + +double CefBrowserHostImpl::GetZoomLevel() { + // Verify that this method is being called on the UI thread. + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return 0; + } + + if (web_contents()) + return content::HostZoomMap::GetZoomLevel(web_contents()); + + return 0; +} + +void CefBrowserHostImpl::SetZoomLevel(double zoomLevel) { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents()) + content::HostZoomMap::SetZoomLevel(web_contents(), zoomLevel); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SetZoomLevel, this, zoomLevel)); + } +} + +void CefBrowserHostImpl::RunFileDialog( + FileDialogMode mode, + const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) { + DCHECK(callback.get()); + if (!callback.get()) + return; + + content::FileChooserParams params; + switch (mode) { + case FILE_DIALOG_OPEN: + params.mode = content::FileChooserParams::Open; + break; + case FILE_DIALOG_OPEN_MULTIPLE: + params.mode = content::FileChooserParams::OpenMultiple; + break; + case FILE_DIALOG_SAVE: + params.mode = content::FileChooserParams::Save; + break; + } + params.title = title; + if (!default_file_name.empty()) + params.default_file_name = base::FilePath(default_file_name); + if (!accept_types.empty()) { + std::vector::const_iterator it = accept_types.begin(); + for (; it != accept_types.end(); ++it) + params.accept_types.push_back(*it); + } + + scoped_refptr wrapper = + new CefRunFileDialogCallbackWrapper(this, callback); + RunFileChooser(params, + base::Bind(&CefRunFileDialogCallbackWrapper::Callback, wrapper)); +} + +void CefBrowserHostImpl::StartDownload(const CefString& url) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::StartDownload, this, url)); + return; + } + + GURL gurl = GURL(url.ToString()); + if (gurl.is_empty() || !gurl.is_valid()) + return; + + if (!web_contents()) + return; + + CefBrowserContext* context = + static_cast(web_contents()->GetBrowserContext()); + if (!context) + return; + + content::DownloadManager* manager = + content::BrowserContext::GetDownloadManager(context); + if (!manager) + return; + + scoped_ptr params; + params.reset( + content::DownloadUrlParameters::FromWebContents(web_contents(), gurl)); + manager->DownloadUrl(params.Pass()); +} + +void CefBrowserHostImpl::Print() { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + printing::PrintViewManager::FromWebContents( + web_contents_.get())->PrintNow(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::Print, this)); + } +} + +void CefBrowserHostImpl::Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + + blink::WebFindOptions options; + options.forward = forward; + options.matchCase = matchCase; + options.findNext = findNext; + web_contents()->Find(identifier, searchText, options); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::Find, this, identifier, searchText, + forward, matchCase, findNext)); + } +} + +void CefBrowserHostImpl::StopFinding(bool clearSelection) { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + + content::StopFindAction action = clearSelection ? + content::STOP_FIND_ACTION_CLEAR_SELECTION : + content::STOP_FIND_ACTION_KEEP_SELECTION; + web_contents()->StopFinding(action); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::StopFinding, this, clearSelection)); + } +} + +void CefBrowserHostImpl::ShowDevTools( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + + if (devtools_frontend_) { + devtools_frontend_->Focus(); + return; + } + + devtools_frontend_ = CefDevToolsFrontend::Show( + this, windowInfo, client, settings); + devtools_observer_.reset(new DevToolsWebContentsObserver( + this, devtools_frontend_->frontend_browser()->web_contents())); + } else { + ShowDevToolsHelper* helper = + new ShowDevToolsHelper(this, windowInfo, client, settings); + CEF_POST_TASK(CEF_UIT, base::Bind(ShowDevToolsWithHelper, helper)); + } +} + +void CefBrowserHostImpl::CloseDevTools() { + if (CEF_CURRENTLY_ON_UIT()) { + if (!devtools_frontend_) + return; + devtools_observer_.reset(); + devtools_frontend_->Close(); + devtools_frontend_ = NULL; + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::CloseDevTools, this)); + } +} + +void CefBrowserHostImpl::SetMouseCursorChangeDisabled(bool disabled) { + base::AutoLock lock_scope(state_lock_); + mouse_cursor_change_disabled_ = disabled; +} + +bool CefBrowserHostImpl::IsMouseCursorChangeDisabled() { + base::AutoLock lock_scope(state_lock_); + return mouse_cursor_change_disabled_; +} + +bool CefBrowserHostImpl::IsWindowRenderingDisabled() { + return IsWindowless(); +} + +void CefBrowserHostImpl::WasResized() { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, base::Bind(&CefBrowserHostImpl::WasResized, this)); + return; + } + + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->WasResized(); +} + +void CefBrowserHostImpl::WasHidden(bool hidden) { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHost::WasHidden, this, hidden)); + return; + } + + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) { + if (hidden) + view->WasHidden(); + else + view->WasShown(); + } +} + +void CefBrowserHostImpl::NotifyScreenInfoChanged() { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::NotifyScreenInfoChanged, this)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->OnScreenInfoChanged(); +} + +void CefBrowserHostImpl::Invalidate(PaintElementType type) { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::Invalidate, this, type)); + return; + } + + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->Invalidate(type); +} + +void CefBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendKeyEvent, this, event)); + return; + } + + content::NativeWebKeyboardEvent web_event; + PlatformTranslateKeyEvent(web_event, event); + + if (!IsWindowless()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardKeyboardEvent(web_event); + } else { + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->SendKeyEvent(web_event); + } +} + +void CefBrowserHostImpl::SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendMouseClickEvent, this, event, type, + mouseUp, clickCount)); + return; + } + + blink::WebMouseEvent web_event; + PlatformTranslateClickEvent(web_event, event, type, mouseUp, clickCount); + + SendMouseEvent(web_event); +} + +void CefBrowserHostImpl::SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendMouseMoveEvent, this, event, + mouseLeave)); + return; + } + + blink::WebMouseEvent web_event; + PlatformTranslateMoveEvent(web_event, event, mouseLeave); + + SendMouseEvent(web_event); +} + +void CefBrowserHostImpl::SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendMouseWheelEvent, this, event, + deltaX, deltaY)); + return; + } + + blink::WebMouseWheelEvent web_event; + PlatformTranslateWheelEvent(web_event, event, deltaX, deltaY); + + if (!IsWindowless()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardWheelEvent(web_event); + } else { + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->SendMouseWheelEvent(web_event); + } +} + +int CefBrowserHostImpl::TranslateModifiers(uint32 cef_modifiers) { + int webkit_modifiers = 0; + // Set modifiers based on key state. + if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) + webkit_modifiers |= blink::WebInputEvent::ShiftKey; + if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) + webkit_modifiers |= blink::WebInputEvent::ControlKey; + if (cef_modifiers & EVENTFLAG_ALT_DOWN) + webkit_modifiers |= blink::WebInputEvent::AltKey; + if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) + webkit_modifiers |= blink::WebInputEvent::MetaKey; + if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + webkit_modifiers |= blink::WebInputEvent::LeftButtonDown; + if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + webkit_modifiers |= blink::WebInputEvent::MiddleButtonDown; + if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + webkit_modifiers |= blink::WebInputEvent::RightButtonDown; + if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) + webkit_modifiers |= blink::WebInputEvent::CapsLockOn; + if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) + webkit_modifiers |= blink::WebInputEvent::NumLockOn; + if (cef_modifiers & EVENTFLAG_IS_LEFT) + webkit_modifiers |= blink::WebInputEvent::IsLeft; + if (cef_modifiers & EVENTFLAG_IS_RIGHT) + webkit_modifiers |= blink::WebInputEvent::IsRight; + if (cef_modifiers & EVENTFLAG_IS_KEY_PAD) + webkit_modifiers |= blink::WebInputEvent::IsKeyPad; + return webkit_modifiers; +} + +void CefBrowserHostImpl::SendMouseEvent(const blink::WebMouseEvent& event) { + if (!IsWindowless()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardMouseEvent(event); + } else { + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->SendMouseEvent(event); + } +} + +void CefBrowserHostImpl::SendFocusEvent(bool setFocus) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendFocusEvent, this, setFocus)); + return; + } + + if (!IsWindowless()) { + SetFocus(setFocus); + } else { + if (!web_contents()) + return; + + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents()->GetRenderViewHost()->GetView()); + if (view) + view->SendFocusEvent(setFocus); + } +} + +void CefBrowserHostImpl::SendCaptureLostEvent() { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendCaptureLostEvent, this)); + return; + } + + if (!web_contents()) + return; + + content::RenderWidgetHostImpl* widget = + content::RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost()); + if (widget) + widget->LostCapture(); +} + +// CefBrowser methods. +// ----------------------------------------------------------------------------- + +CefRefPtr CefBrowserHostImpl::GetHost() { + return this; +} + +bool CefBrowserHostImpl::CanGoBack() { + base::AutoLock lock_scope(state_lock_); + return can_go_back_; +} + +void CefBrowserHostImpl::GoBack() { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get() && web_contents_->GetController().CanGoBack()) + web_contents_->GetController().GoBack(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::GoBack, this)); + } +} + +bool CefBrowserHostImpl::CanGoForward() { + base::AutoLock lock_scope(state_lock_); + return can_go_forward_; +} + +void CefBrowserHostImpl::GoForward() { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get() && web_contents_->GetController().CanGoForward()) + web_contents_->GetController().GoForward(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::GoForward, this)); + } +} + +bool CefBrowserHostImpl::IsLoading() { + base::AutoLock lock_scope(state_lock_); + return is_loading_; +} + +void CefBrowserHostImpl::Reload() { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get()) + web_contents_->GetController().Reload(true); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::Reload, this)); + } +} + +void CefBrowserHostImpl::ReloadIgnoreCache() { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get()) + web_contents_->GetController().ReloadIgnoringCache(true); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::ReloadIgnoreCache, this)); + } +} + +void CefBrowserHostImpl::StopLoad() { + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get()) + web_contents_->Stop(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::StopLoad, this)); + } +} + +int CefBrowserHostImpl::GetIdentifier() { + return browser_id(); +} + +bool CefBrowserHostImpl::IsSame(CefRefPtr that) { + CefBrowserHostImpl* impl = static_cast(that.get()); + return (impl == this); +} + +bool CefBrowserHostImpl::IsPopup() { + return browser_info_->is_popup(); +} + +bool CefBrowserHostImpl::HasDocument() { + base::AutoLock lock_scope(state_lock_); + return has_document_; +} + +CefRefPtr CefBrowserHostImpl::GetMainFrame() { + return GetFrame(CefFrameHostImpl::kMainFrameId); +} + +CefRefPtr CefBrowserHostImpl::GetFocusedFrame() { + return GetFrame(CefFrameHostImpl::kFocusedFrameId); +} + +CefRefPtr CefBrowserHostImpl::GetFrame(int64 identifier) { + base::AutoLock lock_scope(state_lock_); + + if (main_frame_id_ == CefFrameHostImpl::kInvalidFrameId) { + // A main frame does not exist yet. Return the placeholder frame that + // provides limited functionality. + return placeholder_frame_.get(); + } + + if (identifier == CefFrameHostImpl::kMainFrameId) { + identifier = main_frame_id_; + } else if (identifier == CefFrameHostImpl::kFocusedFrameId) { + // Return the main frame if no focused frame is currently identified. + if (focused_frame_id_ == CefFrameHostImpl::kInvalidFrameId) + identifier = main_frame_id_; + else + identifier = focused_frame_id_; + } + + if (identifier == CefFrameHostImpl::kInvalidFrameId) + return NULL; + + FrameMap::const_iterator it = frames_.find(identifier); + if (it != frames_.end()) + return it->second.get(); + + return NULL; +} + +CefRefPtr CefBrowserHostImpl::GetFrame(const CefString& name) { + base::AutoLock lock_scope(state_lock_); + + FrameMap::const_iterator it = frames_.begin(); + for (; it != frames_.end(); ++it) { + if (it->second->GetName() == name) + return it->second.get(); + } + + return NULL; +} + +size_t CefBrowserHostImpl::GetFrameCount() { + base::AutoLock lock_scope(state_lock_); + return frames_.size(); +} + +void CefBrowserHostImpl::GetFrameIdentifiers(std::vector& identifiers) { + base::AutoLock lock_scope(state_lock_); + + if (identifiers.size() > 0) + identifiers.clear(); + + FrameMap::const_iterator it = frames_.begin(); + for (; it != frames_.end(); ++it) + identifiers.push_back(it->first); +} + +void CefBrowserHostImpl::GetFrameNames(std::vector& names) { + base::AutoLock lock_scope(state_lock_); + + if (names.size() > 0) + names.clear(); + + FrameMap::const_iterator it = frames_.begin(); + for (; it != frames_.end(); ++it) + names.push_back(it->second->GetName()); +} + +bool CefBrowserHostImpl::SendProcessMessage( + CefProcessId target_process, + CefRefPtr message) { + DCHECK(message.get()); + + Cef_Request_Params params; + CefProcessMessageImpl* impl = + static_cast(message.get()); + if (impl->CopyTo(params)) { + return SendProcessMessage(target_process, params.name, ¶ms.arguments, + true); + } + + return false; +} + + +// CefBrowserHostImpl public methods. +// ----------------------------------------------------------------------------- + +bool CefBrowserHostImpl::IsWindowless() const { + return window_info_.windowless_rendering_enabled ? true : false; +} + +bool CefBrowserHostImpl::IsTransparent() const { + return window_info_.transparent_painting_enabled ? true : false; +} + +void CefBrowserHostImpl::WindowDestroyed() { + CEF_REQUIRE_UIT(); + DCHECK(!window_destroyed_); + window_destroyed_ = true; + CloseBrowser(true); +} + +void CefBrowserHostImpl::DestroyBrowser() { + CEF_REQUIRE_UIT(); + + destruction_state_ = DESTRUCTION_STATE_COMPLETED; + + if (client_.get()) { + CefRefPtr handler = client_->GetLifeSpanHandler(); + if (handler.get()) { + // Notify the handler that the window is about to be closed. + handler->OnBeforeClose(this); + } + } + + while (!queued_messages_.empty()) { + delete queued_messages_.front(); + queued_messages_.pop(); + } + + registrar_.reset(NULL); + response_manager_.reset(NULL); + content::WebContentsObserver::Observe(NULL); + web_contents_.reset(NULL); + menu_creator_.reset(NULL); + +#if defined(USE_AURA) + window_widget_ = NULL; +#endif + + DetachAllFrames(); + + CefContentBrowserClient::Get()->RemoveBrowserInfo(browser_info_); + browser_info_->set_browser(NULL); + + weak_ptr_factory_.InvalidateWeakPtrs(); +} + +gfx::NativeView CefBrowserHostImpl::GetContentView() const { + CEF_REQUIRE_UIT(); +#if defined(USE_AURA) + if (!window_widget_) + return NULL; + return window_widget_->GetNativeView(); +#else + if (!web_contents_.get()) + return NULL; + return web_contents_->GetNativeView(); +#endif +} + +void CefBrowserHostImpl::CancelContextMenu() { +#if defined(OS_LINUX) && defined(USE_AURA) + CEF_REQUIRE_UIT(); + // Special case for dismissing views-based context menus on Linux Aura + // when using windowless rendering. + if (IsWindowless() && menu_creator_) + menu_creator_->CancelContextMenu(); +#endif +} + +content::WebContents* CefBrowserHostImpl::GetWebContents() const { + CEF_REQUIRE_UIT(); + return web_contents_.get(); +} + +CefRefPtr CefBrowserHostImpl::GetFrameForRequest( + net::URLRequest* request) { + CEF_REQUIRE_IOT(); + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + if (!info) + return NULL; + return GetOrCreateFrame(info->GetRenderFrameID(), + info->GetParentRenderFrameID(), + info->IsMainFrame(), + base::string16(), + GURL()); +} + +void CefBrowserHostImpl::Navigate(const CefNavigateParams& params) { + // Only known frame ids and kMainFrameId are supported. + DCHECK(params.frame_id >= CefFrameHostImpl::kMainFrameId); + + CefMsg_LoadRequest_Params request; + request.url = params.url; + if (!request.url.is_valid()) { + LOG(ERROR) << "Invalid URL passed to CefBrowserHostImpl::Navigate: " << + params.url; + return; + } + + request.method = params.method; + request.referrer = params.referrer.url; + request.referrer_policy = params.referrer.policy; + request.frame_id = params.frame_id; + request.first_party_for_cookies = params.first_party_for_cookies; + request.headers = params.headers; + request.load_flags = params.load_flags; + request.upload_data = params.upload_data; + + Send(new CefMsg_LoadRequest(routing_id(), request)); + + OnSetFocus(FOCUS_SOURCE_NAVIGATION); +} + +void CefBrowserHostImpl::LoadRequest(int64 frame_id, + CefRefPtr request) { + CefNavigateParams params(GURL(std::string(request->GetURL())), + content::PAGE_TRANSITION_TYPED); + params.method = request->GetMethod(); + params.frame_id = frame_id; + params.first_party_for_cookies = + GURL(std::string(request->GetFirstPartyForCookies())); + + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + if (!headerMap.empty()) + params.headers = HttpHeaderUtils::GenerateHeaders(headerMap); + + CefRefPtr postData = request->GetPostData(); + if (postData.get()) { + CefPostDataImpl* impl = static_cast(postData.get()); + params.upload_data = new net::UploadData(); + impl->Get(*params.upload_data.get()); + } + + params.load_flags = request->GetFlags(); + + Navigate(params); +} + +void CefBrowserHostImpl::LoadURL( + int64 frame_id, + const std::string& url, + const content::Referrer& referrer, + content::PageTransition transition, + const std::string& extra_headers) { + if (frame_id == CefFrameHostImpl::kMainFrameId) { + // Go through the navigation controller. + if (CEF_CURRENTLY_ON_UIT()) { + if (web_contents_.get()) { + GURL gurl = GURL(url); + + if (!gurl.is_valid() && !gurl.has_scheme()) { + // Try to add "http://" at the beginning + std::string new_url = std::string("http://") + url; + gurl = GURL(new_url); + } + + if (!gurl.is_valid()) { + LOG(ERROR) << + "Invalid URL passed to CefBrowserHostImpl::LoadURL: " << url; + return; + } + + // Update the loading URL. + OnLoadingURLChange(gurl); + + web_contents_->GetController().LoadURL( + gurl, + referrer, + transition, + extra_headers); + OnSetFocus(FOCUS_SOURCE_NAVIGATION); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::LoadURL, this, frame_id, url, + referrer, transition, extra_headers)); + } + } else { + CefNavigateParams params(GURL(url), transition); + params.frame_id = frame_id; + params.referrer = referrer; + params.headers = extra_headers; + Navigate(params); + } +} + +void CefBrowserHostImpl::LoadString(int64 frame_id, const std::string& string, + const std::string& url) { + // Only known frame ids or kMainFrameId are supported. + DCHECK(frame_id >= CefFrameHostImpl::kMainFrameId); + + Cef_Request_Params params; + params.name = "load-string"; + params.frame_id = frame_id; + params.user_initiated = false; + params.request_id = -1; + params.expect_response = false; + + params.arguments.Append(base::Value::CreateStringValue(string)); + params.arguments.Append(base::Value::CreateStringValue(url)); + + Send(new CefMsg_Request(routing_id(), params)); +} + +void CefBrowserHostImpl::SendCommand( + int64 frame_id, + const std::string& command, + CefRefPtr responseHandler) { + // Only known frame ids are supported. + DCHECK(frame_id > CefFrameHostImpl::kMainFrameId); + DCHECK(!command.empty()); + + // Execute on the UI thread because CefResponseManager is not thread safe. + if (CEF_CURRENTLY_ON_UIT()) { + TRACE_EVENT2("libcef", "CefBrowserHostImpl::SendCommand", + "frame_id", frame_id, + "needsResponse", responseHandler.get() ? 1 : 0); + Cef_Request_Params params; + params.name = "execute-command"; + params.frame_id = frame_id; + params.user_initiated = false; + + if (responseHandler.get()) { + params.request_id = response_manager_->RegisterHandler(responseHandler); + params.expect_response = true; + } else { + params.request_id = -1; + params.expect_response = false; + } + + params.arguments.Append(base::Value::CreateStringValue(command)); + + Send(new CefMsg_Request(routing_id(), params)); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendCommand, this, frame_id, command, + responseHandler)); + } +} + +void CefBrowserHostImpl::SendCode( + int64 frame_id, + bool is_javascript, + const std::string& code, + const std::string& script_url, + int script_start_line, + CefRefPtr responseHandler) { + // Only known frame ids are supported. + DCHECK(frame_id >= CefFrameHostImpl::kMainFrameId); + DCHECK(!code.empty()); + DCHECK_GE(script_start_line, 0); + + // Execute on the UI thread because CefResponseManager is not thread safe. + if (CEF_CURRENTLY_ON_UIT()) { + TRACE_EVENT2("libcef", "CefBrowserHostImpl::SendCommand", + "frame_id", frame_id, + "needsResponse", responseHandler.get() ? 1 : 0); + Cef_Request_Params params; + params.name = "execute-code"; + params.frame_id = frame_id; + params.user_initiated = false; + + if (responseHandler.get()) { + params.request_id = response_manager_->RegisterHandler(responseHandler); + params.expect_response = true; + } else { + params.request_id = -1; + params.expect_response = false; + } + + params.arguments.Append(base::Value::CreateBooleanValue(is_javascript)); + params.arguments.Append(base::Value::CreateStringValue(code)); + params.arguments.Append(base::Value::CreateStringValue(script_url)); + params.arguments.Append(base::Value::CreateIntegerValue(script_start_line)); + + Send(new CefMsg_Request(routing_id(), params)); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::SendCode, this, frame_id, is_javascript, + code, script_url, script_start_line, responseHandler)); + } +} + +bool CefBrowserHostImpl::SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated) { + DCHECK_EQ(PID_RENDERER, target_process); + DCHECK(!name.empty()); + + Cef_Request_Params params; + params.name = name; + if (arguments) + params.arguments.Swap(arguments); + params.frame_id = -1; + params.user_initiated = user_initiated; + params.request_id = -1; + params.expect_response = false; + + return Send(new CefMsg_Request(routing_id(), params)); +} + +bool CefBrowserHostImpl::ViewText(const std::string& text) { + return PlatformViewText(text); +} + +void CefBrowserHostImpl::HandleExternalProtocol(const GURL& url) { + if (CEF_CURRENTLY_ON_UIT()) { + bool allow_os_execution = false; + + if (client_.get()) { + CefRefPtr handler = client_->GetRequestHandler(); + if (handler.get()) + handler->OnProtocolExecution(this, url.spec(), allow_os_execution); + } + + if (allow_os_execution) + PlatformHandleExternalProtocol(url); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::HandleExternalProtocol, this, url)); + } +} + +int CefBrowserHostImpl::browser_id() const { + return browser_info_->browser_id(); +} + +GURL CefBrowserHostImpl::GetLoadingURL() { + base::AutoLock lock_scope(state_lock_); + return loading_url_; +} + +void CefBrowserHostImpl::OnSetFocus(cef_focus_source_t source) { + if (CEF_CURRENTLY_ON_UIT()) { + // SetFocus() might be called while inside the OnSetFocus() callback. If so, + // don't re-enter the callback. + if (!is_in_onsetfocus_) { + if (client_.get()) { + CefRefPtr handler = client_->GetFocusHandler(); + if (handler.get()) { + is_in_onsetfocus_ = true; + bool handled = handler->OnSetFocus(this, source); + is_in_onsetfocus_ = false; + + if (handled) + return; + } + } + } + + PlatformSetFocus(true); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::OnSetFocus, this, source)); + } +} + +void CefBrowserHostImpl::RunFileChooser( + const content::FileChooserParams& params, + const RunFileChooserCallback& callback) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::RunFileChooserOnUIThread, this, params, + callback)); +} + +#if !defined(OS_MACOSX) +CefTextInputContext CefBrowserHostImpl::GetNSTextInputContext() { + NOTREACHED(); + return NULL; +} + +void CefBrowserHostImpl::HandleKeyEventBeforeTextInputClient( + CefEventHandle keyEvent) { + NOTREACHED(); +} + +void CefBrowserHostImpl::HandleKeyEventAfterTextInputClient( + CefEventHandle keyEvent) { + NOTREACHED(); +} +#endif // !defined(OS_MACOSX) + +void CefBrowserHostImpl::DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, + CefBrowserHost::DragOperationsMask allowed_ops) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragTargetDragEnter, this, drag_data, + event, allowed_ops)); + return; + } + + if (!drag_data.get()) { + NOTREACHED(); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + int screenX, screenY; + + if (!client_->GetRenderHandler()->GetScreenPoint( + this, event.x, event.y, screenX, screenY)) { + screenX = event.x; + screenY = event.y; + } + + CefDragDataImpl* data_impl = static_cast(drag_data.get()); + base::AutoLock lock_scope(data_impl->lock()); + const content::DropData& drop_data = data_impl->drop_data(); + gfx::Point client_pt(event.x, event.y); + gfx::Point screen_pt(screenX, screenY); + blink::WebDragOperationsMask ops = + static_cast(allowed_ops); + int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers); + + rvh->DragTargetDragEnter(drop_data, client_pt, screen_pt, ops, modifiers); +} + +void CefBrowserHostImpl::DragTargetDragOver(const CefMouseEvent& event, + CefBrowserHost::DragOperationsMask allowed_ops) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragTargetDragOver, this, event, + allowed_ops)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + int screenX, screenY; + + if (!client_->GetRenderHandler()->GetScreenPoint( + this, event.x, event.y, screenX, screenY)) { + screenX = event.x; + screenY = event.y; + } + + gfx::Point client_pt(event.x, event.y); + gfx::Point screen_pt(screenX, screenY); + blink::WebDragOperationsMask ops = + static_cast(allowed_ops); + int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers); + + rvh->DragTargetDragOver(client_pt, screen_pt, ops, modifiers); +} + +void CefBrowserHostImpl::DragTargetDragLeave() { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragTargetDragLeave, this)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + rvh->DragTargetDragLeave(); +} + +void CefBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragTargetDrop, this, event)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + int screenX, screenY; + + if (!client_->GetRenderHandler()->GetScreenPoint( + this, event.x, event.y, screenX, screenY)) { + screenX = event.x; + screenY = event.y; + } + + gfx::Point client_pt(event.x, event.y); + gfx::Point screen_pt(screenX, screenY); + int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers); + + rvh->DragTargetDrop(client_pt, screen_pt, modifiers); +} + +void CefBrowserHostImpl::DragSourceSystemDragEnded() { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragSourceSystemDragEnded, this)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + rvh->DragSourceSystemDragEnded(); +} + +void CefBrowserHostImpl::DragSourceEndedAt( + int x, int y, CefBrowserHost::DragOperationsMask op) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::DragSourceEndedAt, this, x, y, op)); + return; + } + + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + content::RenderViewHost* rvh = + web_contents() ? web_contents()->GetRenderViewHost() : NULL; + if (!rvh) + return; + + int screenX, screenY; + + if (!client_->GetRenderHandler()->GetScreenPoint( + this, x, y, screenX, screenY)) { + screenX = x; + screenY = y; + } + + blink::WebDragOperation drag_op = static_cast(op); + + rvh->DragSourceEndedAt(x, y, screenX, screenY, drag_op); +} + + +// content::WebContentsDelegate methods. +// ----------------------------------------------------------------------------- + +content::WebContents* CefBrowserHostImpl::OpenURLFromTab( + content::WebContents* source, + const content::OpenURLParams& params) { + // Start a navigation that will result in the creation of a new render + // process. + LoadURL(CefFrameHostImpl::kMainFrameId, params.url.spec(), params.referrer, + params.transition, params.extra_headers); + + return source; +} + +void CefBrowserHostImpl::LoadingStateChanged(content::WebContents* source, + bool to_different_document) { + int current_index = + web_contents_->GetController().GetLastCommittedEntryIndex(); + int max_index = web_contents_->GetController().GetEntryCount() - 1; + + bool is_loading, can_go_back, can_go_forward; + + { + base::AutoLock lock_scope(state_lock_); + is_loading = is_loading_ = web_contents_->IsLoading(); + can_go_back = can_go_back_ = (current_index > 0); + can_go_forward = can_go_forward_ = (current_index < max_index); + } + + if (client_.get()) { + CefRefPtr handler = client_->GetLoadHandler(); + if (handler.get()) { + handler->OnLoadingStateChange(this, is_loading, can_go_back, + can_go_forward); + } + } +} + +void CefBrowserHostImpl::CloseContents(content::WebContents* source) { + if (destruction_state_ == DESTRUCTION_STATE_COMPLETED) + return; + + bool close_browser = true; + + // If this method is called in response to something other than + // WindowDestroyed() ask the user if the browser should close. + if (client_.get() && (IsWindowless() || !window_destroyed_)) { + CefRefPtr handler = + client_->GetLifeSpanHandler(); + if (handler.get()) { + close_browser = !handler->DoClose(this); + } + } + + if (close_browser) { + if (destruction_state_ != DESTRUCTION_STATE_ACCEPTED) + destruction_state_ = DESTRUCTION_STATE_ACCEPTED; + + if (!IsWindowless() && !window_destroyed_) { + // A window exists so try to close it using the platform method. Will + // result in a call to WindowDestroyed() if/when the window is destroyed + // via the platform window destruction mechanism. + PlatformCloseWindow(); + } else { + // Keep a reference to the browser while it's in the process of being + // destroyed. + CefRefPtr browser(this); + + // No window exists. Destroy the browser immediately. + DestroyBrowser(); + if (!IsWindowless()) { + // Release the reference added in PlatformCreateWindow(). + Release(); + } + } + } else if (destruction_state_ != DESTRUCTION_STATE_NONE) { + destruction_state_ = DESTRUCTION_STATE_NONE; + } +} + +void CefBrowserHostImpl::UpdateTargetURL(content::WebContents* source, + int32 page_id, + const GURL& url) { + if (client_.get()) { + CefRefPtr handler = client_->GetDisplayHandler(); + if (handler.get()) + handler->OnStatusMessage(this, url.spec()); + } +} + +bool CefBrowserHostImpl::AddMessageToConsole(content::WebContents* source, + int32 level, + const base::string16& message, + int32 line_no, + const base::string16& source_id) { + if (client_.get()) { + CefRefPtr handler = client_->GetDisplayHandler(); + if (handler.get()) + return handler->OnConsoleMessage(this, message, source_id, line_no); + } + + return false; +} + +void CefBrowserHostImpl::BeforeUnloadFired(content::WebContents* source, + bool proceed, + bool* proceed_to_fire_unload) { + if (destruction_state_ == DESTRUCTION_STATE_ACCEPTED || proceed) { + *proceed_to_fire_unload = true; + } else if (!proceed) { + *proceed_to_fire_unload = false; + destruction_state_ = DESTRUCTION_STATE_NONE; + } +} + +bool CefBrowserHostImpl::TakeFocus(content::WebContents* source, + bool reverse) { + if (client_.get()) { + CefRefPtr handler = client_->GetFocusHandler(); + if (handler.get()) + handler->OnTakeFocus(this, !reverse); + } + + return false; +} + +void CefBrowserHostImpl::WebContentsFocused(content::WebContents* contents) { + if (client_.get()) { + CefRefPtr handler = client_->GetFocusHandler(); + if (handler.get()) + handler->OnGotFocus(this); + } +} + +bool CefBrowserHostImpl::HandleContextMenu( + const content::ContextMenuParams& params) { + if (!menu_creator_.get()) + menu_creator_.reset(new CefMenuCreator(this)); + return menu_creator_->CreateContextMenu(params); +} + +bool CefBrowserHostImpl::PreHandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event, + bool* is_keyboard_shortcut) { + if (client_.get()) { + CefRefPtr handler = client_->GetKeyboardHandler(); + if (handler.get()) { + CefKeyEvent cef_event; + if (!GetCefKeyEvent(event, cef_event)) + return false; + + cef_event.focus_on_editable_field = focus_on_editable_field_; + + return handler->OnPreKeyEvent(this, cef_event, GetCefEventHandle(event), + is_keyboard_shortcut); + } + } + + return false; +} + +void CefBrowserHostImpl::HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) { + // Check to see if event should be ignored. + if (event.skip_in_browser) + return; + + if (client_.get()) { + CefRefPtr handler = client_->GetKeyboardHandler(); + if (handler.get()) { + CefKeyEvent cef_event; + if (GetCefKeyEvent(event, cef_event)) { + cef_event.focus_on_editable_field = focus_on_editable_field_; + + if (handler->OnKeyEvent(this, cef_event, GetCefEventHandle(event))) + return; + } + } + } + + PlatformHandleKeyboardEvent(event); +} + +bool CefBrowserHostImpl::CanDragEnter( + content::WebContents* source, + const content::DropData& data, + blink::WebDragOperationsMask mask) { + CefRefPtr handler = client_->GetDragHandler(); + if (handler.get()) { + CefRefPtr drag_data(new CefDragDataImpl(data)); + drag_data->SetReadOnly(true); + if (handler->OnDragEnter( + this, + drag_data.get(), + static_cast(mask))) { + return false; + } + } + return true; +} + +bool CefBrowserHostImpl::ShouldCreateWebContents( + content::WebContents* web_contents, + int route_id, + WindowContainerType window_container_type, + const base::string16& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace, + content::WebContentsView** view, + content::RenderViewHostDelegateView** delegate_view) { + // In cases where the navigation will occur in a new render process the + // |route_id| value will be MSG_ROUTING_NONE here (because the existing + // renderer will not be able to communicate with the new renderer) and + // OpenURLFromTab will be called after WebContentsCreated. + base::AutoLock lock_scope(pending_popup_info_lock_); + DCHECK(pending_popup_info_.get()); + if (pending_popup_info_->window_info.windowless_rendering_enabled) { + // Use the OSR view instead of the default view. + CefWebContentsViewOSR* view_or = new CefWebContentsViewOSR( + web_contents, + CefContentBrowserClient::Get()->GetWebContentsViewDelegate( + web_contents)); + *view = view_or; + *delegate_view = view_or; + } + + return true; +} + +void CefBrowserHostImpl::WebContentsCreated( + content::WebContents* source_contents, + int opener_render_frame_id, + const base::string16& frame_name, + const GURL& target_url, + content::WebContents* new_contents) { + scoped_ptr pending_popup_info; + { + base::AutoLock lock_scope(pending_popup_info_lock_); + pending_popup_info.reset(pending_popup_info_.release()); + } + DCHECK(pending_popup_info.get()); + + content::RenderViewHost* view_host = new_contents->GetRenderViewHost(); + content::RenderFrameHost* main_frame_host = new_contents->GetMainFrame(); + + CefWindowHandle opener = kNullWindowHandle; + scoped_refptr info = + CefContentBrowserClient::Get()->GetOrCreateBrowserInfo( + view_host->GetProcess()->GetID(), + view_host->GetRoutingID(), + main_frame_host->GetProcess()->GetID(), + main_frame_host->GetRoutingID()); + + if (source_contents) { + DCHECK(info->is_popup()); + opener = GetBrowserForContents(source_contents)->GetWindowHandle(); + } else { + DCHECK(!info->is_popup()); + } + + CefRefPtr browser = + CefBrowserHostImpl::CreateInternal(pending_popup_info->window_info, + pending_popup_info->settings, + pending_popup_info->client, + new_contents, info, opener, NULL); +} + +void CefBrowserHostImpl::DidNavigateMainFramePostCommit( + content::WebContents* tab) { + base::AutoLock lock_scope(state_lock_); + has_document_ = false; +} + +content::JavaScriptDialogManager* + CefBrowserHostImpl::GetJavaScriptDialogManager() { + if (!dialog_manager_.get()) + dialog_manager_.reset(new CefJavaScriptDialogManager(this)); + return dialog_manager_.get(); +} + +void CefBrowserHostImpl::RunFileChooser( + content::WebContents* tab, + const content::FileChooserParams& params) { + content::RenderViewHost* render_view_host = tab->GetRenderViewHost(); + if (!render_view_host) + return; + + RunFileChooserOnUIThread(params, + base::Bind(&CefBrowserHostImpl::OnRunFileChooserDelegateCallback, this, + tab, params.mode)); +} + +bool CefBrowserHostImpl::SetPendingPopupInfo( + scoped_ptr info) { + base::AutoLock lock_scope(pending_popup_info_lock_); + if (pending_popup_info_.get()) + return false; + pending_popup_info_.reset(info.release()); + return true; +} + +base::WeakPtr CefBrowserHostImpl::GetWeakPtr() { + CEF_REQUIRE_UIT(); + return weak_ptr_factory_.GetWeakPtr(); +} + +void CefBrowserHostImpl::UpdatePreferredSize(content::WebContents* source, + const gfx::Size& pref_size) { + PlatformSizeTo(pref_size.width(), pref_size.height()); +} + +void CefBrowserHostImpl::RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback) { + CEF_REQUIRE_UIT(); + + content::MediaStreamDevices devices; + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kEnableMediaStream)) { + // Cancel the request. + callback.Run(devices, content::MEDIA_DEVICE_PERMISSION_DENIED, + scoped_ptr()); + return; + } + + // Based on chrome/browser/media/media_stream_devices_controller.cc + bool microphone_requested = + (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE); + bool webcam_requested = + (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE); + if (microphone_requested || webcam_requested) { + switch (request.request_type) { + case content::MEDIA_OPEN_DEVICE: + // For open device request pick the desired device or fall back to the + // first available of the given type. + CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice( + (microphone_requested ? request.requested_audio_device_id : + request.requested_video_device_id), + microphone_requested, + webcam_requested, + &devices); + break; + case content::MEDIA_DEVICE_ACCESS: + case content::MEDIA_GENERATE_STREAM: + case content::MEDIA_ENUMERATE_DEVICES: + // Get the default devices for the request. + CefMediaCaptureDevicesDispatcher::GetInstance()-> + GetDefaultDevices(CefContentBrowserClient::Get()->pref_service(), + microphone_requested, + webcam_requested, + &devices); + break; + } + } + + callback.Run(devices, content::MEDIA_DEVICE_OK, + scoped_ptr()); +} + + +// content::WebContentsObserver methods. +// ----------------------------------------------------------------------------- + +void CefBrowserHostImpl::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { + browser_info_->add_render_frame_id(render_frame_host->GetProcess()->GetID(), + render_frame_host->GetRoutingID()); +} + +void CefBrowserHostImpl::RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) { + browser_info_->remove_render_frame_id( + render_frame_host->GetProcess()->GetID(), + render_frame_host->GetRoutingID()); +} + +void CefBrowserHostImpl::RenderViewCreated( + content::RenderViewHost* render_view_host) { + browser_info_->add_render_view_id(render_view_host->GetProcess()->GetID(), + render_view_host->GetRoutingID()); + + // May be already registered if the renderer crashed previously. + if (!registrar_->IsRegistered( + this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, + content::Source(render_view_host))) { + registrar_->Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, + content::Source(render_view_host)); + } +} + +void CefBrowserHostImpl::RenderViewDeleted( + content::RenderViewHost* render_view_host) { + browser_info_->remove_render_view_id(render_view_host->GetProcess()->GetID(), + render_view_host->GetRoutingID()); + + if (registrar_->IsRegistered( + this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, + content::Source(render_view_host))) { + registrar_->Remove(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, + content::Source(render_view_host)); + } +} + +void CefBrowserHostImpl::RenderViewReady() { + // Send the queued messages. + queue_messages_ = false; + while (!queued_messages_.empty()) { + Send(queued_messages_.front()); + queued_messages_.pop(); + } +} + +void CefBrowserHostImpl::RenderProcessGone(base::TerminationStatus status) { + queue_messages_ = true; + + cef_termination_status_t ts = TS_ABNORMAL_TERMINATION; + if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) + ts = TS_PROCESS_WAS_KILLED; + else if (status == base::TERMINATION_STATUS_PROCESS_CRASHED) + ts = TS_PROCESS_CRASHED; + else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION) + return; + + if (client_.get()) { + CefRefPtr handler = client_->GetRequestHandler(); + if (handler.get()) + handler->OnRenderProcessTerminated(this, ts); + } +} + +void CefBrowserHostImpl::DidCommitProvisionalLoadForFrame( + int64 frame_id, + const base::string16& frame_unique_name, + bool is_main_frame, + const GURL& url, + content::PageTransition transition_type, + content::RenderViewHost* render_view_host) { + CefRefPtr frame = GetOrCreateFrame(frame_id, + CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, base::string16(), + url); + OnLoadStart(frame, url, transition_type); + if (is_main_frame) + OnAddressChange(frame, url); +} + +void CefBrowserHostImpl::DidFailProvisionalLoad( + int64 frame_id, + const base::string16& frame_unique_name, + bool is_main_frame, + const GURL& validated_url, + int error_code, + const base::string16& error_description, + content::RenderViewHost* render_view_host) { + CefRefPtr frame = GetOrCreateFrame(frame_id, + CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, base::string16(), + GURL()); + OnLoadError(frame, validated_url, error_code, error_description); +} + +void CefBrowserHostImpl::DocumentAvailableInMainFrame() { + base::AutoLock lock_scope(state_lock_); + has_document_ = true; +} + +void CefBrowserHostImpl::DidFailLoad( + int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + int error_code, + const base::string16& error_description, + content::RenderViewHost* render_view_host) { + CefRefPtr frame = GetOrCreateFrame(frame_id, + CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, base::string16(), + validated_url); + OnLoadError(frame, validated_url, error_code, error_description); + OnLoadEnd(frame, validated_url, error_code); +} + +void CefBrowserHostImpl::PluginCrashed(const base::FilePath& plugin_path, + base::ProcessId plugin_pid) { + if (client_.get()) { + CefRefPtr handler = client_->GetRequestHandler(); + if (handler.get()) + handler->OnPluginCrashed(this, plugin_path.value()); + } +} + +bool CefBrowserHostImpl::OnMessageReceived(const IPC::Message& message) { + // Handle the cursor message here if mouse cursor change is disabled instead + // of propegating the message to the normal handler. + if (message.type() == ViewHostMsg_SetCursor::ID) + return IsMouseCursorChangeDisabled(); + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CefBrowserHostImpl, message) + IPC_MESSAGE_HANDLER(CefHostMsg_FrameIdentified, OnFrameIdentified) + IPC_MESSAGE_HANDLER(CefHostMsg_FrameDetached, DetachFrame) + IPC_MESSAGE_HANDLER(CefHostMsg_FrameFocusChange, SetFocusedFrame) + IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad) + IPC_MESSAGE_HANDLER(CefHostMsg_LoadingURLChange, OnLoadingURLChange) + IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest) + IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse) + IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PDFHasUnsupportedFeature, + OnPDFHasUnsupportedFeature) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PDFSaveURLAs, OnPDFSaveURLAs) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PDFUpdateContentRestrictions, + OnPDFUpdateContentRestrictions) + IPC_MESSAGE_HANDLER_DELAY_REPLY( + ChromeViewHostMsg_PDFModalPromptForPassword, + OnPDFModalPromptForPassword) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool CefBrowserHostImpl::Send(IPC::Message* message) { + if (CEF_CURRENTLY_ON_UIT()) { + if (queue_messages_) { + queued_messages_.push(message); + return true; + } else { + return content::WebContentsObserver::Send(message); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(&CefBrowserHostImpl::Send), this, + message)); + return true; + } +} + + +// content::WebContentsObserver::OnMessageReceived() message handlers. +// ----------------------------------------------------------------------------- + +void CefBrowserHostImpl::OnFrameIdentified(int64 frame_id, + int64 parent_frame_id, + base::string16 name) { + bool is_main_frame = (parent_frame_id == CefFrameHostImpl::kMainFrameId); + GetOrCreateFrame(frame_id, parent_frame_id, is_main_frame, name, GURL()); +} + +void CefBrowserHostImpl::OnDidFinishLoad(int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + int http_status_code) { + CefRefPtr frame = GetOrCreateFrame(frame_id, + CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, base::string16(), + validated_url); + + // Give internal scheme handlers an opportunity to update content. + scheme::DidFinishLoad(frame, validated_url); + + OnLoadEnd(frame, validated_url, http_status_code); +} + +void CefBrowserHostImpl::OnLoadingURLChange(const GURL& loading_url) { + base::AutoLock lock_scope(state_lock_); + loading_url_ = loading_url; +} + +void CefBrowserHostImpl::OnRequest(const Cef_Request_Params& params) { + bool success = false; + std::string response; + bool expect_response_ack = false; + + if (params.user_initiated) { + // Give the user a chance to handle the request. + if (client_.get()) { + CefRefPtr message( + new CefProcessMessageImpl(const_cast(¶ms), + false, true)); + success = client_->OnProcessMessageReceived(this, PID_RENDERER, + message.get()); + message->Detach(NULL); + } + } else { + // Invalid request. + NOTREACHED(); + } + + if (params.expect_response) { + DCHECK_GE(params.request_id, 0); + + // Send a response to the renderer. + Cef_Response_Params response_params; + response_params.request_id = params.request_id; + response_params.success = success; + response_params.response = response; + response_params.expect_response_ack = expect_response_ack; + Send(new CefMsg_Response(routing_id(), response_params)); + } +} + +void CefBrowserHostImpl::OnResponse(const Cef_Response_Params& params) { + response_manager_->RunHandler(params); + if (params.expect_response_ack) + Send(new CefMsg_ResponseAck(routing_id(), params.request_id)); +} + +void CefBrowserHostImpl::OnResponseAck(int request_id) { + response_manager_->RunAckHandler(request_id); +} + +void CefBrowserHostImpl::OnPDFHasUnsupportedFeature() { + // TODO(cef): Use Adobe PDF plugin instead. See PDFHasUnsupportedFeature in + // chrome/browser/ui/pdf/pdf_unsupported_feature.cc. +} + +void CefBrowserHostImpl::OnPDFSaveURLAs( + const GURL& url, + const content::Referrer& referrer) { + web_contents()->SaveFrame(url, referrer); +} + +void CefBrowserHostImpl::OnPDFUpdateContentRestrictions( + int content_restrictions) { + // TODO(cef): Add support for communicating PDF content restrictions. +} + +void CefBrowserHostImpl::OnPDFModalPromptForPassword( + const std::string& prompt, + IPC::Message* reply_message) { + // TODO(cef): Add support for PDF password prompt. + OnPDFModalPromptForPasswordClosed(reply_message, false, base::string16()); +} + +void CefBrowserHostImpl::OnPDFModalPromptForPasswordClosed( + IPC::Message* reply_message, + bool success, + const base::string16& actual_value) { + ChromeViewHostMsg_PDFModalPromptForPassword::WriteReplyParams( + reply_message, base::UTF16ToUTF8(actual_value)); + Send(reply_message); +} + + +// content::NotificationObserver methods. +// ----------------------------------------------------------------------------- + +void CefBrowserHostImpl::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(type == content::NOTIFICATION_LOAD_STOP || + type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE || + type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED); + + if (type == content::NOTIFICATION_LOAD_STOP || + type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) { + base::string16 title; + + if (type == content::NOTIFICATION_LOAD_STOP) { + content::NavigationController* controller = + content::Source(source).ptr(); + title = controller->GetWebContents()->GetTitle(); + } else { + content::WebContents* web_contents = + content::Source(source).ptr(); + title = web_contents->GetTitle(); + } + + // Don't notify if the title hasn't changed. + if (title == title_) + return; + + title_ = title; + + if (client_.get()) { + CefRefPtr handler = client_->GetDisplayHandler(); + if (handler.get()) + handler->OnTitleChange(this, title); + } + } else if (type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE) { + focus_on_editable_field_ = *content::Details(details).ptr(); + } +} + + +// CefBrowserHostImpl private methods. +// ----------------------------------------------------------------------------- + +CefBrowserHostImpl::CefBrowserHostImpl( + const CefWindowInfo& window_info, + const CefBrowserSettings& settings, + CefRefPtr client, + content::WebContents* web_contents, + scoped_refptr browser_info, + CefWindowHandle opener) + : content::WebContentsObserver(web_contents), + window_info_(window_info), + settings_(settings), + client_(client), + browser_info_(browser_info), + opener_(opener), + is_loading_(false), + can_go_back_(false), + can_go_forward_(false), + has_document_(false), + queue_messages_(true), + main_frame_id_(CefFrameHostImpl::kInvalidFrameId), + focused_frame_id_(CefFrameHostImpl::kInvalidFrameId), + destruction_state_(DESTRUCTION_STATE_NONE), + window_destroyed_(false), + is_in_onsetfocus_(false), + focus_on_editable_field_(false), + mouse_cursor_change_disabled_(false), + devtools_frontend_(NULL), + file_chooser_pending_(false), + weak_ptr_factory_(this) { +#if defined(USE_AURA) + window_widget_ = NULL; +#endif +#if defined(USE_X11) + window_x11_ = NULL; +#endif + + DCHECK(!browser_info_->browser().get()); + browser_info_->set_browser(this); + + web_contents_.reset(web_contents); + web_contents->SetDelegate(this); + + CefBrowserContext* browser_context = + static_cast(web_contents->GetBrowserContext()); + request_context_ = new CefRequestContextImpl(browser_context); + + registrar_.reset(new content::NotificationRegistrar); + registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, + content::Source(web_contents)); + + // When navigating through the history, the restored NavigationEntry's title + // will be used. If the entry ends up having the same title after we return + // to it, as will usually be the case, the + // NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED will then be suppressed, since the + // NavigationEntry's title hasn't changed. + registrar_->Add(this, content::NOTIFICATION_LOAD_STOP, + content::Source( + &web_contents->GetController())); + + response_manager_.reset(new CefResponseManager); + + placeholder_frame_ = + new CefFrameHostImpl(this, CefFrameHostImpl::kInvalidFrameId, true, + CefString(), CefString(), + CefFrameHostImpl::kInvalidFrameId); + + printing::PrintViewManager::CreateForWebContents(web_contents_.get()); + + // Make sure RenderViewCreated is called at least one time. + RenderViewCreated(web_contents->GetRenderViewHost()); + + if (IsWindowless()) { + CefRenderWidgetHostViewOSR* view = + static_cast( + web_contents->GetRenderViewHost()->GetView()); + if (view) + view->set_browser_impl(this); + } +} + +CefRefPtr CefBrowserHostImpl::GetOrCreateFrame( + int64 frame_id, int64 parent_frame_id, bool is_main_frame, + base::string16 frame_name, const GURL& frame_url) { + DCHECK(frame_id > CefFrameHostImpl::kInvalidFrameId); + if (frame_id <= CefFrameHostImpl::kInvalidFrameId) + return NULL; + + CefString url; + if (frame_url.is_valid()) + url = frame_url.spec(); + + CefString name; + if (!frame_name.empty()) + name = frame_name; + + CefRefPtr frame; + bool frame_created = false; + + { + base::AutoLock lock_scope(state_lock_); + + if (is_main_frame) + main_frame_id_ = frame_id; + + // Check if a frame object already exists. + FrameMap::const_iterator it = frames_.find(frame_id); + if (it != frames_.end()) + frame = it->second.get(); + + if (!frame.get()) { + frame = new CefFrameHostImpl(this, frame_id, is_main_frame, url, name, + parent_frame_id); + frame_created = true; + frames_.insert(std::make_pair(frame_id, frame)); + } + } + + if (!frame_created) + frame->SetAttributes(url, name, parent_frame_id); + + return frame.get(); +} + +void CefBrowserHostImpl::DetachFrame(int64 frame_id) { + base::AutoLock lock_scope(state_lock_); + + FrameMap::iterator it = frames_.find(frame_id); + if (it != frames_.end()) { + it->second->Detach(); + frames_.erase(it); + } + + if (main_frame_id_ == frame_id) + main_frame_id_ = CefFrameHostImpl::kInvalidFrameId; + if (focused_frame_id_ == frame_id) + focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId; +} + +void CefBrowserHostImpl::DetachAllFrames() { + FrameMap frames; + + { + base::AutoLock lock_scope(state_lock_); + + frames = frames_; + frames_.clear(); + + if (main_frame_id_ != CefFrameHostImpl::kInvalidFrameId) + main_frame_id_ = CefFrameHostImpl::kInvalidFrameId; + if (focused_frame_id_ != CefFrameHostImpl::kInvalidFrameId) + focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId; + } + + FrameMap::const_iterator it = frames.begin(); + for (; it != frames.end(); ++it) + it->second->Detach(); +} + +void CefBrowserHostImpl::SetFocusedFrame(int64 frame_id) { + CefRefPtr unfocused_frame; + CefRefPtr focused_frame; + + { + base::AutoLock lock_scope(state_lock_); + + if (focused_frame_id_ != CefFrameHostImpl::kInvalidFrameId) { + // Unfocus the previously focused frame. + FrameMap::const_iterator it = frames_.find(frame_id); + if (it != frames_.end()) + unfocused_frame = it->second; + } + + if (frame_id != CefFrameHostImpl::kInvalidFrameId) { + // Focus the newly focused frame. + FrameMap::iterator it = frames_.find(frame_id); + if (it != frames_.end()) + focused_frame = it->second; + } + + focused_frame_id_ = + focused_frame ? frame_id : CefFrameHostImpl::kInvalidFrameId; + } + + if (unfocused_frame) + unfocused_frame->SetFocused(false); + if (focused_frame) + focused_frame->SetFocused(true); +} + +void CefBrowserHostImpl::OnAddressChange(CefRefPtr frame, + const GURL& url) { + if (client_.get()) { + CefRefPtr handler = client_->GetDisplayHandler(); + if (handler.get()) { + // Notify the handler of an address change. + handler->OnAddressChange(this, GetMainFrame(), url.spec()); + } + } +} + +void CefBrowserHostImpl::OnLoadStart(CefRefPtr frame, + const GURL& url, + content::PageTransition transition_type) { + if (client_.get()) { + CefRefPtr handler = client_->GetLoadHandler(); + if (handler.get()) { + // Notify the handler that loading has started. + handler->OnLoadStart(this, frame); + } + } +} + +void CefBrowserHostImpl::OnLoadError(CefRefPtr frame, + const GURL& url, + int error_code, + const base::string16& error_description) { + if (client_.get()) { + CefRefPtr handler = client_->GetLoadHandler(); + if (handler.get()) { + // Notify the handler that loading has failed. + handler->OnLoadError(this, frame, + static_cast(error_code), + CefString(error_description), + url.spec()); + } + } +} + +void CefBrowserHostImpl::OnLoadEnd(CefRefPtr frame, + const GURL& url, + int http_status_code) { + if (client_.get()) { + CefRefPtr handler = client_->GetLoadHandler(); + if (handler.get()) + handler->OnLoadEnd(this, frame, http_status_code); + } +} + +void CefBrowserHostImpl::RunFileChooserOnUIThread( + const content::FileChooserParams& params, + const RunFileChooserCallback& callback) { + CEF_REQUIRE_UIT(); + + if (file_chooser_pending_) { + // Dismiss the new dialog immediately. + callback.Run(std::vector()); + return; + } + + if (params.mode == content::FileChooserParams::UploadFolder) { + NOTIMPLEMENTED(); + callback.Run(std::vector()); + return; + } + + file_chooser_pending_ = true; + + // Ensure that the |file_chooser_pending_| flag is cleared. + const RunFileChooserCallback& host_callback = + base::Bind(&CefBrowserHostImpl::OnRunFileChooserCallback, this, callback); + + bool handled = false; + + if (client_.get()) { + CefRefPtr handler = client_->GetDialogHandler(); + if (handler.get()) { + cef_file_dialog_mode_t mode = FILE_DIALOG_OPEN; + switch (params.mode) { + case content::FileChooserParams::Open: + mode = FILE_DIALOG_OPEN; + break; + case content::FileChooserParams::OpenMultiple: + mode = FILE_DIALOG_OPEN_MULTIPLE; + break; + case content::FileChooserParams::Save: + mode = FILE_DIALOG_SAVE; + break; + default: + NOTREACHED(); + break; + } + + std::vector accept_types; + std::vector::const_iterator it = + params.accept_types.begin(); + for (; it != params.accept_types.end(); ++it) + accept_types.push_back(*it); + + CefRefPtr callbackImpl( + new CefFileDialogCallbackImpl(host_callback)); + handled = handler->OnFileDialog(this, mode, params.title, + params.default_file_name.value(), + accept_types, callbackImpl.get()); + if (!handled) { + if (callbackImpl->IsConnected()) { + callbackImpl->Disconnect(); + } else { + // User executed the callback even though they returned false. + NOTREACHED(); + handled = true; + } + } + } + } + + if (!handled) + PlatformRunFileChooser(params, host_callback); +} + +void CefBrowserHostImpl::OnRunFileChooserCallback( + const RunFileChooserCallback& callback, + const std::vector& file_paths) { + CEF_REQUIRE_UIT(); + + file_chooser_pending_ = false; + + // Execute the callback asynchronously. + CEF_POST_TASK(CEF_UIT, base::Bind(callback, file_paths)); +} + +void CefBrowserHostImpl::OnRunFileChooserDelegateCallback( + content::WebContents* tab, + content::FileChooserParams::Mode mode, + const std::vector& file_paths) { + CEF_REQUIRE_UIT(); + + content::RenderViewHost* render_view_host = tab->GetRenderViewHost(); + if (!render_view_host) + return; + + // Convert FilePath list to SelectedFileInfo list. + std::vector selected_files; + for (size_t i = 0; i < file_paths.size(); ++i) { + selected_files.push_back( + ui::SelectedFileInfo(file_paths[i], base::FilePath())); + } + + // Notify our RenderViewHost in all cases. + render_view_host->FilesSelectedInChooser(selected_files, mode); +} + +void CefBrowserHostImpl::OnDevToolsWebContentsDestroyed() { + devtools_observer_.reset(); + devtools_frontend_ = NULL; +} diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h new file mode 100644 index 000000000..fc44d0056 --- /dev/null +++ b/libcef/browser/browser_host_impl.h @@ -0,0 +1,679 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_ +#pragma once + +#include +#include +#include +#include + +#include "include/cef_browser.h" +#include "include/cef_client.h" +#include "include/cef_frame.h" +#include "libcef/browser/frame_host_impl.h" +#include "libcef/browser/javascript_dialog_manager.h" +#include "libcef/browser/menu_creator.h" +#include "libcef/common/response_manager.h" + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "base/synchronization/lock.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/common/file_chooser_params.h" + +#if defined(USE_AURA) +#include "third_party/WebKit/public/platform/WebCursorInfo.h" +#include "ui/base/cursor/cursor.h" +#endif + +#if defined(USE_X11) +#include "ui/base/x/x11_util.h" +#endif + +namespace content { +struct NativeWebKeyboardEvent; +} + +namespace blink { +class WebMouseEvent; +class WebMouseWheelEvent; +class WebInputEvent; +} + +namespace net { +class URLRequest; +} + +#if defined(USE_AURA) +namespace views { +class Widget; +} +#endif + +#if defined(USE_X11) +class CefWindowX11; +#endif + +struct Cef_Request_Params; +struct Cef_Response_Params; +class CefBrowserInfo; +class CefDevToolsFrontend; +struct CefNavigateParams; +class SiteInstance; + +// Implementation of CefBrowser. +// +// WebContentsDelegate: Interface for handling WebContents delegations. There is +// a one-to-one relationship between CefBrowserHostImpl and WebContents +// instances. +// +// WebContentsObserver: Interface for observing WebContents notifications and +// IPC messages. There is a one-to-one relationship between WebContents and +// RenderViewHost instances. IPC messages received by the RenderViewHost will be +// forwarded to this WebContentsObserver implementation via WebContents. IPC +// messages sent using CefBrowserHostImpl::Send() will be forwarded to the +// RenderViewHost (after posting to the UI thread if necessary). Use +// WebContentsObserver::routing_id() when sending IPC messages. +// +// NotificationObserver: Interface for observing post-processed notifications. +class CefBrowserHostImpl : public CefBrowserHost, + public CefBrowser, + public content::WebContentsDelegate, + public content::WebContentsObserver, + public content::NotificationObserver { + public: + // Used for handling the response to command messages. + class CommandResponseHandler : public virtual CefBase { + public: + virtual void OnResponse(const std::string& response) =0; + }; + + virtual ~CefBrowserHostImpl(); + + // Create a new CefBrowserHostImpl instance. + static CefRefPtr Create( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefWindowHandle opener, + bool is_popup, + CefRefPtr request_context); + + // Returns the browser associated with the specified RenderViewHost. + static CefRefPtr GetBrowserForHost( + const content::RenderViewHost* host); + // Returns the browser associated with the specified RenderFrameHost. + static CefRefPtr GetBrowserForHost( + const content::RenderFrameHost* host); + // Returns the browser associated with the specified WebContents. + static CefRefPtr GetBrowserForContents( + content::WebContents* contents); + // Returns the browser associated with the specified URLRequest. + static CefRefPtr GetBrowserForRequest( + net::URLRequest* request); + // Returns the browser associated with the specified view routing IDs. + static CefRefPtr GetBrowserForView( + int render_process_id, int render_routing_id); + // Returns the browser associated with the specified frame routing IDs. + static CefRefPtr GetBrowserForFrame( + int render_process_id, int render_routing_id); + + // CefBrowserHost methods. + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual void CloseBrowser(bool force_close) OVERRIDE; + virtual void SetFocus(bool focus) OVERRIDE; + virtual void SetWindowVisibility(bool visible) OVERRIDE; + virtual CefWindowHandle GetWindowHandle() OVERRIDE; + virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; + virtual CefRefPtr GetClient() OVERRIDE; + virtual CefRefPtr GetRequestContext() OVERRIDE; + virtual double GetZoomLevel() OVERRIDE; + virtual void SetZoomLevel(double zoomLevel) OVERRIDE; + virtual void RunFileDialog( + FileDialogMode mode, + const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) OVERRIDE; + virtual void StartDownload(const CefString& url) OVERRIDE; + virtual void Print() OVERRIDE; + virtual void Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) OVERRIDE; + virtual void StopFinding(bool clearSelection) OVERRIDE; + virtual void ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) OVERRIDE; + virtual void CloseDevTools() OVERRIDE; + virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE; + virtual bool IsMouseCursorChangeDisabled() OVERRIDE; + virtual bool IsWindowRenderingDisabled() OVERRIDE; + virtual void WasResized() OVERRIDE; + virtual void WasHidden(bool hidden) OVERRIDE; + virtual void NotifyScreenInfoChanged() OVERRIDE; + virtual void Invalidate(PaintElementType type) OVERRIDE; + virtual void SendKeyEvent(const CefKeyEvent& event) OVERRIDE; + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, + bool mouseUp, int clickCount) OVERRIDE; + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) OVERRIDE; + virtual void SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) OVERRIDE; + virtual void SendFocusEvent(bool setFocus) OVERRIDE; + virtual void SendCaptureLostEvent() OVERRIDE; + virtual CefTextInputContext GetNSTextInputContext() OVERRIDE; + virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) + OVERRIDE; + virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) + OVERRIDE; + virtual void DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, + DragOperationsMask allowed_ops); + virtual void DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops); + virtual void DragTargetDragLeave(); + virtual void DragTargetDrop(const CefMouseEvent& event); + virtual void DragSourceSystemDragEnded(); + virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op); + + // CefBrowser methods. + virtual CefRefPtr GetHost() OVERRIDE; + virtual bool CanGoBack() OVERRIDE; + virtual void GoBack() OVERRIDE; + virtual bool CanGoForward() OVERRIDE; + virtual void GoForward() OVERRIDE; + virtual bool IsLoading() OVERRIDE; + virtual void Reload() OVERRIDE; + virtual void ReloadIgnoreCache() OVERRIDE; + virtual void StopLoad() OVERRIDE; + virtual int GetIdentifier() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool IsPopup() OVERRIDE; + virtual bool HasDocument() OVERRIDE; + virtual CefRefPtr GetMainFrame() OVERRIDE; + virtual CefRefPtr GetFocusedFrame() OVERRIDE; + virtual CefRefPtr GetFrame(int64 identifier) OVERRIDE; + virtual CefRefPtr GetFrame(const CefString& name) OVERRIDE; + virtual size_t GetFrameCount() OVERRIDE; + virtual void GetFrameIdentifiers(std::vector& identifiers) OVERRIDE; + virtual void GetFrameNames(std::vector& names) OVERRIDE; + virtual bool SendProcessMessage( + CefProcessId target_process, + CefRefPtr message) OVERRIDE; + + // Returns true if windowless rendering is enabled. + bool IsWindowless() const; + // Returns true if transparent painting is enabled. + bool IsTransparent() const; + + // Called when the OS window hosting the browser is destroyed. + void WindowDestroyed(); + + // Destroy the browser members. This method should only be called after the + // native browser window is not longer processing messages. + void DestroyBrowser(); + + // Cancel display of the context menu, if any. + void CancelContextMenu(); + + // Returns the native view for the WebContents. + gfx::NativeView GetContentView() const; + + // Returns a pointer to the WebContents. + content::WebContents* GetWebContents() const; + + // Returns the frame associated with the specified URLRequest. + CefRefPtr GetFrameForRequest(net::URLRequest* request); + + // Navigate as specified by the |params| argument. + void Navigate(const CefNavigateParams& params); + + // Load the specified request. + void LoadRequest(int64 frame_id, CefRefPtr request); + + // Load the specified URL. + void LoadURL(int64 frame_id, + const std::string& url, + const content::Referrer& referrer, + content::PageTransition transition, + const std::string& extra_headers); + + // Load the specified string. + void LoadString(int64 frame_id, const std::string& string, + const std::string& url); + + // Send a command to the renderer for execution. + void SendCommand(int64 frame_id, const std::string& command, + CefRefPtr responseHandler); + + // Send code to the renderer for execution. + void SendCode(int64 frame_id, bool is_javascript, const std::string& code, + const std::string& script_url, int script_start_line, + CefRefPtr responseHandler); + + bool SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated); + + // Open the specified text in the default text editor. + bool ViewText(const std::string& text); + + // Handler for URLs involving external protocols. + void HandleExternalProtocol(const GURL& url); + + // Thread safe accessors. + const CefBrowserSettings& settings() const { return settings_; } + CefRefPtr client() const { return client_; } + int browser_id() const; + +#if defined(USE_AURA) + views::Widget* window_widget() const { return window_widget_; } +#endif + +#if defined(USE_X11) + CefWindowX11* window_x11() const { return window_x11_; } +#endif + + // Returns the URL that is currently loading (or loaded) in the main frame. + GURL GetLoadingURL(); + +#if defined(OS_WIN) + static void RegisterWindowClass(); +#endif + +#if defined(USE_AURA) + ui::PlatformCursor GetPlatformCursor(blink::WebCursorInfo::Type type); +#endif + + void OnSetFocus(cef_focus_source_t source); + + // The argument vector will be empty if the dialog was cancelled. + typedef base::Callback&)> + RunFileChooserCallback; + + // Run the file chooser dialog specified by |params|. Only a single dialog may + // be pending at any given time. |callback| will be executed asynchronously + // after the dialog is dismissed or if another dialog is already pending. + void RunFileChooser(const content::FileChooserParams& params, + const RunFileChooserCallback& callback); + + // Used when creating a new popup window. + struct PendingPopupInfo { + CefWindowInfo window_info; + CefBrowserSettings settings; + CefRefPtr client; + }; + // Returns false if a popup is already pending. + bool SetPendingPopupInfo(scoped_ptr info); + + enum DestructionState { + DESTRUCTION_STATE_NONE = 0, + DESTRUCTION_STATE_PENDING, + DESTRUCTION_STATE_ACCEPTED, + DESTRUCTION_STATE_COMPLETED + }; + DestructionState destruction_state() const { return destruction_state_; } + + // Used to retrieve a WeakPtr that will be invalidated when the browser is + // destroyed. This method can only be called on, and the resulting WeakPtr + // can only be dereferenced on, the UI thread. + base::WeakPtr GetWeakPtr(); + + // content::WebContentsDelegate methods. + virtual content::WebContents* OpenURLFromTab( + content::WebContents* source, + const content::OpenURLParams& params) OVERRIDE; + virtual void LoadingStateChanged(content::WebContents* source, + bool to_different_document) OVERRIDE; + virtual void CloseContents(content::WebContents* source) OVERRIDE; + virtual void UpdateTargetURL(content::WebContents* source, + int32 page_id, + const GURL& url) OVERRIDE; + virtual bool AddMessageToConsole(content::WebContents* source, + int32 level, + const base::string16& message, + int32 line_no, + const base::string16& source_id) OVERRIDE; + virtual void BeforeUnloadFired(content::WebContents* source, + bool proceed, + bool* proceed_to_fire_unload) OVERRIDE; + virtual bool TakeFocus(content::WebContents* source, + bool reverse) OVERRIDE; + virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE; + virtual bool HandleContextMenu( + const content::ContextMenuParams& params) OVERRIDE; + virtual bool PreHandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event, + bool* is_keyboard_shortcut) OVERRIDE; + virtual void HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) OVERRIDE; + virtual bool CanDragEnter( + content::WebContents* source, + const content::DropData& data, + blink::WebDragOperationsMask operations_allowed) OVERRIDE; + virtual bool ShouldCreateWebContents( + content::WebContents* web_contents, + int route_id, + WindowContainerType window_container_type, + const base::string16& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace, + content::WebContentsView** view, + content::RenderViewHostDelegateView** delegate_view) OVERRIDE; + virtual void WebContentsCreated(content::WebContents* source_contents, + int opener_render_frame_id, + const base::string16& frame_name, + const GURL& target_url, + content::WebContents* new_contents) OVERRIDE; + virtual void DidNavigateMainFramePostCommit( + content::WebContents* tab) OVERRIDE; + virtual content::JavaScriptDialogManager* GetJavaScriptDialogManager() + OVERRIDE; + virtual void RunFileChooser( + content::WebContents* tab, + const content::FileChooserParams& params) OVERRIDE; + virtual void UpdatePreferredSize(content::WebContents* source, + const gfx::Size& pref_size) OVERRIDE; + virtual void RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + const content::MediaResponseCallback& callback) OVERRIDE; + + // content::WebContentsObserver methods. + using content::WebContentsObserver::BeforeUnloadFired; + using content::WebContentsObserver::WasHidden; + virtual void RenderFrameCreated( + content::RenderFrameHost* render_frame_host) OVERRIDE; + virtual void RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) OVERRIDE; + virtual void RenderViewCreated( + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void RenderViewDeleted( + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void RenderViewReady() OVERRIDE; + virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; + virtual void DidCommitProvisionalLoadForFrame( + int64 frame_id, + const base::string16& frame_unique_name, + bool is_main_frame, + const GURL& url, + content::PageTransition transition_type, + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DidFailProvisionalLoad( + int64 frame_id, + const base::string16& frame_unique_name, + bool is_main_frame, + const GURL& validated_url, + int error_code, + const base::string16& error_description, + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DocumentAvailableInMainFrame() OVERRIDE; + virtual void DidFailLoad(int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + int error_code, + const base::string16& error_description, + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void PluginCrashed(const base::FilePath& plugin_path, + base::ProcessId plugin_pid) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + // Override to provide a thread safe implementation. + virtual bool Send(IPC::Message* message) OVERRIDE; + + private: + class DevToolsWebContentsObserver; + + static CefRefPtr CreateInternal( + const CefWindowInfo& window_info, + const CefBrowserSettings& settings, + CefRefPtr client, + content::WebContents* web_contents, + scoped_refptr browser_info, + CefWindowHandle opener, + CefRefPtr request_context); + + // content::WebContentsObserver::OnMessageReceived() message handlers. + void OnFrameIdentified(int64 frame_id, + int64 parent_frame_id, + base::string16 name); + void OnDidFinishLoad( + int64 frame_id, + const GURL& validated_url, + bool is_main_frame, + int http_status_code); + void OnLoadingURLChange(const GURL& pending_url); + void OnRequest(const Cef_Request_Params& params); + void OnResponse(const Cef_Response_Params& params); + void OnResponseAck(int request_id); + void OnPDFHasUnsupportedFeature(); + void OnPDFSaveURLAs(const GURL& url, + const content::Referrer& referrer); + void OnPDFUpdateContentRestrictions(int content_restrictions); + void OnPDFModalPromptForPassword(const std::string& prompt, + IPC::Message* reply_message); + + void OnPDFModalPromptForPasswordClosed(IPC::Message* reply_message, + bool success, + const base::string16& actual_value); + + // content::NotificationObserver methods. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + CefBrowserHostImpl(const CefWindowInfo& window_info, + const CefBrowserSettings& settings, + CefRefPtr client, + content::WebContents* web_contents, + scoped_refptr browser_info, + CefWindowHandle opener); + + // Updates and returns an existing frame or creates a new frame. Pass + // CefFrameHostImpl::kUnspecifiedFrameId for |parent_frame_id| if unknown. + CefRefPtr GetOrCreateFrame(int64 frame_id, + int64 parent_frame_id, + bool is_main_frame, + base::string16 frame_name, + const GURL& frame_url); + // Remove the reference to the frame and mark it as detached. + void DetachFrame(int64 frame_id); + // Remove the references to all frames and mark them as detached. + void DetachAllFrames(); + // Set the frame that currently has focus. + void SetFocusedFrame(int64 frame_id); + +#if defined(OS_WIN) + static LPCTSTR GetWndClass(); + static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif + + // Create the window. + bool PlatformCreateWindow(); + // Sends a message via the OS to close the native browser window. + // DestroyBrowser will be called after the native window has closed. + void PlatformCloseWindow(); + // Resize the window to the given dimensions. + void PlatformSizeTo(int width, int height); + // Set or remove focus from the window. + void PlatformSetFocus(bool focus); +#if defined(OS_MACOSX) + // Set or remove window visibility. + void PlatformSetWindowVisibility(bool visible); +#endif + // Return the handle for this window. + CefWindowHandle PlatformGetWindowHandle(); + // Open the specified text in the default text editor. + bool PlatformViewText(const std::string& text); + // Forward the keyboard event to the application or frame window to allow + // processing of shortcut keys. + void PlatformHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event); + // Invoke platform specific handling for the external protocol. + void PlatformHandleExternalProtocol(const GURL& url); + // Invoke platform specific file chooser dialog. + void PlatformRunFileChooser(const content::FileChooserParams& params, + RunFileChooserCallback callback); + + void PlatformTranslateKeyEvent(content::NativeWebKeyboardEvent& native_event, + const CefKeyEvent& key_event); + void PlatformTranslateClickEvent(blink::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event, + CefBrowserHost::MouseButtonType type, + bool mouseUp, int clickCount); + void PlatformTranslateMoveEvent(blink::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event, + bool mouseLeave); + void PlatformTranslateWheelEvent(blink::WebMouseWheelEvent& web_event, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY); + void PlatformTranslateMouseEvent(blink::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event); + + int TranslateModifiers(uint32 cefKeyStates); + void SendMouseEvent(const blink::WebMouseEvent& web_event); + + void OnAddressChange(CefRefPtr frame, + const GURL& url); + void OnLoadStart(CefRefPtr frame, + const GURL& url, + content::PageTransition transition_type); + void OnLoadError(CefRefPtr frame, + const GURL& url, + int error_code, + const base::string16& error_description); + void OnLoadEnd(CefRefPtr frame, + const GURL& url, + int http_status_code); + + // Continuation from RunFileChooser. + void RunFileChooserOnUIThread(const content::FileChooserParams& params, + const RunFileChooserCallback& callback); + + // Used with RunFileChooser to clear the |file_chooser_pending_| flag. + void OnRunFileChooserCallback(const RunFileChooserCallback& callback, + const std::vector& file_paths); + + // Used with WebContentsDelegate::RunFileChooser to notify the WebContents. + void OnRunFileChooserDelegateCallback( + content::WebContents* tab, + content::FileChooserParams::Mode mode, + const std::vector& file_paths); + + void OnDevToolsWebContentsDestroyed(); + + CefWindowInfo window_info_; + CefBrowserSettings settings_; + CefRefPtr client_; + scoped_ptr web_contents_; + scoped_refptr browser_info_; + CefWindowHandle opener_; + CefRefPtr request_context_; + + // Pending popup information. Access must be protected by + // |pending_popup_info_lock_|. + base::Lock pending_popup_info_lock_; + scoped_ptr pending_popup_info_; + + // Volatile state information. All access must be protected by the state lock. + base::Lock state_lock_; + bool is_loading_; + bool can_go_back_; + bool can_go_forward_; + bool has_document_; + GURL loading_url_; + + // Messages we queue while waiting for the RenderView to be ready. We queue + // them here instead of in the RenderProcessHost to ensure that they're sent + // after the CefRenderViewObserver has been created on the renderer side. + std::queue queued_messages_; + bool queue_messages_; + + // Map of unique frame ids to CefFrameHostImpl references. + typedef std::map > FrameMap; + FrameMap frames_; + // The unique frame id currently identified as the main frame. + int64 main_frame_id_; + // The unique frame id currently identified as the focused frame. + int64 focused_frame_id_; + // Used when no other frame exists. Provides limited functionality. + CefRefPtr placeholder_frame_; + + // Represents the current browser destruction state. Only accessed on the UI + // thread. + DestructionState destruction_state_; + + // True if the OS window hosting the browser has been destroyed. Only accessed + // on the UI thread. + bool window_destroyed_; + + // True if currently in the OnSetFocus callback. Only accessed on the UI + // thread. + bool is_in_onsetfocus_; + + // True if the focus is currently on an editable field on the page. Only + // accessed on the UI thread. + bool focus_on_editable_field_; + + // True if mouse cursor change is disabled. + bool mouse_cursor_change_disabled_; + + // Used for managing notification subscriptions. + scoped_ptr registrar_; + + // Manages response registrations. + scoped_ptr response_manager_; + + // Used for creating and managing JavaScript dialogs. + scoped_ptr dialog_manager_; + + // Used for creating and managing context menus. + scoped_ptr menu_creator_; + + // Track the lifespan of the frontend WebContents associated with this + // browser. + scoped_ptr devtools_observer_; + // CefDevToolsFrontend will delete itself when the frontend WebContents is + // destroyed. + CefDevToolsFrontend* devtools_frontend_; + + // True if a file chooser is currently pending. + bool file_chooser_pending_; + + // Current title for the main frame. Only accessed on the UI thread. + base::string16 title_; + +#if defined(USE_AURA) + // Widget hosting the web contents. It will be deleted automatically when the + // associated root window is destroyed. + views::Widget* window_widget_; +#endif // defined(USE_AURA) +#if defined(USE_X11) + CefWindowX11* window_x11_; + scoped_ptr invisible_cursor_; +#endif // defined(USE_X11) + + // Only used on the UI thread. All references will be invalidated when + // DestroyBrowser() is called. Must be the last member. + base::WeakPtrFactory weak_ptr_factory_; + + IMPLEMENT_REFCOUNTING(CefBrowserHostImpl); + DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_ diff --git a/libcef/browser/browser_host_impl_linux.cc b/libcef/browser/browser_host_impl_linux.cc new file mode 100644 index 000000000..ab4d140dc --- /dev/null +++ b/libcef/browser/browser_host_impl_linux.cc @@ -0,0 +1,431 @@ +// Copyright (c) 2014 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 "libcef/browser/browser_host_impl.h" + +#include +#include + +#include "libcef/browser/context.h" +#include "libcef/browser/window_delegate_view.h" +#include "libcef/browser/window_x11.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/common/file_chooser_params.h" +#include "content/public/common/renderer_preferences.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/views/widget/widget.h" + +namespace { + +// Returns the number of seconds since system boot. +long GetSystemUptime() { + struct sysinfo info; + if (sysinfo(&info) == 0) + return info.uptime; + return 0; +} + +// Based on ui/base/cursor/cursor_loader_x11.cc. + +using blink::WebCursorInfo; + +int ToCursorID(WebCursorInfo::Type type) { + switch (type) { + case WebCursorInfo::TypePointer: + return XC_left_ptr; + case WebCursorInfo::TypeCross: + return XC_crosshair; + case WebCursorInfo::TypeHand: + return XC_hand2; + case WebCursorInfo::TypeIBeam: + return XC_xterm; + case WebCursorInfo::TypeWait: + return XC_watch; + case WebCursorInfo::TypeHelp: + return XC_question_arrow; + case WebCursorInfo::TypeEastResize: + return XC_right_side; + case WebCursorInfo::TypeNorthResize: + return XC_top_side; + case WebCursorInfo::TypeNorthEastResize: + return XC_top_right_corner; + case WebCursorInfo::TypeNorthWestResize: + return XC_top_left_corner; + case WebCursorInfo::TypeSouthResize: + return XC_bottom_side; + case WebCursorInfo::TypeSouthEastResize: + return XC_bottom_right_corner; + case WebCursorInfo::TypeSouthWestResize: + return XC_bottom_left_corner; + case WebCursorInfo::TypeWestResize: + return XC_left_side; + case WebCursorInfo::TypeNorthSouthResize: + return XC_sb_v_double_arrow; + case WebCursorInfo::TypeEastWestResize: + return XC_sb_h_double_arrow; + case WebCursorInfo::TypeNorthEastSouthWestResize: + return XC_left_ptr; + case WebCursorInfo::TypeNorthWestSouthEastResize: + return XC_left_ptr; + case WebCursorInfo::TypeColumnResize: + return XC_sb_h_double_arrow; + case WebCursorInfo::TypeRowResize: + return XC_sb_v_double_arrow; + case WebCursorInfo::TypeMiddlePanning: + return XC_fleur; + case WebCursorInfo::TypeEastPanning: + return XC_sb_right_arrow; + case WebCursorInfo::TypeNorthPanning: + return XC_sb_up_arrow; + case WebCursorInfo::TypeNorthEastPanning: + return XC_top_right_corner; + case WebCursorInfo::TypeNorthWestPanning: + return XC_top_left_corner; + case WebCursorInfo::TypeSouthPanning: + return XC_sb_down_arrow; + case WebCursorInfo::TypeSouthEastPanning: + return XC_bottom_right_corner; + case WebCursorInfo::TypeSouthWestPanning: + return XC_bottom_left_corner; + case WebCursorInfo::TypeWestPanning: + return XC_sb_left_arrow; + case WebCursorInfo::TypeMove: + return XC_fleur; + case WebCursorInfo::TypeVerticalText: + return XC_left_ptr; + case WebCursorInfo::TypeCell: + return XC_left_ptr; + case WebCursorInfo::TypeContextMenu: + return XC_left_ptr; + case WebCursorInfo::TypeAlias: + return XC_left_ptr; + case WebCursorInfo::TypeProgress: + return XC_left_ptr; + case WebCursorInfo::TypeNoDrop: + return XC_left_ptr; + case WebCursorInfo::TypeCopy: + return XC_left_ptr; + case WebCursorInfo::TypeNotAllowed: + return XC_left_ptr; + case WebCursorInfo::TypeZoomIn: + return XC_left_ptr; + case WebCursorInfo::TypeZoomOut: + return XC_left_ptr; + case WebCursorInfo::TypeGrab: + return XC_left_ptr; + case WebCursorInfo::TypeGrabbing: + return XC_left_ptr; + case WebCursorInfo::TypeCustom: + case WebCursorInfo::TypeNone: + break; + } + NOTREACHED(); + return 0; +} + +} // namespace + +ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor( + blink::WebCursorInfo::Type type) { + if (type == WebCursorInfo::TypeNone) { + if (!invisible_cursor_) { + invisible_cursor_.reset( + new ui::XScopedCursor(ui::CreateInvisibleCursor(), + gfx::GetXDisplay())); + } + return invisible_cursor_->get(); + } else { + return ui::GetXCursor(ToCursorID(type)); + } +} + +bool CefBrowserHostImpl::PlatformCreateWindow() { + DCHECK(!window_x11_); + DCHECK(!window_widget_); + + if (window_info_.width == 0) + window_info_.width = 800; + if (window_info_.height == 0) + window_info_.height = 600; + + gfx::Rect rect(window_info_.x, window_info_.y, + window_info_.width, window_info_.height); + + // Create a new window object. It will delete itself when the associated X11 + // window is destroyed. + window_x11_ = new CefWindowX11(this, window_info_.parent_window, rect); + window_info_.window = window_x11_->xwindow(); + + // Add a reference that will be released in the destroy handler. + AddRef(); + + SkColor background_color = SK_ColorWHITE; + const CefSettings& settings = CefContext::Get()->settings(); + if (CefColorGetA(settings.background_color) > 0) { + background_color = SkColorSetRGB( + CefColorGetR(settings.background_color), + CefColorGetG(settings.background_color), + CefColorGetB(settings.background_color)); + } + + CefWindowDelegateView* delegate_view = + new CefWindowDelegateView(background_color); + delegate_view->Init(window_info_.window, + web_contents(), + gfx::Rect(gfx::Point(), rect.size())); + + window_widget_ = delegate_view->GetWidget(); + window_widget_->Show(); + + window_x11_->Show(); + + // As an additional requirement on Linux, we must set the colors for the + // render widgets in webkit. + content::RendererPreferences* prefs = + web_contents_->GetMutableRendererPrefs(); + prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0); + prefs->thumb_active_color = SkColorSetRGB(244, 244, 244); + prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234); + prefs->track_color = SkColorSetRGB(211, 211, 211); + + prefs->active_selection_bg_color = SkColorSetRGB(30, 144, 255); + prefs->active_selection_fg_color = SK_ColorWHITE; + prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); + prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); + + return true; +} + +void CefBrowserHostImpl::PlatformCloseWindow() { + if (window_x11_) + window_x11_->Close(); +} + +void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { + if (window_x11_) { + window_x11_->SetBounds( + gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height))); + } +} + +void CefBrowserHostImpl::PlatformSetFocus(bool focus) { + if (!focus) + return; + + if (web_contents_) { + // Give logical focus to the RenderWidgetHostViewAura in the views + // hierarchy. This does not change the native keyboard focus. + web_contents_->Focus(); + } + + if (window_x11_) { + // Give native focus to the DesktopNativeWidgetAura for the root window. + // Needs to be done via the ::Window so that keyboard focus is assigned + // correctly. + window_x11_->Focus(); + } +} + +CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { + return IsWindowless() ? window_info_.parent_window : window_info_.window; +} + +bool CefBrowserHostImpl::PlatformViewText(const std::string& text) { + CEF_REQUIRE_UIT(); + + char buff[] = "/tmp/CEFSourceXXXXXX"; + int fd = mkstemp(buff); + + if (fd == -1) + return false; + + FILE* srcOutput = fdopen(fd, "w+"); + if (!srcOutput) + return false; + + if (fputs(text.c_str(), srcOutput) < 0) { + fclose(srcOutput); + return false; + } + + fclose(srcOutput); + + std::string newName(buff); + newName.append(".txt"); + if (rename(buff, newName.c_str()) != 0) + return false; + + std::string openCommand("xdg-open "); + openCommand += newName; + + if (system(openCommand.c_str()) != 0) + return false; + + return true; +} + +void CefBrowserHostImpl::PlatformHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { + // TODO(cef): Is something required here to handle shortcut keys? +} + +void CefBrowserHostImpl::PlatformRunFileChooser( + const content::FileChooserParams& params, + RunFileChooserCallback callback) { + NOTIMPLEMENTED(); + std::vector files; + callback.Run(files); +} + +void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& result, + const CefKeyEvent& key_event) { + result.timeStampSeconds = GetSystemUptime(); + + result.windowsKeyCode = key_event.windows_key_code; + result.nativeKeyCode = key_event.native_key_code; + result.isSystemKey = key_event.is_system_key ? 1 : 0; + switch (key_event.type) { + case KEYEVENT_RAWKEYDOWN: + case KEYEVENT_KEYDOWN: + result.type = blink::WebInputEvent::RawKeyDown; + break; + case KEYEVENT_KEYUP: + result.type = blink::WebInputEvent::KeyUp; + break; + case KEYEVENT_CHAR: + result.type = blink::WebInputEvent::Char; + break; + default: + NOTREACHED(); + } + + result.text[0] = key_event.character; + result.unmodifiedText[0] = key_event.unmodified_character; + + result.setKeyIdentifierFromWindowsKeyCode(); + + result.modifiers |= TranslateModifiers(key_event.modifiers); +} + +void CefBrowserHostImpl::PlatformTranslateClickEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + MouseButtonType type, + bool mouseUp, int clickCount) { + PlatformTranslateMouseEvent(result, mouse_event); + + switch (type) { + case MBT_LEFT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonLeft; + break; + case MBT_MIDDLE: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonMiddle; + break; + case MBT_RIGHT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonRight; + break; + default: + NOTREACHED(); + } + + result.clickCount = clickCount; +} + +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + PlatformTranslateMouseEvent(result, mouse_event); + + if (!mouseLeave) { + result.type = blink::WebInputEvent::MouseMove; + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; + } else { + result.type = blink::WebInputEvent::MouseLeave; + result.button = blink::WebMouseEvent::ButtonNone; + } + + result.clickCount = 0; +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + blink::WebMouseWheelEvent& result, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + result = blink::WebMouseWheelEvent(); + PlatformTranslateMouseEvent(result, mouse_event); + + result.type = blink::WebInputEvent::MouseWheel; + + static const double scrollbarPixelsPerGtkTick = 40.0; + result.deltaX = deltaX; + result.deltaY = deltaY; + result.wheelTicksX = result.deltaX / scrollbarPixelsPerGtkTick; + result.wheelTicksY = result.deltaY / scrollbarPixelsPerGtkTick; + result.hasPreciseScrollingDeltas = true; + + // Unless the phase and momentumPhase are passed in as parameters to this + // function, there is no way to know them + result.phase = blink::WebMouseWheelEvent::PhaseNone; + result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone; + + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event) { + // position + result.x = mouse_event.x; + result.y = mouse_event.y; + result.windowX = result.x; + result.windowY = result.y; + result.globalX = result.x; + result.globalY = result.y; + + if (IsWindowless()) { + GetClient()->GetRenderHandler()->GetScreenPoint( + GetBrowser(), + result.x, result.y, + result.globalX, result.globalY); + } else if (window_x11_) { + const gfx::Point& origin = window_x11_->bounds().origin(); + result.globalX += origin.x(); + result.globalY += origin.y(); + } + + // modifiers + result.modifiers |= TranslateModifiers(mouse_event.modifiers); + + // timestamp + result.timeStampSeconds = GetSystemUptime(); +} diff --git a/libcef/browser/browser_host_impl_mac.mm b/libcef/browser/browser_host_impl_mac.mm new file mode 100644 index 000000000..8426a1125 --- /dev/null +++ b/libcef/browser/browser_host_impl_mac.mm @@ -0,0 +1,696 @@ +// Copyright (c) 2012 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 "libcef/browser/browser_host_impl.h" + +#import +#import + +#include "libcef/browser/render_widget_host_view_osr.h" +#include "libcef/browser/text_input_client_osr_mac.h" +#include "libcef/browser/thread_util.h" + +#include "base/file_util.h" +#include "base/mac/mac_util.h" +#include "base/mac/scoped_nsautorelease_pool.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_restrictions.h" +#import "chrome/browser/ui/cocoa/nsview_additions.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/file_chooser_params.h" +#include "grit/ui_strings.h" +#include "net/base/mime_util.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h" +#import "ui/base/cocoa/underlay_opengl_hosting_window.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/events/keycodes/keyboard_codes_posix.h" +#include "ui/gfx/rect.h" + +// Wrapper NSView for the native view. Necessary to destroy the browser when +// the view is deleted. +@interface CefBrowserHostView : NSView { + @private + CefBrowserHostImpl* browser_; // weak +} + +@property (nonatomic, assign) CefBrowserHostImpl* browser; + +@end + +@implementation CefBrowserHostView + +@synthesize browser = browser_; + +- (void) dealloc { + if (browser_) { + // Force the browser to be destroyed and release the reference added in + // PlatformCreateWindow(). + browser_->WindowDestroyed(); + } + + [super dealloc]; +} + +@end + +// Receives notifications from the browser window. Will delete itself when done. +@interface CefWindowDelegate : NSObject { + @private + CefBrowserHostImpl* browser_; // weak +} + +@property (nonatomic, assign) CefBrowserHostImpl* browser; + +@end + +@implementation CefWindowDelegate + +@synthesize browser = browser_; + +// Called when we are activated (when we gain focus). +- (void)windowDidBecomeKey:(NSNotification*)notification { + if (browser_) + browser_->SetFocus(true); +} + +// Called when we are deactivated (when we lose focus). +- (void)windowDidResignKey:(NSNotification*)notification { + if (browser_) + browser_->SetFocus(false); +} + +// Called when we have been minimized. +- (void)windowDidMiniaturize:(NSNotification *)notification { + if (browser_) + browser_->SetWindowVisibility(false); +} + +// Called when we have been unminimized. +- (void)windowDidDeminiaturize:(NSNotification *)notification { + if (browser_) + browser_->SetWindowVisibility(true); +} + +// Called when the application has been hidden. +- (void)applicationDidHide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![[notification object] isMiniaturized]) { + if (browser_) + browser_->SetWindowVisibility(false); + } +} + +// Called when the application has been unhidden. +- (void)applicationDidUnhide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![[notification object] isMiniaturized]) { + if (browser_) + browser_->SetWindowVisibility(true); + } +} + +- (BOOL)windowShouldClose:(id)window { + // Protect against multiple requests to close while the close is pending. + if (browser_ && browser_->destruction_state() <= + CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) { + if (browser_->destruction_state() == + CefBrowserHostImpl::DESTRUCTION_STATE_NONE) { + // Request that the browser close. + browser_->CloseBrowser(false); + } + + // Cancel the close. + return NO; + } + + // Clean ourselves up after clearing the stack of anything that might have the + // window on it. + [self performSelectorOnMainThread:@selector(cleanup:) + withObject:window + waitUntilDone:NO]; + + // Allow the close. + return YES; +} + +- (void)cleanup:(id)window { + [self release]; +} + +@end + + +namespace { + +// Accept-types to file-types helper. +NSMutableArray* GetFileTypesFromAcceptTypes( + const std::vector& accept_types) { + NSMutableArray* acceptArray = [[NSMutableArray alloc] init]; + for (size_t i=0; i ext; + net::GetExtensionsForMimeType(ascii_type, &ext); + for (size_t x = 0; x < ext.size(); ++x) + [acceptArray addObject:base::SysUTF8ToNSString(ext[x])]; + } + } + } + return acceptArray; +} + +void RunOpenFileDialog(const content::FileChooserParams& params, + NSView* view, + std::vector* files) { + NSOpenPanel* openPanel = [NSOpenPanel openPanel]; + + base::string16 title; + if (!params.title.empty()) { + title = params.title; + } else { + title = l10n_util::GetStringUTF16( + params.mode == content::FileChooserParams::Open ? + IDS_OPEN_FILE_DIALOG_TITLE : IDS_OPEN_FILES_DIALOG_TITLE); + } + [openPanel setTitle:base::SysUTF16ToNSString(title)]; + + // Consider default file name if any. + base::FilePath default_file_name(params.default_file_name); + + if (!default_file_name.empty()) { + if (!default_file_name.BaseName().empty()) { + NSString* defaultName = base::SysUTF8ToNSString( + default_file_name.BaseName().value()); + [openPanel setNameFieldStringValue:defaultName]; + } + + if (!default_file_name.DirName().empty()) { + NSString* defaultDir = base::SysUTF8ToNSString( + default_file_name.DirName().value()); + [openPanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]]; + } + } + + // Consider supported file types + if (!params.accept_types.empty()) { + [openPanel setAllowedFileTypes:GetFileTypesFromAcceptTypes( + params.accept_types)]; + } + + // Further panel configuration. + [openPanel setAllowsOtherFileTypes:YES]; + [openPanel setAllowsMultipleSelection: + (params.mode == content::FileChooserParams::OpenMultiple)]; + [openPanel setCanChooseFiles:YES]; + [openPanel setCanChooseDirectories:NO]; + + // Show panel. + [openPanel beginSheetModalForWindow:[view window] completionHandler:nil]; + if ([openPanel runModal] == NSFileHandlingPanelOKButton) { + NSArray *urls = [openPanel URLs]; + int i, count = [urls count]; + for (i=0; ipush_back(base::FilePath(base::SysNSStringToUTF8([url path]))); + } + } + [NSApp endSheet:openPanel]; +} + +bool RunSaveFileDialog(const content::FileChooserParams& params, + NSView* view, + base::FilePath* file) { + NSSavePanel* savePanel = [NSSavePanel savePanel]; + + base::string16 title; + if (!params.title.empty()) + title = params.title; + else + title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE); + [savePanel setTitle:base::SysUTF16ToNSString(title)]; + + // Consider default file name if any. + base::FilePath default_file_name(params.default_file_name); + + if (!default_file_name.empty()) { + if (!default_file_name.BaseName().empty()) { + NSString* defaultName = base::SysUTF8ToNSString( + default_file_name.BaseName().value()); + [savePanel setNameFieldStringValue:defaultName]; + } + + if (!default_file_name.DirName().empty()) { + NSString* defaultDir = base::SysUTF8ToNSString( + default_file_name.DirName().value()); + [savePanel setDirectoryURL:[NSURL fileURLWithPath:defaultDir]]; + } + } + + // Consider supported file types + if (!params.accept_types.empty()) { + [savePanel setAllowedFileTypes:GetFileTypesFromAcceptTypes( + params.accept_types)]; + } + + [savePanel setAllowsOtherFileTypes:YES]; + + bool success = false; + + [savePanel beginSheetModalForWindow:[view window] completionHandler:nil]; + if ([savePanel runModal] == NSFileHandlingPanelOKButton) { + NSURL * url = [savePanel URL]; + NSString* path = [url path]; + *file = base::FilePath([path UTF8String]); + success = true; + } + [NSApp endSheet:savePanel]; + + return success; +} + +} // namespace + +bool CefBrowserHostImpl::PlatformViewText(const std::string& text) { + NOTIMPLEMENTED(); + return false; +} + +CefTextInputContext CefBrowserHostImpl::GetNSTextInputContext() { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return NULL; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "Called on invalid thread"; + return NULL; + } + + CefRenderWidgetHostViewOSR* rwhv = static_cast( + GetWebContents()->GetRenderWidgetHostView()); + + return rwhv->GetNSTextInputContext(); +} + +void CefBrowserHostImpl::HandleKeyEventBeforeTextInputClient( + CefEventHandle keyEvent) { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "Called on invalid thread"; + return; + } + + CefRenderWidgetHostViewOSR* rwhv = static_cast( + GetWebContents()->GetRenderWidgetHostView()); + + rwhv->HandleKeyEventBeforeTextInputClient(keyEvent); +} + +void CefBrowserHostImpl::HandleKeyEventAfterTextInputClient( + CefEventHandle keyEvent) { + if (!IsWindowless()) { + NOTREACHED() << "Window rendering is not disabled"; + return; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "Called on invalid thread"; + return; + } + + CefRenderWidgetHostViewOSR* rwhv = static_cast( + GetWebContents()->GetRenderWidgetHostView()); + + rwhv->HandleKeyEventAfterTextInputClient(keyEvent); +} + +bool CefBrowserHostImpl::PlatformCreateWindow() { + base::mac::ScopedNSAutoreleasePool autorelease_pool; + + NSWindow* newWnd = nil; + + NSView* parentView = window_info_.parent_view; + NSRect contentRect = {{window_info_.x, window_info_.y}, + {window_info_.width, window_info_.height}}; + if (parentView == nil) { + // Create a new window. + NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; + NSRect window_rect = {{window_info_.x, + screen_rect.size.height - window_info_.y}, + {window_info_.width, window_info_.height}}; + if (window_rect.size.width == 0) + window_rect.size.width = 750; + if (window_rect.size.height == 0) + window_rect.size.height = 750; + + contentRect.origin.x = 0; + contentRect.origin.y = 0; + contentRect.size.width = window_rect.size.width; + contentRect.size.height = window_rect.size.height; + + // Create the delegate for control and browser window events. + CefWindowDelegate* delegate = [[CefWindowDelegate alloc] init]; + delegate.browser = this; + + newWnd = [[UnderlayOpenGLHostingWindow alloc] + initWithContentRect:window_rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask | + NSUnifiedTitleAndToolbarWindowMask ) + backing:NSBackingStoreBuffered + defer:NO]; + [newWnd setDelegate:delegate]; + parentView = [newWnd contentView]; + window_info_.parent_view = parentView; + } + + // Make the content view for the window have a layer. This will make all + // sub-views have layers. This is necessary to ensure correct layer + // ordering of all child views and their layers. + [[[parentView window] contentView] cr_setWantsLayer:YES]; + + // Add a reference that will be released in the dealloc handler. + AddRef(); + + // Create the browser view. + CefBrowserHostView* browser_view = + [[CefBrowserHostView alloc] initWithFrame:contentRect]; + browser_view.browser = this; + [parentView addSubview:browser_view]; + [browser_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [browser_view setNeedsDisplay:YES]; + [browser_view release]; + + // Parent the TabContents to the browser view. + const NSRect bounds = [browser_view bounds]; + NSView* native_view = web_contents_->GetNativeView(); + [browser_view addSubview:native_view]; + [native_view setFrame:bounds]; + [native_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [native_view setNeedsDisplay:YES]; + + window_info_.view = browser_view; + + if (newWnd != nil && !window_info_.hidden) { + // Show the window. + [newWnd makeKeyAndOrderFront: nil]; + } + + return true; +} + +void CefBrowserHostImpl::PlatformCloseWindow() { + if (window_info_.view != nil) { + [[window_info_.view window] + performSelectorOnMainThread:@selector(performClose:) + withObject:nil + waitUntilDone:NO]; + } +} + +void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { + // Not needed; subviews are bound. +} + +void CefBrowserHostImpl::PlatformSetFocus(bool focus) { + if (web_contents_) { + if (content::RenderWidgetHostView* view = + web_contents_->GetRenderWidgetHostView()) { + view->SetActive(focus); + + if (focus && !IsWindowless()) { + // Give keyboard focus to the native view. + NSView* view = web_contents_->GetContentNativeView(); + DCHECK([view canBecomeKeyView]); + [[view window] makeFirstResponder:view]; + } + } + } +} + +void CefBrowserHostImpl::PlatformSetWindowVisibility(bool visible) { + if (web_contents_) { + if (content::RenderWidgetHostView* view = + web_contents_->GetRenderWidgetHostView()) { + view->SetWindowVisibility(visible); + } + } +} + +CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { + return IsWindowless() ? window_info_.parent_view : window_info_.view; +} + +void CefBrowserHostImpl::PlatformHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { + // Give the top level menu equivalents a chance to handle the event. + if ([event.os_event type] == NSKeyDown) + [[NSApp mainMenu] performKeyEquivalent:event.os_event]; +} + +void CefBrowserHostImpl::PlatformRunFileChooser( + const content::FileChooserParams& params, + RunFileChooserCallback callback) { + std::vector files; + + if (params.mode == content::FileChooserParams::Open || + params.mode == content::FileChooserParams::OpenMultiple) { + RunOpenFileDialog(params, PlatformGetWindowHandle(), &files); + } else if (params.mode == content::FileChooserParams::Save) { + base::FilePath file; + if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file)) + files.push_back(file); + } else { + NOTIMPLEMENTED(); + } + + callback.Run(files); +} + +void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { +} + +static NSTimeInterval currentEventTimestamp() { + NSEvent* currentEvent = [NSApp currentEvent]; + if (currentEvent) + return [currentEvent timestamp]; + else { + // FIXME(API): In case there is no current event, the timestamp could be + // obtained by getting the time since the application started. This involves + // taking some more static functions from Chromium code. + // Another option is to have the timestamp as a field in CefEvent structures + // and let the client provide it. + return 0; + } +} + +static NSUInteger NativeModifiers(int cef_modifiers) { + NSUInteger native_modifiers = 0; + if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) + native_modifiers |= NSShiftKeyMask; + if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) + native_modifiers |= NSControlKeyMask; + if (cef_modifiers & EVENTFLAG_ALT_DOWN) + native_modifiers |= NSAlternateKeyMask; + if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) + native_modifiers |= NSCommandKeyMask; + if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) + native_modifiers |= NSAlphaShiftKeyMask; + if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) + native_modifiers |= NSNumericPadKeyMask; + + return native_modifiers; +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& native_event, + const CefKeyEvent& key_event) { + // Use a synthetic NSEvent in order to obtain the windowsKeyCode member from + // the NativeWebKeyboardEvent constructor. This is the only member which can + // not be easily translated (without hardcoding keyCodes) + // Determining whether a modifier key is left or right seems to be done + // through the key code as well. + + NSEventType event_type; + if (key_event.character == 0 && key_event.unmodified_character == 0) { + // Check if both character and unmodified_characther are empty to determine + // if this was a NSFlagsChanged event. + // A dead key will have an empty character, but a non-empty unmodified + // character + event_type = NSFlagsChanged; + } else { + switch (key_event.type) { + case KEYEVENT_RAWKEYDOWN: + case KEYEVENT_KEYDOWN: + case KEYEVENT_CHAR: + event_type = NSKeyDown; + break; + case KEYEVENT_KEYUP: + event_type = NSKeyUp; + break; + } + } + + NSString* charactersIgnoringModifiers = [[[NSString alloc] + initWithCharacters:&key_event.unmodified_character length:1] + autorelease]; + NSString* characters = [[[NSString alloc] + initWithCharacters:&key_event.character length:1] autorelease]; + + NSEvent* synthetic_event = + [NSEvent keyEventWithType:event_type + location:NSMakePoint(0, 0) + modifierFlags:NativeModifiers(key_event.modifiers) + timestamp:currentEventTimestamp() + windowNumber:0 + context:nil + characters:characters + charactersIgnoringModifiers:charactersIgnoringModifiers + isARepeat:NO + keyCode:key_event.native_key_code]; + + native_event = content::NativeWebKeyboardEvent(synthetic_event); + if (key_event.type == KEYEVENT_CHAR) + native_event.type = blink::WebInputEvent::Char; + + native_event.isSystemKey = key_event.is_system_key; +} + +void CefBrowserHostImpl::PlatformTranslateClickEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + MouseButtonType type, + bool mouseUp, int clickCount) { + PlatformTranslateMouseEvent(result, mouse_event); + + switch (type) { + case MBT_LEFT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonLeft; + break; + case MBT_MIDDLE: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonMiddle; + break; + case MBT_RIGHT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonRight; + break; + default: + NOTREACHED(); + } + + result.clickCount = clickCount; +} + +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + PlatformTranslateMouseEvent(result, mouse_event); + + if (!mouseLeave) { + result.type = blink::WebInputEvent::MouseMove; + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; + } else { + result.type = blink::WebInputEvent::MouseLeave; + result.button = blink::WebMouseEvent::ButtonNone; + } + + result.clickCount = 0; +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + blink::WebMouseWheelEvent& result, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + result = blink::WebMouseWheelEvent(); + PlatformTranslateMouseEvent(result, mouse_event); + + result.type = blink::WebInputEvent::MouseWheel; + + static const double scrollbarPixelsPerCocoaTick = 40.0; + result.deltaX = deltaX; + result.deltaY = deltaY; + result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick; + result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick; + result.hasPreciseScrollingDeltas = true; + + // Unless the phase and momentumPhase are passed in as parameters to this + // function, there is no way to know them + result.phase = blink::WebMouseWheelEvent::PhaseNone; + result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone; + + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event) { + // position + result.x = mouse_event.x; + result.y = mouse_event.y; + result.windowX = result.x; + result.windowY = result.y; + result.globalX = result.x; + result.globalY = result.y; + + if (IsWindowless()) { + GetClient()->GetRenderHandler()->GetScreenPoint( + GetBrowser(), + result.x, result.y, + result.globalX, result.globalY); + } else { + NSView* view = window_info_.parent_view; + if (view) { + NSRect bounds = [view bounds]; + NSPoint view_pt = {result.x, bounds.size.height - result.y}; + NSPoint window_pt = [view convertPoint:view_pt toView:nil]; + NSPoint screen_pt = [[view window] convertBaseToScreen:window_pt]; + result.globalX = screen_pt.x; + result.globalY = screen_pt.y; + } + } + + // modifiers + result.modifiers |= TranslateModifiers(mouse_event.modifiers); + + // timestamp - Mac OSX specific + result.timeStampSeconds = currentEventTimestamp(); +} diff --git a/libcef/browser/browser_host_impl_win.cc b/libcef/browser/browser_host_impl_win.cc new file mode 100644 index 000000000..ee228a486 --- /dev/null +++ b/libcef/browser/browser_host_impl_win.cc @@ -0,0 +1,942 @@ +// Copyright (c) 2012 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 "libcef/browser/browser_host_impl.h" + +#include +#include +#include +#include +#include + +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/window_delegate_view.h" + +#include "base/file_util.h" +#include "base/i18n/case_conversion.h" +#include "base/memory/ref_counted_memory.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/win/registry.h" +#include "base/win/windows_version.h" +#include "content/common/cursors/webcursor.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/common/file_chooser_params.h" +#include "grit/cef_strings.h" +#include "grit/ui_strings.h" +#include "grit/ui_unscaled_resources.h" +#include "net/base/mime_util.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/win/shell.h" +#include "ui/gfx/win/hwnd_util.h" +#include "ui/views/widget/widget.h" +#include "ui/views/win/hwnd_util.h" + +#pragma comment(lib, "dwmapi.lib") + +namespace { + +void WriteTempFileAndView(scoped_refptr str) { + CEF_REQUIRE_FILET(); + + base::FilePath tmp_file; + if (!base::CreateTemporaryFile(&tmp_file)) + return; + + // The shell command will look at the file extension to identify the correct + // program to open. + tmp_file = tmp_file.AddExtension(L"txt"); + + const std::string& data = str->data(); + int write_ct = base::WriteFile(tmp_file, data.c_str(), data.size()); + DCHECK_EQ(static_cast(data.size()), write_ct); + + ui::win::OpenItemViaShell(tmp_file); +} + +// From ui/base/dialogs/select_file_dialog_win.cc. + +// Get the file type description from the registry. This will be "Text Document" +// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't +// have an entry for the file type, we return false, true if the description was +// found. 'file_ext' must be in form ".txt". +static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext, + std::wstring* reg_description) { + DCHECK(reg_description); + base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ); + std::wstring reg_app; + if (reg_ext.ReadValue(NULL, ®_app) == ERROR_SUCCESS && !reg_app.empty()) { + base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ); + if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS) + return true; + } + return false; +} + +// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file +// extensions (internally separated by semicolons), |ext_desc| as the text +// descriptions of the |file_ext| types (optional), and (optionally) the default +// 'All Files' view. The purpose of the filter is to show only files of a +// particular type in a Windows Save/Open dialog box. The resulting filter is +// returned. The filters created here are: +// 1. only files that have 'file_ext' as their extension +// 2. all files (only added if 'include_all_files' is true) +// Example: +// file_ext: { "*.txt", "*.htm;*.html" } +// ext_desc: { "Text Document" } +// returned: "Text Document\0*.txt\0HTML Document\0*.htm;*.html\0" +// "All Files\0*.*\0\0" (in one big string) +// If a description is not provided for a file extension, it will be retrieved +// from the registry. If the file extension does not exist in the registry, it +// will be omitted from the filter, as it is likely a bogus extension. +std::wstring FormatFilterForExtensions( + const std::vector& file_ext, + const std::vector& ext_desc, + bool include_all_files) { + const std::wstring all_ext = L"*.*"; + const std::wstring all_desc = + l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES) + + L" (" + all_ext + L")"; + + DCHECK(file_ext.size() >= ext_desc.size()); + + if (file_ext.empty()) + include_all_files = true; + + std::wstring result; + + for (size_t i = 0; i < file_ext.size(); ++i) { + std::wstring ext = file_ext[i]; + std::wstring desc; + if (i < ext_desc.size()) + desc = ext_desc[i]; + + if (ext.empty()) { + // Force something reasonable to appear in the dialog box if there is no + // extension provided. + include_all_files = true; + continue; + } + + if (desc.empty()) { + DCHECK(ext.find(L'.') != std::wstring::npos); + std::wstring first_extension = ext.substr(ext.find(L'.')); + size_t first_separator_index = first_extension.find(L';'); + if (first_separator_index != std::wstring::npos) + first_extension = first_extension.substr(0, first_separator_index); + + // Find the extension name without the preceeding '.' character. + std::wstring ext_name = first_extension; + size_t ext_index = ext_name.find_first_not_of(L'.'); + if (ext_index != std::wstring::npos) + ext_name = ext_name.substr(ext_index); + + if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) { + // The extension doesn't exist in the registry. Create a description + // based on the unknown extension type (i.e. if the extension is .qqq, + // the we create a description "QQQ File (.qqq)"). + include_all_files = true; + desc = l10n_util::GetStringFUTF16( + IDS_APP_SAVEAS_EXTENSION_FORMAT, + base::i18n::ToUpper(base::WideToUTF16(ext_name)), + ext_name); + } + } + + if (!desc.empty()) + desc += L" (" + ext + L")"; + else + desc = ext; + + result.append(desc.c_str(), desc.size() + 1); // Append NULL too. + result.append(ext.c_str(), ext.size() + 1); + } + + if (include_all_files) { + result.append(all_desc.c_str(), all_desc.size() + 1); + result.append(all_ext.c_str(), all_ext.size() + 1); + } + + result.append(1, '\0'); // Double NULL required. + return result; +} + +std::wstring GetDescriptionFromMimeType(const std::string& mime_type) { + // Check for wild card mime types and return an appropriate description. + static const struct { + const char* mime_type; + int string_id; + } kWildCardMimeTypes[] = { + { "audio", IDS_APP_AUDIO_FILES }, + { "image", IDS_APP_IMAGE_FILES }, + { "text", IDS_APP_TEXT_FILES }, + { "video", IDS_APP_VIDEO_FILES }, + }; + + for (size_t i = 0; i < arraysize(kWildCardMimeTypes); ++i) { + if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*") + return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id); + } + + return std::wstring(); +} + +std::wstring GetFilterStringFromAcceptTypes( + const std::vector& accept_types) { + std::vector extensions; + std::vector descriptions; + + for (size_t i = 0; i < accept_types.size(); ++i) { + std::string ascii_type = base::UTF16ToASCII(accept_types[i]); + if (ascii_type.length()) { + // Just treat as extension if contains '.' as the first character. + if (ascii_type[0] == '.') { + extensions.push_back(L"*" + base::ASCIIToWide(ascii_type)); + descriptions.push_back(std::wstring()); + } else { + // Otherwise convert mime type to one or more extensions. + std::vector ext; + std::wstring ext_str; + net::GetExtensionsForMimeType(ascii_type, &ext); + if (ext.size() > 0) { + for (size_t x = 0; x < ext.size(); ++x) { + if (x != 0) + ext_str += L";"; + ext_str += L"*." + ext[x]; + } + extensions.push_back(ext_str); + descriptions.push_back(GetDescriptionFromMimeType(ascii_type)); + } + } + } + } + + return FormatFilterForExtensions(extensions, descriptions, true); +} + +// from chrome/browser/views/shell_dialogs_win.cc + +bool RunOpenFileDialog(const content::FileChooserParams& params, + HWND owner, + base::FilePath* path) { + OPENFILENAME ofn; + + // We must do this otherwise the ofn's FlagsEx may be initialized to random + // junk in release builds which can cause the Places Bar not to show up! + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = owner; + + // Consider default file name if any. + base::FilePath default_file_name(params.default_file_name); + + wchar_t filename[MAX_PATH] = {0}; + + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + + std::wstring directory; + if (!default_file_name.empty()) { + base::wcslcpy(filename, default_file_name.value().c_str(), + arraysize(filename)); + + directory = default_file_name.DirName().value(); + ofn.lpstrInitialDir = directory.c_str(); + } + + std::wstring title; + if (!params.title.empty()) + title = params.title; + else + title = l10n_util::GetStringUTF16(IDS_OPEN_FILE_DIALOG_TITLE); + if (!title.empty()) + ofn.lpstrTitle = title.c_str(); + + // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory + // without having to close Chrome first. + ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER | + OFN_ENABLESIZING; + + std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types); + if (!filter.empty()) + ofn.lpstrFilter = filter.c_str(); + + bool success = !!GetOpenFileName(&ofn); + if (success) + *path = base::FilePath(filename); + return success; +} + +bool RunOpenMultiFileDialog(const content::FileChooserParams& params, + HWND owner, + std::vector* paths) { + OPENFILENAME ofn; + + // We must do this otherwise the ofn's FlagsEx may be initialized to random + // junk in release builds which can cause the Places Bar not to show up! + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = owner; + + scoped_ptr filename(new wchar_t[UNICODE_STRING_MAX_CHARS]); + filename[0] = 0; + + ofn.lpstrFile = filename.get(); + ofn.nMaxFile = UNICODE_STRING_MAX_CHARS; + + std::wstring title; + if (!params.title.empty()) + title = params.title; + else + title = l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE); + if (!title.empty()) + ofn.lpstrTitle = title.c_str(); + + // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory + // without having to close Chrome first. + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | + OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING; + + std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types); + if (!filter.empty()) + ofn.lpstrFilter = filter.c_str(); + + bool success = !!GetOpenFileName(&ofn); + + if (success) { + std::vector files; + const wchar_t* selection = ofn.lpstrFile; + while (*selection) { // Empty string indicates end of list. + files.push_back(base::FilePath(selection)); + // Skip over filename and null-terminator. + selection += files.back().value().length() + 1; + } + if (files.empty()) { + success = false; + } else if (files.size() == 1) { + // When there is one file, it contains the path and filename. + paths->swap(files); + } else { + // Otherwise, the first string is the path, and the remainder are + // filenames. + std::vector::iterator path = files.begin(); + for (std::vector::iterator file = path + 1; + file != files.end(); ++file) { + paths->push_back(path->Append(*file)); + } + } + } + return success; +} + +bool RunSaveFileDialog(const content::FileChooserParams& params, + HWND owner, + base::FilePath* path) { + OPENFILENAME ofn; + + // We must do this otherwise the ofn's FlagsEx may be initialized to random + // junk in release builds which can cause the Places Bar not to show up! + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = owner; + + // Consider default file name if any. + base::FilePath default_file_name(params.default_file_name); + + wchar_t filename[MAX_PATH] = {0}; + + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + + std::wstring directory; + if (!default_file_name.empty()) { + base::wcslcpy(filename, default_file_name.value().c_str(), + arraysize(filename)); + + directory = default_file_name.DirName().value(); + ofn.lpstrInitialDir = directory.c_str(); + } + + std::wstring title; + if (!params.title.empty()) + title = params.title; + else + title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE); + if (!title.empty()) + ofn.lpstrTitle = title.c_str(); + + // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory + // without having to close Chrome first. + ofn.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING | + OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST; + + std::wstring filter = GetFilterStringFromAcceptTypes(params.accept_types); + if (!filter.empty()) + ofn.lpstrFilter = filter.c_str(); + + bool success = !!GetSaveFileName(&ofn); + if (success) + *path = base::FilePath(filename); + return success; +} + + +// According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp: +// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in +// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 +// support URLS of 2083 chars in length, 2K is safe." +const int kMaxAddressLengthChars = 2048; + +bool HasExternalHandler(const std::string& scheme) { + base::win::RegKey key; + const std::wstring registry_path = + base::ASCIIToWide(scheme + "\\shell\\open\\command"); + key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ); + if (key.Valid()) { + DWORD size = 0; + key.ReadValue(NULL, NULL, &size, NULL); + if (size > 2) { + // ShellExecute crashes the process when the command is empty. + // We check for "2" because it always returns the trailing NULL. + return true; + } + } + + return false; +} + +WORD KeyStatesToWord() { + static const USHORT kHighBitMaskShort = 0x8000; + WORD result = 0; + + if (GetKeyState(VK_CONTROL) & kHighBitMaskShort) + result |= MK_CONTROL; + if (GetKeyState(VK_SHIFT) & kHighBitMaskShort) + result |= MK_SHIFT; + if (GetKeyState(VK_LBUTTON) & kHighBitMaskShort) + result |= MK_LBUTTON; + if (GetKeyState(VK_MBUTTON) & kHighBitMaskShort) + result |= MK_MBUTTON; + if (GetKeyState(VK_RBUTTON) & kHighBitMaskShort) + result |= MK_RBUTTON; + return result; +} + +// From content/common/cursors/webcursor_win.cc. + +using blink::WebCursorInfo; + +LPCWSTR ToCursorID(WebCursorInfo::Type type) { + switch (type) { + case WebCursorInfo::TypePointer: + return IDC_ARROW; + case WebCursorInfo::TypeCross: + return IDC_CROSS; + case WebCursorInfo::TypeHand: + return IDC_HAND; + case WebCursorInfo::TypeIBeam: + return IDC_IBEAM; + case WebCursorInfo::TypeWait: + return IDC_WAIT; + case WebCursorInfo::TypeHelp: + return IDC_HELP; + case WebCursorInfo::TypeEastResize: + return IDC_SIZEWE; + case WebCursorInfo::TypeNorthResize: + return IDC_SIZENS; + case WebCursorInfo::TypeNorthEastResize: + return IDC_SIZENESW; + case WebCursorInfo::TypeNorthWestResize: + return IDC_SIZENWSE; + case WebCursorInfo::TypeSouthResize: + return IDC_SIZENS; + case WebCursorInfo::TypeSouthEastResize: + return IDC_SIZENWSE; + case WebCursorInfo::TypeSouthWestResize: + return IDC_SIZENESW; + case WebCursorInfo::TypeWestResize: + return IDC_SIZEWE; + case WebCursorInfo::TypeNorthSouthResize: + return IDC_SIZENS; + case WebCursorInfo::TypeEastWestResize: + return IDC_SIZEWE; + case WebCursorInfo::TypeNorthEastSouthWestResize: + return IDC_SIZENESW; + case WebCursorInfo::TypeNorthWestSouthEastResize: + return IDC_SIZENWSE; + case WebCursorInfo::TypeColumnResize: + return MAKEINTRESOURCE(IDC_COLRESIZE); + case WebCursorInfo::TypeRowResize: + return MAKEINTRESOURCE(IDC_ROWRESIZE); + case WebCursorInfo::TypeMiddlePanning: + return MAKEINTRESOURCE(IDC_PAN_MIDDLE); + case WebCursorInfo::TypeEastPanning: + return MAKEINTRESOURCE(IDC_PAN_EAST); + case WebCursorInfo::TypeNorthPanning: + return MAKEINTRESOURCE(IDC_PAN_NORTH); + case WebCursorInfo::TypeNorthEastPanning: + return MAKEINTRESOURCE(IDC_PAN_NORTH_EAST); + case WebCursorInfo::TypeNorthWestPanning: + return MAKEINTRESOURCE(IDC_PAN_NORTH_WEST); + case WebCursorInfo::TypeSouthPanning: + return MAKEINTRESOURCE(IDC_PAN_SOUTH); + case WebCursorInfo::TypeSouthEastPanning: + return MAKEINTRESOURCE(IDC_PAN_SOUTH_EAST); + case WebCursorInfo::TypeSouthWestPanning: + return MAKEINTRESOURCE(IDC_PAN_SOUTH_WEST); + case WebCursorInfo::TypeWestPanning: + return MAKEINTRESOURCE(IDC_PAN_WEST); + case WebCursorInfo::TypeMove: + return IDC_SIZEALL; + case WebCursorInfo::TypeVerticalText: + return MAKEINTRESOURCE(IDC_VERTICALTEXT); + case WebCursorInfo::TypeCell: + return MAKEINTRESOURCE(IDC_CELL); + case WebCursorInfo::TypeContextMenu: + return MAKEINTRESOURCE(IDC_ARROW); + case WebCursorInfo::TypeAlias: + return MAKEINTRESOURCE(IDC_ALIAS); + case WebCursorInfo::TypeProgress: + return IDC_APPSTARTING; + case WebCursorInfo::TypeNoDrop: + return IDC_NO; + case WebCursorInfo::TypeCopy: + return MAKEINTRESOURCE(IDC_COPYCUR); + case WebCursorInfo::TypeNone: + return MAKEINTRESOURCE(IDC_CURSOR_NONE); + case WebCursorInfo::TypeNotAllowed: + return IDC_NO; + case WebCursorInfo::TypeZoomIn: + return MAKEINTRESOURCE(IDC_ZOOMIN); + case WebCursorInfo::TypeZoomOut: + return MAKEINTRESOURCE(IDC_ZOOMOUT); + case WebCursorInfo::TypeGrab: + return MAKEINTRESOURCE(IDC_HAND_GRAB); + case WebCursorInfo::TypeGrabbing: + return MAKEINTRESOURCE(IDC_HAND_GRABBING); + } + NOTREACHED(); + return NULL; +} + +bool IsSystemCursorID(LPCWSTR cursor_id) { + return cursor_id >= IDC_ARROW; // See WinUser.h +} + +} // namespace + +// static +void CefBrowserHostImpl::RegisterWindowClass() { + // Register the window class + WNDCLASSEX wcex = { + /* cbSize = */ sizeof(WNDCLASSEX), + /* style = */ CS_HREDRAW | CS_VREDRAW, + /* lpfnWndProc = */ CefBrowserHostImpl::WndProc, + /* cbClsExtra = */ 0, + /* cbWndExtra = */ 0, + /* hInstance = */ ::GetModuleHandle(NULL), + /* hIcon = */ NULL, + /* hCursor = */ LoadCursor(NULL, IDC_ARROW), + /* hbrBackground = */ 0, + /* lpszMenuName = */ NULL, + /* lpszClassName = */ CefBrowserHostImpl::GetWndClass(), + /* hIconSm = */ NULL, + }; + RegisterClassEx(&wcex); +} + +// static +LPCTSTR CefBrowserHostImpl::GetWndClass() { + return L"CefBrowserWindow"; +} + +// static +LRESULT CALLBACK CefBrowserHostImpl::WndProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) { + CefBrowserHostImpl* browser = + static_cast(gfx::GetWindowUserData(hwnd)); + + switch (message) { + case WM_CLOSE: + // Protect against multiple requests to close while the close is pending. + if (browser && browser->destruction_state() <= DESTRUCTION_STATE_PENDING) { + if (browser->destruction_state() == DESTRUCTION_STATE_NONE) { + // Request that the browser close. + browser->CloseBrowser(false); + } + + // Cancel the close. + return 0; + } + + // Allow the close. + break; + + case WM_DESTROY: + if (browser) { + // Clear the user data pointer. + gfx::SetWindowUserData(hwnd, NULL); + + // Force the browser to be destroyed and release the reference added in + // PlatformCreateWindow(). + browser->WindowDestroyed(); + } + return 0; + + case WM_SIZE: + // Minimizing resizes the window to 0x0 which causes our layout to go all + // screwy, so we just ignore it. + if (wParam != SIZE_MINIMIZED && browser && browser->window_widget_) { + // Resize the Widget window to the full size of the browser window. + RECT rc; + GetClientRect(hwnd, &rc); + browser->window_widget_->SetSize(gfx::Size(rc.right, rc.bottom)); + } + return 0; + + case WM_SETFOCUS: + if (browser) + browser->SetFocus(true); + return 0; + + case WM_ERASEBKGND: + return 0; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor( + blink::WebCursorInfo::Type type) { + HMODULE module_handle = NULL; + const wchar_t* cursor_id = ToCursorID(type); + if (!IsSystemCursorID(cursor_id)) { + module_handle = ::GetModuleHandle( + CefContentBrowserClient::Get()->GetResourceDllName()); + if (!module_handle) + module_handle = ::GetModuleHandle(NULL); + } + + return LoadCursor(module_handle, cursor_id); +} + +bool CefBrowserHostImpl::PlatformCreateWindow() { + std::wstring windowName(CefString(&window_info_.window_name)); + + // Create the new browser window. + window_info_.window = CreateWindowEx(window_info_.ex_style, + GetWndClass(), windowName.c_str(), window_info_.style, + window_info_.x, window_info_.y, window_info_.width, + window_info_.height, window_info_.parent_window, window_info_.menu, + ::GetModuleHandle(NULL), NULL); + + // It's possible for CreateWindowEx to fail if the parent window was + // destroyed between the call to CreateBrowser and the above one. + DCHECK(window_info_.window != NULL); + if (!window_info_.window) + return false; + + // Set window user data to this object for future reference from the window + // procedure. + gfx::SetWindowUserData(window_info_.window, this); + + // Add a reference that will be released in the WM_DESTROY handler. + AddRef(); + + RECT cr; + GetClientRect(window_info_.window, &cr); + + DCHECK(!window_widget_); + + SkColor background_color = SK_ColorWHITE; + const CefSettings& settings = CefContext::Get()->settings(); + if (CefColorGetA(settings.background_color) > 0) { + background_color = SkColorSetRGB( + CefColorGetR(settings.background_color), + CefColorGetG(settings.background_color), + CefColorGetB(settings.background_color)); + } + + CefWindowDelegateView* delegate_view = + new CefWindowDelegateView(background_color); + delegate_view->Init(window_info_.window, + web_contents(), + gfx::Rect(0, 0, cr.right, cr.bottom)); + + window_widget_ = delegate_view->GetWidget(); + window_widget_->Show(); + + return true; +} + +void CefBrowserHostImpl::PlatformCloseWindow() { + if (window_info_.window != NULL) { + HWND frameWnd = GetAncestor(window_info_.window, GA_ROOT); + PostMessage(frameWnd, WM_CLOSE, 0, 0); + } +} + +void CefBrowserHostImpl::PlatformSizeTo(int width, int height) { + RECT rect = {0, 0, width, height}; + DWORD style = GetWindowLong(window_info_.window, GWL_STYLE); + DWORD ex_style = GetWindowLong(window_info_.window, GWL_EXSTYLE); + bool has_menu = !(style & WS_CHILD) && (GetMenu(window_info_.window) != NULL); + + // The size value is for the client area. Calculate the whole window size + // based on the current style. + AdjustWindowRectEx(&rect, style, has_menu, ex_style); + + // Size the window. + SetWindowPos(window_info_.window, NULL, 0, 0, rect.right, + rect.bottom, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); +} + +void CefBrowserHostImpl::PlatformSetFocus(bool focus) { + if (!focus) + return; + + if (web_contents_) { + // Give logical focus to the RenderWidgetHostViewAura in the views + // hierarchy. This does not change the native keyboard focus. + web_contents_->Focus(); + } + + if (window_widget_) { + // Give native focus to the DesktopNativeWidgetAura for the root window. + // Needs to be done via the HWND so that keyboard focus is assigned + // correctly. DesktopNativeWidgetAura will update focus state on the + // aura::Window when WM_SETFOCUS and WM_KILLFOCUS are received. + ::SetFocus(HWNDForWidget(window_widget_)); + } +} + +CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() { + return IsWindowless() ? window_info_.parent_window : window_info_.window; +} + +bool CefBrowserHostImpl::PlatformViewText(const std::string& text) { + CEF_REQUIRE_UIT(); + + std::string str = text; + scoped_refptr str_ref = + base::RefCountedString::TakeString(&str); + CEF_POST_TASK(CEF_FILET, base::Bind(WriteTempFileAndView, str_ref)); + return true; +} + +void CefBrowserHostImpl::PlatformHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { + // Any unhandled keyboard/character messages are sent to DefWindowProc so that + // shortcut keys work correctly. + if (event.os_event) { + const MSG& msg = event.os_event->native_event(); + DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); + } +} + +void CefBrowserHostImpl::PlatformRunFileChooser( + const content::FileChooserParams& params, + RunFileChooserCallback callback) { + std::vector files; + + if (params.mode == content::FileChooserParams::Open) { + base::FilePath file; + if (RunOpenFileDialog(params, PlatformGetWindowHandle(), &file)) + files.push_back(file); + } else if (params.mode == content::FileChooserParams::OpenMultiple) { + RunOpenMultiFileDialog(params, PlatformGetWindowHandle(), &files); + } else if (params.mode == content::FileChooserParams::Save) { + base::FilePath file; + if (RunSaveFileDialog(params, PlatformGetWindowHandle(), &file)) + files.push_back(file); + } else { + NOTIMPLEMENTED(); + } + + callback.Run(files); +} + +void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { + if (CEF_CURRENTLY_ON_FILET()) { + if (!HasExternalHandler(url.scheme())) + return; + + const std::string& address = url.spec(); + if (address.length() > kMaxAddressLengthChars) + return; + + ShellExecuteA(NULL, "open", address.c_str(), NULL, NULL, SW_SHOWNORMAL); + } else { + // Execute on the FILE thread. + CEF_POST_TASK(CEF_FILET, + base::Bind(&CefBrowserHostImpl::PlatformHandleExternalProtocol, this, + url)); + } +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& result, const CefKeyEvent& key_event) { + result.timeStampSeconds = GetMessageTime() / 1000.0; + + result.windowsKeyCode = key_event.windows_key_code; + result.nativeKeyCode = key_event.native_key_code; + result.isSystemKey = key_event.is_system_key ? 1 : 0; + switch (key_event.type) { + case KEYEVENT_RAWKEYDOWN: + case KEYEVENT_KEYDOWN: + result.type = blink::WebInputEvent::RawKeyDown; + break; + case KEYEVENT_KEYUP: + result.type = blink::WebInputEvent::KeyUp; + break; + case KEYEVENT_CHAR: + result.type = blink::WebInputEvent::Char; + break; + default: + NOTREACHED(); + } + + if (result.type == blink::WebInputEvent::Char || + result.type == blink::WebInputEvent::RawKeyDown) { + result.text[0] = result.windowsKeyCode; + result.unmodifiedText[0] = result.windowsKeyCode; + } + if (result.type != blink::WebInputEvent::Char) + result.setKeyIdentifierFromWindowsKeyCode(); + + result.modifiers |= TranslateModifiers(key_event.modifiers); +} + +void CefBrowserHostImpl::PlatformTranslateClickEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + CefBrowserHost::MouseButtonType type, + bool mouseUp, int clickCount) { + PlatformTranslateMouseEvent(result, mouse_event); + + switch (type) { + case MBT_LEFT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonLeft; + break; + case MBT_MIDDLE: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonMiddle; + break; + case MBT_RIGHT: + result.type = mouseUp ? blink::WebInputEvent::MouseUp : + blink::WebInputEvent::MouseDown; + result.button = blink::WebMouseEvent::ButtonRight; + break; + default: + NOTREACHED(); + } + + result.clickCount = clickCount; +} + +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + PlatformTranslateMouseEvent(result, mouse_event); + + if (!mouseLeave) { + result.type = blink::WebInputEvent::MouseMove; + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = blink::WebMouseEvent::ButtonRight; + else + result.button = blink::WebMouseEvent::ButtonNone; + } else { + result.type = blink::WebInputEvent::MouseLeave; + result.button = blink::WebMouseEvent::ButtonNone; + } + + result.clickCount = 0; +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + blink::WebMouseWheelEvent& result, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + PlatformTranslateMouseEvent(result, mouse_event); + + result.type = blink::WebInputEvent::MouseWheel; + result.button = blink::WebMouseEvent::ButtonNone; + + float wheelDelta; + bool horizontalScroll = false; + + wheelDelta = static_cast(deltaY ? deltaY : deltaX); + + horizontalScroll = (deltaY == 0); + + static const ULONG defaultScrollCharsPerWheelDelta = 1; + static const FLOAT scrollbarPixelsPerLine = 100.0f / 3.0f; + static const ULONG defaultScrollLinesPerWheelDelta = 3; + wheelDelta /= WHEEL_DELTA; + float scrollDelta = wheelDelta; + if (horizontalScroll) { + ULONG scrollChars = defaultScrollCharsPerWheelDelta; + SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0); + scrollDelta *= static_cast(scrollChars) * scrollbarPixelsPerLine; + } else { + ULONG scrollLines = defaultScrollLinesPerWheelDelta; + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0); + if (scrollLines == WHEEL_PAGESCROLL) + result.scrollByPage = true; + if (!result.scrollByPage) + scrollDelta *= static_cast(scrollLines) * scrollbarPixelsPerLine; + } + + // Set scroll amount based on above calculations. WebKit expects positive + // deltaY to mean "scroll up" and positive deltaX to mean "scroll left". + if (horizontalScroll) { + result.deltaX = scrollDelta; + result.wheelTicksX = wheelDelta; + } else { + result.deltaY = scrollDelta; + result.wheelTicksY = wheelDelta; + } +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + blink::WebMouseEvent& result, + const CefMouseEvent& mouse_event) { + // position + result.x = mouse_event.x; + result.y = mouse_event.y; + result.windowX = result.x; + result.windowY = result.y; + result.globalX = result.x; + result.globalY = result.y; + + if (IsWindowless()) { + GetClient()->GetRenderHandler()->GetScreenPoint( + GetBrowser(), + result.x, result.y, + result.globalX, result.globalY); + } else { + POINT globalPoint = { result.x, result.y }; + ClientToScreen(GetWindowHandle(), &globalPoint); + result.globalX = globalPoint.x; + result.globalY = globalPoint.y; + } + + // modifiers + result.modifiers |= TranslateModifiers(mouse_event.modifiers); + + // timestamp + result.timeStampSeconds = GetMessageTime() / 1000.0; +} diff --git a/libcef/browser/browser_info.cc b/libcef/browser/browser_info.cc new file mode 100644 index 000000000..6ca13c4cd --- /dev/null +++ b/libcef/browser/browser_info.cc @@ -0,0 +1,112 @@ +// 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 "libcef/browser/browser_info.h" +#include "ipc/ipc_message.h" + +CefBrowserInfo::CefBrowserInfo(int browser_id, bool is_popup) + : browser_id_(browser_id), + is_popup_(is_popup), + is_windowless_(false) { + DCHECK_GT(browser_id, 0); +} + +CefBrowserInfo::~CefBrowserInfo() { +} + +void CefBrowserInfo::set_windowless(bool windowless) { + is_windowless_ = windowless; +} + +void CefBrowserInfo::add_render_view_id( + int render_process_id, int render_routing_id) { + add_render_id(&render_view_id_set_, render_process_id, render_routing_id); +} + +void CefBrowserInfo::add_render_frame_id( + int render_process_id, int render_routing_id) { + add_render_id(&render_frame_id_set_, render_process_id, render_routing_id); +} + +void CefBrowserInfo::remove_render_view_id( + int render_process_id, int render_routing_id) { + remove_render_id(&render_view_id_set_, render_process_id, render_routing_id); +} + +void CefBrowserInfo::remove_render_frame_id( + int render_process_id, int render_routing_id) { + remove_render_id(&render_frame_id_set_, render_process_id, render_routing_id); +} + +bool CefBrowserInfo::is_render_view_id_match( + int render_process_id, int render_routing_id) { + return is_render_id_match(&render_view_id_set_, + render_process_id, + render_routing_id); +} + +bool CefBrowserInfo::is_render_frame_id_match( + int render_process_id, int render_routing_id) { + return is_render_id_match(&render_frame_id_set_, + render_process_id, + render_routing_id); +} + +CefRefPtr CefBrowserInfo::browser() { + base::AutoLock lock_scope(lock_); + return browser_; +} + +void CefBrowserInfo::set_browser(CefRefPtr browser) { + base::AutoLock lock_scope(lock_); + browser_ = browser; +} + +void CefBrowserInfo::add_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { + DCHECK_GT(render_process_id, 0); + DCHECK_GT(render_routing_id, 0); + + base::AutoLock lock_scope(lock_); + + if (!id_set->empty()) { + RenderIdSet::const_iterator it = + id_set->find(std::make_pair(render_process_id, render_routing_id)); + if (it != id_set->end()) + return; + } + + id_set->insert(std::make_pair(render_process_id, render_routing_id)); +} + +void CefBrowserInfo::remove_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { + DCHECK_GT(render_process_id, 0); + DCHECK_GT(render_routing_id, 0); + + base::AutoLock lock_scope(lock_); + + DCHECK(!id_set->empty()); + if (id_set->empty()) + return; + + bool erased = id_set->erase( + std::make_pair(render_process_id, render_routing_id)) != 0; + DCHECK(erased); +} + +bool CefBrowserInfo::is_render_id_match(const RenderIdSet* id_set, + int render_process_id, + int render_routing_id) { + base::AutoLock lock_scope(lock_); + + if (id_set->empty()) + return false; + + RenderIdSet::const_iterator it = + id_set->find(std::make_pair(render_process_id, render_routing_id)); + return (it != id_set->end()); +} diff --git a/libcef/browser/browser_info.h b/libcef/browser/browser_info.h new file mode 100644 index 000000000..b84cbbc25 --- /dev/null +++ b/libcef/browser/browser_info.h @@ -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_LIBCEF_BROWSER_BROWSER_INFO_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_INFO_H_ +#pragma once + +#include + +#include "libcef/browser/browser_host_impl.h" +#include "base/memory/ref_counted.h" + +// CefBrowserInfo is used to associate a browser ID and render view/process +// IDs with a particular CefBrowserHostImpl. Render view/process IDs may change +// during the lifetime of a single CefBrowserHostImpl. +// +// CefBrowserInfo objects are managed by CefContentBrowserClient and should not +// be created directly. +class CefBrowserInfo : public base::RefCountedThreadSafe { + public: + CefBrowserInfo(int browser_id, bool is_popup); + virtual ~CefBrowserInfo(); + + int browser_id() const { return browser_id_; }; + bool is_popup() const { return is_popup_; } + bool is_windowless() const { return is_windowless_; } + + void set_windowless(bool windowless); + + // Adds an ID pair if it doesn't already exist. + void add_render_view_id(int render_process_id, int render_routing_id); + void add_render_frame_id(int render_process_id, int render_routing_id); + + // Remove an ID pair if it exists. + void remove_render_view_id(int render_process_id, int render_routing_id); + void remove_render_frame_id(int render_process_id, int render_routing_id); + + // Returns true if this browser matches the specified ID pair. + bool is_render_view_id_match(int render_process_id, int render_routing_id); + bool is_render_frame_id_match(int render_process_id, int render_routing_id); + + CefRefPtr browser(); + void set_browser(CefRefPtr browser); + + private: + typedef std::set > RenderIdSet; + + void add_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + void remove_render_id(RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + bool is_render_id_match(const RenderIdSet* id_set, + int render_process_id, + int render_routing_id); + + int browser_id_; + bool is_popup_; + bool is_windowless_; + + base::Lock lock_; + + // The below members must be protected by |lock_|. + + // Set of mapped (process_id, routing_id) pairs. Keeping this set is + // necessary for the following reasons: + // 1. When navigating cross-origin the new (pending) RenderViewHost will be + // created before the old (current) RenderViewHost is destroyed. + // 2. When canceling and asynchronously continuing navigation of the same URL + // a new RenderViewHost may be created for the first (canceled) navigation + // and then destroyed as a result of the second (allowed) navigation. + // 3. Out-of-process iframes have their own render IDs which must also be + // associated with the host browser. + RenderIdSet render_view_id_set_; + RenderIdSet render_frame_id_set_; + + // May be NULL if the browser has not yet been created or if the browser has + // been destroyed. + CefRefPtr browser_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserInfo); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_ diff --git a/libcef/browser/browser_main.cc b/libcef/browser/browser_main.cc new file mode 100644 index 000000000..36561a6ca --- /dev/null +++ b/libcef/browser/browser_main.cc @@ -0,0 +1,205 @@ +// 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 "libcef/browser/browser_main.h" + +#include + +#include "libcef/browser/browser_context_impl.h" +#include "libcef/browser/browser_message_loop.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/devtools_delegate.h" +#include "libcef/common/net_resource_provider.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/net/proxy_service_factory.h" +#include "content/browser/webui/content_web_ui_controller_factory.h" +#include "content/public/browser/gpu_data_manager.h" +#include "content/public/browser/web_ui_controller_factory.h" +#include "content/public/common/content_switches.h" +#include "net/base/net_module.h" +#include "net/proxy/proxy_resolver_v8.h" +#include "ui/base/resource/resource_bundle.h" +#include "v8/include/v8.h" + +#if defined(USE_AURA) +#include "ui/aura/env.h" +#include "ui/gfx/screen.h" +#include "ui/views/test/desktop_test_views_delegate.h" +#include "ui/views/widget/desktop_aura/desktop_screen.h" + +#if defined(OS_WIN) +#include "ui/base/cursor/cursor_loader_win.h" +#endif +#endif // defined(USE_AURA) + +#if defined(USE_AURA) && defined(OS_LINUX) +#include "ui/base/ime/input_method_initializer.h" +#endif + +#if defined(OS_LINUX) +#include "libcef/browser/printing/print_dialog_linux.h" +#endif + +CefBrowserMainParts::CefBrowserMainParts( + const content::MainFunctionParams& parameters) + : BrowserMainParts(), + proxy_v8_isolate_(NULL) { +} + +CefBrowserMainParts::~CefBrowserMainParts() { +} + +void CefBrowserMainParts::PreMainMessageLoopStart() { + if (!base::MessageLoop::current()) { + // Create the browser message loop. + message_loop_.reset(new CefBrowserMessageLoop()); + message_loop_->set_thread_name("CrBrowserMain"); + } +} + +void CefBrowserMainParts::PreEarlyInitialization() { +#if defined(USE_AURA) && defined(OS_LINUX) + // TODO(linux): Consider using a real input method or + // views::LinuxUI::SetInstance. + ui::InitializeInputMethodForTesting(); +#endif +} + +void CefBrowserMainParts::ToolkitInitialized() { +#if defined(USE_AURA) + CHECK(aura::Env::GetInstance()); + + DCHECK(!views::ViewsDelegate::views_delegate); + new views::DesktopTestViewsDelegate; + +#if defined(OS_WIN) + ui::CursorLoaderWin::SetCursorResourceModule( + CefContentBrowserClient::Get()->GetResourceDllName()); +#endif +#endif // defined(USE_AURA) +} + +void CefBrowserMainParts::PostMainMessageLoopStart() { + // Don't use the default WebUI controller factory because is conflicts with + // CEF's internal handling of "chrome://tracing". + content::WebUIControllerFactory::UnregisterFactoryForTesting( + content::ContentWebUIControllerFactory::GetInstance()); + +#if defined(OS_LINUX) + printing::PrintingContextLinux::SetCreatePrintDialogFunction( + &CefPrintDialogLinux::CreatePrintDialog); +#endif +} + +int CefBrowserMainParts::PreCreateThreads() { + PlatformInitialize(); + net::NetModule::SetResourceProvider(&NetResourceProvider); + + // Initialize the GpuDataManager before IO access restrictions are applied and + // before the IO thread is started. + content::GpuDataManager::GetInstance(); + +#if defined(USE_AURA) + gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, + views::CreateDesktopScreen()); +#endif + + // Initialize user preferences. + pref_store_ = new CefBrowserPrefStore(); + pref_store_->SetInitializationCompleted(); + pref_service_ = pref_store_->CreateService().Pass(); + + // Create a v8::Isolate for the current thread if it doesn't already exist. + if (!v8::Isolate::GetCurrent()) { + proxy_v8_isolate_ = v8::Isolate::New(); + proxy_v8_isolate_->Enter(); + } + + // Initialize the V8 proxy integration. + net::ProxyResolverV8::EnsureIsolateCreated(); + + // Initialize proxy configuration tracker. + pref_proxy_config_tracker_.reset( + ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( + pref_service_.get())); + + return 0; +} + +void CefBrowserMainParts::PreMainMessageLoopRun() { + // Create the global browser context. + global_browser_context_.reset(new CefBrowserContextImpl()); + + // Initialize the proxy configuration service. This needs to occur before + // CefURLRequestContextGetter::GetURLRequestContext() is called for the + // first time. + proxy_config_service_.reset( + ProxyServiceFactory::CreateProxyConfigService( + pref_proxy_config_tracker_.get())); + + // Initialize the request context getter. This indirectly triggers a call + // to CefURLRequestContextGetter::GetURLRequestContext() on the IO thread. + global_request_context_ = global_browser_context_->GetRequestContext(); + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kRemoteDebuggingPort)) { + std::string port_str = + command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort); + int port; + if (base::StringToInt(port_str, &port) && port > 0 && port < 65535) { + devtools_delegate_.reset(new CefDevToolsDelegate(port)); + } else { + LOG(WARNING) << "Invalid http debugger port number " << port; + } + } +} + +void CefBrowserMainParts::PostMainMessageLoopRun() { + if (devtools_delegate_) + devtools_delegate_->Stop(); + pref_proxy_config_tracker_->DetachFromPrefService(); + + // Only the global browser context should still exist. + DCHECK(browser_contexts_.empty()); + browser_contexts_.clear(); + + global_request_context_ = NULL; + global_browser_context_.reset(); +} + +void CefBrowserMainParts::PostDestroyThreads() { + pref_proxy_config_tracker_.reset(NULL); + + if (proxy_v8_isolate_) { + proxy_v8_isolate_->Exit(); + proxy_v8_isolate_->Dispose(); + } + +#if defined(USE_AURA) + aura::Env::DeleteInstance(); + delete views::ViewsDelegate::views_delegate; +#endif + + PlatformCleanup(); +} + +void CefBrowserMainParts::AddBrowserContext(CefBrowserContext* context) { + browser_contexts_.push_back(context); +} + +void CefBrowserMainParts::RemoveBrowserContext(CefBrowserContext* context) { + ScopedVector::iterator it = browser_contexts_.begin(); + for (; it != browser_contexts_.end(); ++it) { + if (*it == context) { + browser_contexts_.erase(it); + return; + } + } + + NOTREACHED(); +} diff --git a/libcef/browser/browser_main.h b/libcef/browser/browser_main.h new file mode 100644 index 000000000..58f826f62 --- /dev/null +++ b/libcef/browser/browser_main.h @@ -0,0 +1,86 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_ +#pragma once + +#include "libcef/browser/browser_pref_store.h" + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/prefs/pref_service.h" +#include "base/strings/string_piece.h" +#include "chrome/browser/net/pref_proxy_config_tracker.h" +#include "content/public/browser/browser_main_parts.h" +#include "net/proxy/proxy_config_service.h" +#include "net/url_request/url_request_context_getter.h" + +namespace base { +class MessageLoop; +class Thread; +} + +namespace content { +struct MainFunctionParams; +} + +namespace v8 { +class Isolate; +} + +class CefBrowserContext; +class CefDevToolsDelegate; + +class CefBrowserMainParts : public content::BrowserMainParts { + public: + explicit CefBrowserMainParts(const content::MainFunctionParams& parameters); + virtual ~CefBrowserMainParts(); + + virtual void PreMainMessageLoopStart() OVERRIDE; + virtual void PostMainMessageLoopStart() OVERRIDE; + virtual void PreEarlyInitialization() OVERRIDE; + virtual void ToolkitInitialized() OVERRIDE; + virtual int PreCreateThreads() OVERRIDE; + virtual void PreMainMessageLoopRun() OVERRIDE; + virtual void PostMainMessageLoopRun() OVERRIDE; + virtual void PostDestroyThreads() OVERRIDE; + + CefBrowserContext* browser_context() const { + return global_browser_context_.get(); + } + scoped_refptr request_context() const { + return global_request_context_; + } + CefDevToolsDelegate* devtools_delegate() const { + return devtools_delegate_.get(); + } + PrefService* pref_service() const { return pref_service_.get(); } + scoped_ptr proxy_config_service() { + return proxy_config_service_.Pass(); + } + + void AddBrowserContext(CefBrowserContext* context); + void RemoveBrowserContext(CefBrowserContext* context); + + private: + void PlatformInitialize(); + void PlatformCleanup(); + + scoped_ptr global_browser_context_; + scoped_refptr global_request_context_; + ScopedVector browser_contexts_; + scoped_ptr devtools_delegate_; + scoped_ptr message_loop_; + scoped_ptr pref_proxy_config_tracker_; + scoped_ptr proxy_config_service_; + scoped_refptr pref_store_; + scoped_ptr pref_service_; + v8::Isolate* proxy_v8_isolate_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserMainParts); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_MAIN_H_ diff --git a/libcef/browser/browser_main_linux.cc b/libcef/browser/browser_main_linux.cc new file mode 100644 index 000000000..d9b14a323 --- /dev/null +++ b/libcef/browser/browser_main_linux.cc @@ -0,0 +1,11 @@ +// 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 "libcef/browser/browser_main.h" + +void CefBrowserMainParts::PlatformInitialize() { +} + +void CefBrowserMainParts::PlatformCleanup() { +} diff --git a/libcef/browser/browser_main_mac.mm b/libcef/browser/browser_main_mac.mm new file mode 100644 index 000000000..f9ea5b3f0 --- /dev/null +++ b/libcef/browser/browser_main_mac.mm @@ -0,0 +1,24 @@ +// 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 "libcef/browser/browser_main.h" +#include "libcef/browser/context.h" + +#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h" + +void CefBrowserMainParts::PlatformInitialize() { + const CefSettings& settings = CefContext::Get()->settings(); + if (CefColorGetA(settings.background_color) > 0) { + const float r = + static_cast(CefColorGetR(settings.background_color)) / 255.0f; + const float g = + static_cast(CefColorGetG(settings.background_color)) / 255.0f; + const float b = + static_cast(CefColorGetB(settings.background_color)) / 255.0f; + content::CompositingIOSurfaceShaderPrograms::SetBackgroundColor(r, g, b); + } +} + +void CefBrowserMainParts::PlatformCleanup() { +} diff --git a/libcef/browser/browser_main_win.cc b/libcef/browser/browser_main_win.cc new file mode 100644 index 000000000..094f2202f --- /dev/null +++ b/libcef/browser/browser_main_win.cc @@ -0,0 +1,32 @@ +// 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 +#include +#include + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_main.h" + +void CefBrowserMainParts::PlatformInitialize() { + HRESULT res; + + // Initialize common controls. + res = CoInitialize(NULL); + DCHECK(SUCCEEDED(res)); + INITCOMMONCONTROLSEX InitCtrlEx; + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + + // Start COM stuff. + res = OleInitialize(NULL); + DCHECK(SUCCEEDED(res)); + + // Register the browser window class. + CefBrowserHostImpl::RegisterWindowClass(); +} + +void CefBrowserMainParts::PlatformCleanup() { +} diff --git a/libcef/browser/browser_message_filter.cc b/libcef/browser/browser_message_filter.cc new file mode 100644 index 000000000..dd4f33097 --- /dev/null +++ b/libcef/browser/browser_message_filter.cc @@ -0,0 +1,110 @@ +/// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions (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 "libcef/browser/browser_message_filter.h" + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/origin_whitelist_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/cef_messages.h" +#include "libcef/common/content_client.h" +#include "libcef/common/values_impl.h" + +#include "base/compiler_specific.h" +#include "base/bind.h" +#include "content/common/view_messages.h" +#include "content/public/browser/render_process_host.h" + +CefBrowserMessageFilter::CefBrowserMessageFilter( + content::RenderProcessHost* host) + : host_(host), + sender_(NULL) { +} + +CefBrowserMessageFilter::~CefBrowserMessageFilter() { +} + +void CefBrowserMessageFilter::OnFilterAdded(IPC::Sender* sender) { + sender_ = sender; +} + +void CefBrowserMessageFilter::OnFilterRemoved() { +} + +bool CefBrowserMessageFilter::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + if (message.type() == ViewHostMsg_CreateWindow::ID) { + // Observe but don't handle this message. + handled = false; + } + + IPC_BEGIN_MESSAGE_MAP(CefBrowserMessageFilter, message) + IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo, + OnGetNewRenderThreadInfo) + IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewBrowserInfo, + OnGetNewBrowserInfo) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CreateWindow, OnCreateWindow) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +bool CefBrowserMessageFilter::Send(IPC::Message* message) { + return host_->Send(message); +} + +void CefBrowserMessageFilter::OnGetNewRenderThreadInfo( + CefProcessHostMsg_GetNewRenderThreadInfo_Params* params) { + GetCrossOriginWhitelistEntries(¶ms->cross_origin_whitelist_entries); + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetBrowserProcessHandler(); + if (handler.get()) { + CefRefPtr listValuePtr( + new CefListValueImpl(¶ms->extra_info, false, false)); + handler->OnRenderProcessThreadCreated(listValuePtr.get()); + listValuePtr->Detach(NULL); + } + } +} + +void CefBrowserMessageFilter::OnGetNewBrowserInfo( + int render_view_routing_id, + int render_frame_routing_id, + CefProcessHostMsg_GetNewBrowserInfo_Params* params) { + DCHECK_GT(render_view_routing_id, 0); + DCHECK_GT(render_frame_routing_id, 0); + + // Popup windows may not have info yet. + scoped_refptr info = + CefContentBrowserClient::Get()->GetOrCreateBrowserInfo( + host_->GetID(), + render_view_routing_id, + host_->GetID(), + render_frame_routing_id); + params->browser_id = info->browser_id(); + params->is_popup = info->is_popup(); + params->is_windowless = info->is_windowless(); +} + +void CefBrowserMessageFilter::OnCreateWindow( + const ViewHostMsg_CreateWindow_Params& params, + IPC::Message* reply_msg) { + CefContentBrowserClient::LastCreateWindowParams lcwp; + lcwp.opener_process_id = host_->GetID(); + lcwp.opener_view_id = params.opener_id; + lcwp.opener_frame_id = params.opener_render_frame_id; + lcwp.target_url = params.target_url; + lcwp.target_frame_name = params.frame_name; + CefContentBrowserClient::Get()->set_last_create_window_params(lcwp); + + // Reply message is not used. + delete reply_msg; +} diff --git a/libcef/browser/browser_message_filter.h b/libcef/browser/browser_message_filter.h new file mode 100644 index 000000000..a5f6d77d2 --- /dev/null +++ b/libcef/browser/browser_message_filter.h @@ -0,0 +1,52 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_ + +#include +#include "ipc/ipc_channel_proxy.h" +#include "ipc/message_filter.h" + +namespace content { +class RenderProcessHost; +} + +struct CefProcessHostMsg_GetNewBrowserInfo_Params; +struct CefProcessHostMsg_GetNewRenderThreadInfo_Params; +struct ViewHostMsg_CreateWindow_Params; + +// This class sends and receives control messages on the browser process. +class CefBrowserMessageFilter : public IPC::MessageFilter { + public: + explicit CefBrowserMessageFilter(content::RenderProcessHost* host); + virtual ~CefBrowserMessageFilter(); + + // IPC::ChannelProxy::MessageFilter implementation. + virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE; + virtual void OnFilterRemoved() OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + bool Send(IPC::Message* message); + + private: + // Message handlers. + void OnGetNewRenderThreadInfo( + CefProcessHostMsg_GetNewRenderThreadInfo_Params* params); + void OnGetNewBrowserInfo( + int render_view_routing_id, + int render_frame_routing_id, + CefProcessHostMsg_GetNewBrowserInfo_Params* params); + void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params, + IPC::Message* reply_msg); + + content::RenderProcessHost* host_; + IPC::Sender* sender_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserMessageFilter); +}; + + +#endif // CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_FILTER_H_ diff --git a/libcef/browser/browser_message_loop.cc b/libcef/browser/browser_message_loop.cc new file mode 100644 index 000000000..246d3f29c --- /dev/null +++ b/libcef/browser/browser_message_loop.cc @@ -0,0 +1,28 @@ +// 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 "libcef/browser/browser_message_loop.h" +#include "base/run_loop.h" + +CefBrowserMessageLoop::CefBrowserMessageLoop() { +} + +CefBrowserMessageLoop::~CefBrowserMessageLoop() { +} + +// static +CefBrowserMessageLoop* CefBrowserMessageLoop::current() { + base::MessageLoop* loop = base::MessageLoop::current(); + DCHECK_EQ(base::MessageLoop::TYPE_UI, loop->type()); + return static_cast(loop); +} + +void CefBrowserMessageLoop::DoMessageLoopIteration() { + base::RunLoop run_loop; + run_loop.RunUntilIdle(); +} + +void CefBrowserMessageLoop::RunMessageLoop() { + Run(); +} diff --git a/libcef/browser/browser_message_loop.h b/libcef/browser/browser_message_loop.h new file mode 100644 index 000000000..990b1aa9a --- /dev/null +++ b/libcef/browser/browser_message_loop.h @@ -0,0 +1,33 @@ +// 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_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/message_loop/message_loop.h" + +// Class used to process events on the current message loop. +class CefBrowserMessageLoop : public base::MessageLoopForUI { + typedef base::MessageLoopForUI inherited; + + public: + CefBrowserMessageLoop(); + virtual ~CefBrowserMessageLoop(); + + // Returns the MessageLoopForUI of the current thread. + static CefBrowserMessageLoop* current(); + + // Do a single interation of the UI message loop. + void DoMessageLoopIteration(); + + // Run the UI message loop. + void RunMessageLoop(); + + private: + DISALLOW_COPY_AND_ASSIGN(CefBrowserMessageLoop); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_MESSAGE_LOOP_H_ diff --git a/libcef/browser/browser_pref_store.cc b/libcef/browser/browser_pref_store.cc new file mode 100644 index 000000000..7c397ef04 --- /dev/null +++ b/libcef/browser/browser_pref_store.cc @@ -0,0 +1,39 @@ +// 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 "libcef/browser/browser_pref_store.h" +#include "libcef/browser/media_capture_devices_dispatcher.h" + +#include "base/command_line.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/pref_service_factory.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/values.h" +#include "chrome/browser/net/pref_proxy_config_tracker_impl.h" +#include "chrome/browser/prefs/command_line_pref_store.h" +#include "chrome/browser/prefs/proxy_config_dictionary.h" +#include "chrome/common/pref_names.h" + +CefBrowserPrefStore::CefBrowserPrefStore() { +} + +scoped_ptr CefBrowserPrefStore::CreateService() { + base::PrefServiceFactory factory; + factory.set_command_line_prefs( + new CommandLinePrefStore(CommandLine::ForCurrentProcess())); + factory.set_user_prefs(this); + + scoped_refptr registry(new PrefRegistrySimple()); + + // Default settings. + CefMediaCaptureDevicesDispatcher::RegisterPrefs(registry); + PrefProxyConfigTrackerImpl::RegisterPrefs(registry); + + registry->RegisterBooleanPref(prefs::kPrintingEnabled, true); + + return factory.Create(registry); +} + +CefBrowserPrefStore::~CefBrowserPrefStore() { +} diff --git a/libcef/browser/browser_pref_store.h b/libcef/browser/browser_pref_store.h new file mode 100644 index 000000000..191567826 --- /dev/null +++ b/libcef/browser/browser_pref_store.h @@ -0,0 +1,25 @@ +// 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_LIBCEF_BROWSER_BROWSER_PREF_STORE_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_PREF_STORE_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/prefs/testing_pref_store.h" + +class PrefService; + +class CefBrowserPrefStore : public TestingPrefStore { + public: + CefBrowserPrefStore(); + + scoped_ptr CreateService(); + + protected: + virtual ~CefBrowserPrefStore(); + + DISALLOW_COPY_AND_ASSIGN(CefBrowserPrefStore); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_PREF_STORE_H_ diff --git a/libcef/browser/browser_settings.cc b/libcef/browser/browser_settings.cc new file mode 100644 index 000000000..520613cb0 --- /dev/null +++ b/libcef/browser/browser_settings.cc @@ -0,0 +1,127 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + +#include "libcef/browser/browser_settings.h" + +#include + +#include "libcef/common/cef_switches.h" + +#include "base/command_line.h" +#include "include/internal/cef_types_wrappers.h" +#include "webkit/common/webpreferences.h" + +// Set default preferences based on CEF command-line flags. Chromium command- +// line flags should not exist for these preferences. +void SetDefaults(WebPreferences& web) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch(switches::kDefaultEncoding)) { + web.default_encoding = + command_line.GetSwitchValueASCII(switches::kDefaultEncoding); + } + + web.javascript_can_open_windows_automatically = + !command_line.HasSwitch(switches::kDisableJavascriptOpenWindows); + web.allow_scripts_to_close_windows = + !command_line.HasSwitch(switches::kDisableJavascriptCloseWindows); + web.javascript_can_access_clipboard = + !command_line.HasSwitch(switches::kDisableJavascriptAccessClipboard); + web.dom_paste_enabled = + !command_line.HasSwitch(switches::kDisableJavascriptDomPaste); + web.caret_browsing_enabled = + command_line.HasSwitch(switches::kEnableCaretBrowsing); + web.allow_universal_access_from_file_urls = + command_line.HasSwitch(switches::kAllowUniversalAccessFromFileUrls); + web.loads_images_automatically = + !command_line.HasSwitch(switches::kDisableImageLoading); + web.shrinks_standalone_images_to_fit = + command_line.HasSwitch(switches::kImageShrinkStandaloneToFit); + web.text_areas_are_resizable = + !command_line.HasSwitch(switches::kDisableTextAreaResize); + web.tabs_to_links = + !command_line.HasSwitch(switches::kDisableTabToLinks); +} + +// Helper macro for setting a WebPreferences variable based on the value of a +// CefBrowserSettings variable. +#define SET_STATE(cef_var, web_var) \ + if (cef_var == STATE_ENABLED) \ + web_var = true; \ + else if (cef_var == STATE_DISABLED) \ + web_var = false; + +// Use the preferences from WebContentsImpl::GetWebkitPrefs and the +// WebPreferences constructor by default. Only override features that are +// explicitly enabled or disabled. +void BrowserToWebSettings(const CefBrowserSettings& cef, WebPreferences& web) { + SetDefaults(web); + + if (cef.standard_font_family.length > 0) { + web.standard_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.standard_font_family); + } + if (cef.fixed_font_family.length > 0) { + web.fixed_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.fixed_font_family); + } + if (cef.serif_font_family.length > 0) { + web.serif_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.serif_font_family); + } + if (cef.sans_serif_font_family.length > 0) { + web.sans_serif_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.sans_serif_font_family); + } + if (cef.cursive_font_family.length > 0) { + web.cursive_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.cursive_font_family); + } + if (cef.fantasy_font_family.length > 0) { + web.fantasy_font_family_map[webkit_glue::kCommonScript] = + CefString(&cef.fantasy_font_family); + } + + if (cef.default_font_size > 0) + web.default_font_size = cef.default_font_size; + if (cef.default_fixed_font_size > 0) + web.default_fixed_font_size = cef.default_fixed_font_size; + if (cef.minimum_font_size > 0) + web.minimum_font_size = cef.minimum_font_size; + if (cef.minimum_logical_font_size > 0) + web.minimum_logical_font_size = cef.minimum_logical_font_size; + + if (cef.default_encoding.length > 0) + web.default_encoding = CefString(&cef.default_encoding); + + SET_STATE(cef.remote_fonts, web.remote_fonts_enabled); + SET_STATE(cef.javascript, web.javascript_enabled); + SET_STATE(cef.javascript_open_windows, + web.javascript_can_open_windows_automatically); + SET_STATE(cef.javascript_close_windows, web.allow_scripts_to_close_windows); + SET_STATE(cef.javascript_access_clipboard, + web.javascript_can_access_clipboard); + SET_STATE(cef.javascript_dom_paste, web.dom_paste_enabled); + SET_STATE(cef.caret_browsing, web.caret_browsing_enabled); + SET_STATE(cef.java, web.java_enabled); + SET_STATE(cef.plugins, web.plugins_enabled); + SET_STATE(cef.universal_access_from_file_urls, + web.allow_universal_access_from_file_urls); + SET_STATE(cef.file_access_from_file_urls, + web.allow_file_access_from_file_urls); + SET_STATE(cef.web_security, web.web_security_enabled); + SET_STATE(cef.image_loading, web.loads_images_automatically); + SET_STATE(cef.image_shrink_standalone_to_fit, + web.shrinks_standalone_images_to_fit); + SET_STATE(cef.text_area_resize, web.text_areas_are_resizable); + SET_STATE(cef.tab_to_links, web.tabs_to_links); + SET_STATE(cef.local_storage, web.local_storage_enabled); + SET_STATE(cef.databases, web.databases_enabled); + SET_STATE(cef.application_cache, web.application_cache_enabled); + + // Never explicitly enable GPU-related functions in this method because the + // GPU blacklist is not being checked here. + if (cef.webgl == STATE_DISABLED) + web.experimental_webgl_enabled = false; +} diff --git a/libcef/browser/browser_settings.h b/libcef/browser/browser_settings.h new file mode 100644 index 000000000..7b2ab3b14 --- /dev/null +++ b/libcef/browser/browser_settings.h @@ -0,0 +1,15 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_SETTINGS_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_SETTINGS_H_ +#pragma once + +#include "include/internal/cef_types_wrappers.h" + +struct WebPreferences; + +void BrowserToWebSettings(const CefBrowserSettings& cef, WebPreferences& web); + +#endif // CEF_LIBCEF_BROWSER_BROWSER_SETTINGS_H_ diff --git a/libcef/browser/browser_urlrequest_impl.cc b/libcef/browser/browser_urlrequest_impl.cc new file mode 100644 index 000000000..b576f12ae --- /dev/null +++ b/libcef/browser/browser_urlrequest_impl.cc @@ -0,0 +1,540 @@ +// 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 "libcef/browser/browser_urlrequest_impl.h" + +#include + +#include "libcef/browser/browser_context.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_user_data.h" +#include "libcef/common/http_header_utils.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/response_impl.h" + +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_util.h" +#include "content/public/common/url_fetcher.h" +#include "net/base/io_buffer.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_fetcher_response_writer.h" +#include "net/url_request/url_request_status.h" + + +namespace { + +class CefURLFetcherDelegate : public net::URLFetcherDelegate { + public: + CefURLFetcherDelegate(CefBrowserURLRequest::Context* context, + int request_flags); + virtual ~CefURLFetcherDelegate(); + + // net::URLFetcherDelegate methods. + virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; + virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source, + int64 current, int64 total) OVERRIDE; + virtual void OnURLFetchUploadProgress(const net::URLFetcher* source, + int64 current, int64 total) OVERRIDE; + + private: + // The context_ pointer will outlive this object. + CefBrowserURLRequest::Context* context_; + int request_flags_; +}; + +class NET_EXPORT CefURLFetcherResponseWriter : + public net::URLFetcherResponseWriter { + public: + CefURLFetcherResponseWriter( + CefRefPtr url_request, + scoped_refptr message_loop_proxy) + : url_request_(url_request), + message_loop_proxy_(message_loop_proxy) { + } + virtual ~CefURLFetcherResponseWriter() { + } + + // net::URLFetcherResponseWriter methods. + virtual int Initialize(const net::CompletionCallback& callback) OVERRIDE { + return net::OK; + } + + virtual int Write(net::IOBuffer* buffer, + int num_bytes, + const net::CompletionCallback& callback) OVERRIDE { + if (url_request_) { + message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&CefURLFetcherResponseWriter::WriteOnClientThread, + url_request_, scoped_refptr(buffer), + num_bytes, callback, + base::MessageLoop::current()->message_loop_proxy())); + return net::ERR_IO_PENDING; + } + return num_bytes; + } + + virtual int Finish(const net::CompletionCallback& callback) OVERRIDE { + if (url_request_) + url_request_ = NULL; + return net::OK; + } + + private: + static void WriteOnClientThread( + CefRefPtr url_request, + scoped_refptr buffer, + int num_bytes, + const net::CompletionCallback& callback, + scoped_refptr source_message_loop_proxy) { + CefRefPtr client = url_request->GetClient(); + if (client) + client->OnDownloadData(url_request.get(), buffer->data(), num_bytes); + + source_message_loop_proxy->PostTask(FROM_HERE, + base::Bind(&CefURLFetcherResponseWriter::ContinueOnSourceThread, + num_bytes, callback)); + } + + static void ContinueOnSourceThread( + int num_bytes, + const net::CompletionCallback& callback) { + callback.Run(num_bytes); + } + + CefRefPtr url_request_; + scoped_refptr message_loop_proxy_; + + DISALLOW_COPY_AND_ASSIGN(CefURLFetcherResponseWriter); +}; + +base::SupportsUserData::Data* CreateURLRequestUserData( + CefRefPtr client) { + return new CefURLRequestUserData(client); +} + +} // namespace + + +// CefBrowserURLRequest::Context ---------------------------------------------- + +class CefBrowserURLRequest::Context + : public base::RefCountedThreadSafe { + public: + Context(CefRefPtr url_request, + CefRefPtr request, + CefRefPtr client) + : url_request_(url_request), + request_(request), + client_(client), + message_loop_proxy_(base::MessageLoop::current()->message_loop_proxy()), + status_(UR_IO_PENDING), + error_code_(ERR_NONE), + upload_data_size_(0), + got_upload_progress_complete_(false) { + // Mark the request as read-only. + static_cast(request_.get())->SetReadOnly(true); + } + + virtual ~Context() { + if (fetcher_.get()) { + // Delete the fetcher object on the thread that created it. + message_loop_proxy_->DeleteSoon(FROM_HERE, fetcher_.release()); + } + } + + inline bool CalledOnValidThread() { + return message_loop_proxy_->BelongsToCurrentThread(); + } + + bool Start() { + DCHECK(CalledOnValidThread()); + + GURL url = GURL(request_->GetURL().ToString()); + if (!url.is_valid()) + return false; + + std::string method = request_->GetMethod(); + StringToLowerASCII(&method); + net::URLFetcher::RequestType request_type = net::URLFetcher::GET; + if (LowerCaseEqualsASCII(method, "get")) { + } else if (LowerCaseEqualsASCII(method, "post")) { + request_type = net::URLFetcher::POST; + } else if (LowerCaseEqualsASCII(method, "head")) { + request_type = net::URLFetcher::HEAD; + } else if (LowerCaseEqualsASCII(method, "delete")) { + request_type = net::URLFetcher::DELETE_REQUEST; + } else if (LowerCaseEqualsASCII(method, "put")) { + request_type = net::URLFetcher::PUT; + } else { + NOTREACHED() << "invalid request type"; + return false; + } + + fetcher_delegate_.reset( + new CefURLFetcherDelegate(this, request_->GetFlags())); + + fetcher_.reset(net::URLFetcher::Create(url, request_type, + fetcher_delegate_.get())); + fetcher_->SetRequestContext( + CefContentBrowserClient::Get()->request_context()); + + CefRequest::HeaderMap headerMap; + request_->GetHeaderMap(headerMap); + + // Extract the Referer header value. + { + CefString referrerStr; + referrerStr.FromASCII(net::HttpRequestHeaders::kReferer); + CefRequest::HeaderMap::iterator it = headerMap.find(referrerStr); + if (it == headerMap.end()) { + fetcher_->SetReferrer(""); + } else { + fetcher_->SetReferrer(it->second); + headerMap.erase(it); + } + } + + std::string content_type; + + // Extract the Content-Type header value. + { + CefString contentTypeStr; + contentTypeStr.FromASCII(net::HttpRequestHeaders::kContentType); + CefRequest::HeaderMap::iterator it = headerMap.find(contentTypeStr); + if (it != headerMap.end()) { + content_type = it->second; + headerMap.erase(it); + } + } + + int64 upload_data_size = 0; + + CefRefPtr post_data = request_->GetPostData(); + if (post_data.get()) { + CefPostData::ElementVector elements; + post_data->GetElements(elements); + if (elements.size() == 1) { + // Default to URL encoding if not specified. + if (content_type.empty()) + content_type = "application/x-www-form-urlencoded"; + + CefPostDataElementImpl* impl = + static_cast(elements[0].get()); + + switch (elements[0]->GetType()) + case PDE_TYPE_BYTES: { + upload_data_size = impl->GetBytesCount(); + fetcher_->SetUploadData(content_type, + std::string(static_cast(impl->GetBytes()), + upload_data_size)); + break; + case PDE_TYPE_FILE: + fetcher_->SetUploadFilePath( + content_type, + base::FilePath(impl->GetFile()), + 0, kuint64max, + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE).get()); + break; + case PDE_TYPE_EMPTY: + break; + } + } else if (elements.size() > 1) { + NOTIMPLEMENTED() << " multi-part form data is not supported"; + } + } + + std::string first_party_for_cookies = request_->GetFirstPartyForCookies(); + if (!first_party_for_cookies.empty()) + fetcher_->SetFirstPartyForCookies(GURL(first_party_for_cookies)); + + int cef_flags = request_->GetFlags(); + + if (cef_flags & UR_FLAG_NO_RETRY_ON_5XX) + fetcher_->SetAutomaticallyRetryOn5xx(false); + + int load_flags = 0; + + if (cef_flags & UR_FLAG_SKIP_CACHE) + load_flags |= net::LOAD_BYPASS_CACHE; + + if (!(cef_flags & UR_FLAG_ALLOW_CACHED_CREDENTIALS)) { + load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA; + load_flags |= net::LOAD_DO_NOT_SEND_COOKIES; + load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES; + } + + if (cef_flags & UR_FLAG_REPORT_UPLOAD_PROGRESS) { + load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS; + upload_data_size_ = upload_data_size; + } + + if (cef_flags & UR_FLAG_REPORT_LOAD_TIMING) + load_flags |= net::LOAD_ENABLE_LOAD_TIMING; + + if (cef_flags & UR_FLAG_REPORT_RAW_HEADERS) + load_flags |= net::LOAD_REPORT_RAW_HEADERS; + + fetcher_->SetLoadFlags(load_flags); + + fetcher_->SetExtraRequestHeaders( + HttpHeaderUtils::GenerateHeaders(headerMap)); + + fetcher_->SetURLRequestUserData( + CefURLRequestUserData::kUserDataKey, + base::Bind(&CreateURLRequestUserData, client_)); + + scoped_ptr response_writer; + if (cef_flags & UR_FLAG_NO_DOWNLOAD_DATA) { + response_writer.reset(new CefURLFetcherResponseWriter(NULL, NULL)); + } else { + response_writer.reset( + new CefURLFetcherResponseWriter(url_request_, message_loop_proxy_)); + } + fetcher_->SaveResponseWithWriter(response_writer.Pass()); + + fetcher_->Start(); + + return true; + } + + void Cancel() { + DCHECK(CalledOnValidThread()); + + // The request may already be complete. + if (!fetcher_.get()) + return; + + // Cancel the fetch by deleting the fetcher. + fetcher_.reset(NULL); + + status_ = UR_CANCELED; + error_code_ = ERR_ABORTED; + OnComplete(); + } + + void OnComplete() { + DCHECK(CalledOnValidThread()); + + if (fetcher_.get()) { + const net::URLRequestStatus& status = fetcher_->GetStatus(); + + if (status.is_success()) + NotifyUploadProgressIfNecessary(); + + switch (status.status()) { + case net::URLRequestStatus::SUCCESS: + status_ = UR_SUCCESS; + break; + case net::URLRequestStatus::IO_PENDING: + status_ = UR_IO_PENDING; + break; + case net::URLRequestStatus::CANCELED: + status_ = UR_CANCELED; + break; + case net::URLRequestStatus::FAILED: + status_ = UR_FAILED; + break; + } + + error_code_ = static_cast(status.error()); + + if(!response_.get()) + OnResponse(); + } + + DCHECK(url_request_.get()); + client_->OnRequestComplete(url_request_.get()); + + if (fetcher_.get()) + fetcher_.reset(NULL); + + // This may result in the Context object being deleted. + url_request_ = NULL; + } + + void OnDownloadProgress(int64 current, int64 total) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + + if(!response_.get()) + OnResponse(); + + NotifyUploadProgressIfNecessary(); + + client_->OnDownloadProgress(url_request_.get(), current, total); + } + + void OnDownloadData(scoped_ptr download_data) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + + if(!response_.get()) + OnResponse(); + + client_->OnDownloadData(url_request_.get(), download_data->c_str(), + download_data->length()); + } + + void OnUploadProgress(int64 current, int64 total) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + if (current == total) + got_upload_progress_complete_ = true; + client_->OnUploadProgress(url_request_.get(), current, total); + } + + CefRefPtr request() { return request_; } + CefRefPtr client() { return client_; } + CefURLRequest::Status status() { return status_; } + CefURLRequest::ErrorCode error_code() { return error_code_; } + CefRefPtr response() { return response_; } + + private: + void NotifyUploadProgressIfNecessary() { + if (!got_upload_progress_complete_ && upload_data_size_ > 0) { + // URLFetcher sends upload notifications using a timer and will not send + // a notification if the request completes too quickly. We therefore + // send the notification here if necessary. + client_->OnUploadProgress(url_request_.get(), upload_data_size_, + upload_data_size_); + got_upload_progress_complete_ = true; + } + } + + void OnResponse() { + if (fetcher_.get()) { + response_ = new CefResponseImpl(); + CefResponseImpl* responseImpl = + static_cast(response_.get()); + + net::HttpResponseHeaders* headers = fetcher_->GetResponseHeaders(); + if (headers) + responseImpl->SetResponseHeaders(*headers); + + responseImpl->SetReadOnly(true); + } + } + + // Members only accessed on the initialization thread. + CefRefPtr url_request_; + CefRefPtr request_; + CefRefPtr client_; + scoped_refptr message_loop_proxy_; + scoped_ptr fetcher_; + scoped_ptr fetcher_delegate_; + CefURLRequest::Status status_; + CefURLRequest::ErrorCode error_code_; + CefRefPtr response_; + int64 upload_data_size_; + bool got_upload_progress_complete_; +}; + + +// CefURLFetcherDelegate ------------------------------------------------------ + +namespace { + +CefURLFetcherDelegate::CefURLFetcherDelegate( + CefBrowserURLRequest::Context* context, int request_flags) + : context_(context), + request_flags_(request_flags) { +} + +CefURLFetcherDelegate::~CefURLFetcherDelegate() { +} + +void CefURLFetcherDelegate::OnURLFetchComplete( + const net::URLFetcher* source) { + // Complete asynchronously so as not to delete the URLFetcher while it's still + // in the call stack. + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&CefBrowserURLRequest::Context::OnComplete, context_)); +} + +void CefURLFetcherDelegate::OnURLFetchDownloadProgress( + const net::URLFetcher* source, + int64 current, int64 total) { + context_->OnDownloadProgress(current, total); +} + +void CefURLFetcherDelegate::OnURLFetchUploadProgress( + const net::URLFetcher* source, + int64 current, int64 total) { + if (request_flags_ & UR_FLAG_REPORT_UPLOAD_PROGRESS) + context_->OnUploadProgress(current, total); +} + +} // namespace + + +// CefBrowserURLRequest ------------------------------------------------------- + +CefBrowserURLRequest::CefBrowserURLRequest( + CefRefPtr request, + CefRefPtr client) { + context_ = new Context(this, request, client); +} + +CefBrowserURLRequest::~CefBrowserURLRequest() { +} + +bool CefBrowserURLRequest::Start() { + if (!VerifyContext()) + return false; + return context_->Start(); +} + +CefRefPtr CefBrowserURLRequest::GetRequest() { + if (!VerifyContext()) + return NULL; + return context_->request(); +} + +CefRefPtr CefBrowserURLRequest::GetClient() { + if (!VerifyContext()) + return NULL; + return context_->client(); +} + +CefURLRequest::Status CefBrowserURLRequest::GetRequestStatus() { + if (!VerifyContext()) + return UR_UNKNOWN; + return context_->status(); +} + +CefURLRequest::ErrorCode CefBrowserURLRequest::GetRequestError() { + if (!VerifyContext()) + return ERR_NONE; + return context_->error_code(); +} + +CefRefPtr CefBrowserURLRequest::GetResponse() { + if (!VerifyContext()) + return NULL; + return context_->response(); +} + +void CefBrowserURLRequest::Cancel() { + if (!VerifyContext()) + return; + return context_->Cancel(); +} + +bool CefBrowserURLRequest::VerifyContext() { + DCHECK(context_.get()); + if (!context_->CalledOnValidThread()) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + return true; +} diff --git a/libcef/browser/browser_urlrequest_impl.h b/libcef/browser/browser_urlrequest_impl.h new file mode 100644 index 000000000..e1e186940 --- /dev/null +++ b/libcef/browser/browser_urlrequest_impl.h @@ -0,0 +1,37 @@ +// 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_LIBCEF_BROWSER_BROWSER_URLREQUEST_IMPL_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_URLREQUEST_IMPL_H_ + +#include "include/cef_urlrequest.h" +#include "base/memory/ref_counted.h" + +class CefBrowserURLRequest : public CefURLRequest { + public: + class Context; + + CefBrowserURLRequest(CefRefPtr request, + CefRefPtr client); + virtual ~CefBrowserURLRequest(); + + bool Start(); + + // CefURLRequest methods. + virtual CefRefPtr GetRequest() OVERRIDE; + virtual CefRefPtr GetClient() OVERRIDE; + virtual Status GetRequestStatus() OVERRIDE; + virtual ErrorCode GetRequestError() OVERRIDE; + virtual CefRefPtr GetResponse() OVERRIDE; + virtual void Cancel() OVERRIDE; + + private: + bool VerifyContext(); + + scoped_refptr context_; + + IMPLEMENT_REFCOUNTING(CefBrowserURLRequest); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_URLREQUEST_IMPL_H_ diff --git a/libcef/browser/chrome_browser_process_stub.cc b/libcef/browser/chrome_browser_process_stub.cc new file mode 100644 index 000000000..03c506dfc --- /dev/null +++ b/libcef/browser/chrome_browser_process_stub.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. +// Portions (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 "libcef/browser/chrome_browser_process_stub.h" +#include "libcef/browser/context.h" + +#include "base/memory/scoped_ptr.h" +#include "ui/message_center/message_center.h" + +ChromeBrowserProcessStub::ChromeBrowserProcessStub() + : locale_("en-US") { +} + +ChromeBrowserProcessStub::~ChromeBrowserProcessStub() { + g_browser_process = NULL; +} + +void ChromeBrowserProcessStub::ResourceDispatcherHostCreated() { + NOTIMPLEMENTED(); +}; + +void ChromeBrowserProcessStub::EndSession() { + NOTIMPLEMENTED(); +}; + +MetricsServicesManager* ChromeBrowserProcessStub::GetMetricsServicesManager() { + NOTIMPLEMENTED(); + return NULL; +} + +MetricsService* ChromeBrowserProcessStub::metrics_service() { + NOTIMPLEMENTED(); + return NULL; +} + +rappor::RapporService* ChromeBrowserProcessStub::rappor_service() { + NOTIMPLEMENTED(); + return NULL; +} + +IOThread* ChromeBrowserProcessStub::io_thread() { + NOTIMPLEMENTED(); + return NULL; +} + +WatchDogThread* ChromeBrowserProcessStub::watchdog_thread() { + NOTIMPLEMENTED(); + return NULL; +} + +ProfileManager* ChromeBrowserProcessStub::profile_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +PrefService* ChromeBrowserProcessStub::local_state() { + NOTIMPLEMENTED(); + return NULL; +} + +net::URLRequestContextGetter* + ChromeBrowserProcessStub::system_request_context() { + NOTIMPLEMENTED(); + return NULL; +} + +chrome_variations::VariationsService* + ChromeBrowserProcessStub::variations_service() { + NOTIMPLEMENTED(); + return NULL; +} + +BrowserProcessPlatformPart* ChromeBrowserProcessStub::platform_part() { + NOTIMPLEMENTED(); + return NULL; +} + +extensions::EventRouterForwarder* + ChromeBrowserProcessStub::extension_event_router_forwarder() { + NOTIMPLEMENTED(); + return NULL; +} + +NotificationUIManager* ChromeBrowserProcessStub::notification_ui_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +message_center::MessageCenter* ChromeBrowserProcessStub::message_center() { + NOTIMPLEMENTED(); + return NULL; +} + +policy::BrowserPolicyConnector* + ChromeBrowserProcessStub::browser_policy_connector() { + NOTIMPLEMENTED(); + return NULL; +} + +policy::PolicyService* ChromeBrowserProcessStub::policy_service() { + NOTIMPLEMENTED(); + return NULL; +} + +IconManager* ChromeBrowserProcessStub::icon_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +GLStringManager* ChromeBrowserProcessStub::gl_string_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +GpuModeManager* ChromeBrowserProcessStub::gpu_mode_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +void ChromeBrowserProcessStub::CreateDevToolsHttpProtocolHandler( + chrome::HostDesktopType host_desktop_type, + const std::string& ip, + int port) { +} + +unsigned int ChromeBrowserProcessStub::AddRefModule() { + NOTIMPLEMENTED(); + return 0; +} + +unsigned int ChromeBrowserProcessStub::ReleaseModule() { + NOTIMPLEMENTED(); + return 0; +} + +bool ChromeBrowserProcessStub::IsShuttingDown() { + NOTIMPLEMENTED(); + return false; +} + +printing::PrintJobManager* ChromeBrowserProcessStub::print_job_manager() { + return CefContext::Get()->print_job_manager(); +} + +printing::PrintPreviewDialogController* + ChromeBrowserProcessStub::print_preview_dialog_controller() { + NOTIMPLEMENTED(); + return NULL; +} + +printing::BackgroundPrintingManager* + ChromeBrowserProcessStub::background_printing_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +IntranetRedirectDetector* + ChromeBrowserProcessStub::intranet_redirect_detector() { + NOTIMPLEMENTED(); + return NULL; +} + +const std::string &ChromeBrowserProcessStub::GetApplicationLocale() { + DCHECK(!locale_.empty()); + return locale_; +} + +void ChromeBrowserProcessStub::SetApplicationLocale(const std::string& locale) { + locale_ = locale; +} + +DownloadStatusUpdater* ChromeBrowserProcessStub::download_status_updater() { + NOTIMPLEMENTED(); + return NULL; +} + +DownloadRequestLimiter* ChromeBrowserProcessStub::download_request_limiter() { + NOTIMPLEMENTED(); + return NULL; +} + +BackgroundModeManager* ChromeBrowserProcessStub::background_mode_manager() { + NOTIMPLEMENTED(); + return NULL; +} + +void ChromeBrowserProcessStub::set_background_mode_manager_for_test( + scoped_ptr manager) { + NOTIMPLEMENTED(); +} + +StatusTray* ChromeBrowserProcessStub::status_tray() { + NOTIMPLEMENTED(); + return NULL; +} + +SafeBrowsingService* ChromeBrowserProcessStub::safe_browsing_service() { + NOTIMPLEMENTED(); + return NULL; +} + +safe_browsing::ClientSideDetectionService* + ChromeBrowserProcessStub::safe_browsing_detection_service() { + NOTIMPLEMENTED(); + return NULL; +} + +#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) +void ChromeBrowserProcessStub::StartAutoupdateTimer() { +} +#endif + +ChromeNetLog* ChromeBrowserProcessStub::net_log() { + NOTIMPLEMENTED(); + return NULL; +} + +prerender::PrerenderTracker* ChromeBrowserProcessStub::prerender_tracker() { + NOTIMPLEMENTED(); + return NULL; +} + +component_updater::ComponentUpdateService* + ChromeBrowserProcessStub::component_updater() { + NOTIMPLEMENTED(); + return NULL; +} + +CRLSetFetcher* ChromeBrowserProcessStub::crl_set_fetcher() { + NOTIMPLEMENTED(); + return NULL; +} + +component_updater::PnaclComponentInstaller* + ChromeBrowserProcessStub::pnacl_component_installer() { + NOTIMPLEMENTED(); + return NULL; +} + +MediaFileSystemRegistry* + ChromeBrowserProcessStub::media_file_system_registry() { + NOTIMPLEMENTED(); + return NULL; +} + +bool ChromeBrowserProcessStub::created_local_state() const { + NOTIMPLEMENTED(); + return false; +} + +#if defined(ENABLE_WEBRTC) +WebRtcLogUploader* ChromeBrowserProcessStub::webrtc_log_uploader() { + NOTIMPLEMENTED(); + return NULL; +} +#endif + +network_time::NetworkTimeTracker* + ChromeBrowserProcessStub::network_time_tracker() { + NOTIMPLEMENTED(); + return NULL; +} + +gcm::GCMDriver* ChromeBrowserProcessStub::gcm_driver() { + NOTIMPLEMENTED(); + return NULL; +} diff --git a/libcef/browser/chrome_browser_process_stub.h b/libcef/browser/chrome_browser_process_stub.h new file mode 100644 index 000000000..4491c89b0 --- /dev/null +++ b/libcef/browser/chrome_browser_process_stub.h @@ -0,0 +1,104 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. +// Portions (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. + +#ifndef CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_ +#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_ + +#include + +#include "chrome/browser/browser_process.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" + +// This file provides a stub implementation of chrome::BrowserProcess so that +// PrintJobWorker can determine the current locale. + +class BackgroundModeManager { + public: + BackgroundModeManager(); + virtual ~BackgroundModeManager(); + private: + DISALLOW_COPY_AND_ASSIGN(BackgroundModeManager); +}; + +class ChromeBrowserProcessStub : public BrowserProcess { + public: + ChromeBrowserProcessStub(); + virtual ~ChromeBrowserProcessStub(); + + // BrowserProcess implementation. + virtual void ResourceDispatcherHostCreated() OVERRIDE; + virtual void EndSession() OVERRIDE; + virtual MetricsServicesManager* GetMetricsServicesManager() OVERRIDE; + virtual MetricsService* metrics_service() OVERRIDE; + virtual rappor::RapporService* rappor_service() OVERRIDE; + virtual IOThread* io_thread() OVERRIDE; + virtual WatchDogThread* watchdog_thread() OVERRIDE; + virtual ProfileManager* profile_manager() OVERRIDE; + virtual PrefService* local_state() OVERRIDE; + virtual net::URLRequestContextGetter* system_request_context() OVERRIDE; + virtual chrome_variations::VariationsService* variations_service() OVERRIDE; + virtual BrowserProcessPlatformPart* platform_part() OVERRIDE; + virtual extensions::EventRouterForwarder* + extension_event_router_forwarder() OVERRIDE; + virtual NotificationUIManager* notification_ui_manager() OVERRIDE; + virtual message_center::MessageCenter* message_center() OVERRIDE; + virtual policy::BrowserPolicyConnector* browser_policy_connector() OVERRIDE; + virtual policy::PolicyService* policy_service() OVERRIDE; + virtual IconManager* icon_manager() OVERRIDE; + virtual GLStringManager* gl_string_manager() OVERRIDE; + virtual GpuModeManager* gpu_mode_manager() OVERRIDE; + virtual void CreateDevToolsHttpProtocolHandler( + chrome::HostDesktopType host_desktop_type, + const std::string& ip, + int port) OVERRIDE; + virtual unsigned int AddRefModule() OVERRIDE; + virtual unsigned int ReleaseModule() OVERRIDE; + virtual bool IsShuttingDown() OVERRIDE; + virtual printing::PrintJobManager* print_job_manager() OVERRIDE; + virtual printing::PrintPreviewDialogController* + print_preview_dialog_controller() OVERRIDE; + virtual printing::BackgroundPrintingManager* + background_printing_manager() OVERRIDE; + virtual IntranetRedirectDetector* intranet_redirect_detector() OVERRIDE; + virtual const std::string& GetApplicationLocale() OVERRIDE; + virtual void SetApplicationLocale(const std::string& locale) OVERRIDE; + virtual DownloadStatusUpdater* download_status_updater() OVERRIDE; + virtual DownloadRequestLimiter* download_request_limiter() OVERRIDE; + virtual BackgroundModeManager* background_mode_manager() OVERRIDE; + virtual void set_background_mode_manager_for_test( + scoped_ptr manager) OVERRIDE; + virtual StatusTray* status_tray() OVERRIDE; + virtual SafeBrowsingService* safe_browsing_service() OVERRIDE; + virtual safe_browsing::ClientSideDetectionService* + safe_browsing_detection_service() OVERRIDE; + +#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) + virtual void StartAutoupdateTimer() OVERRIDE; +#endif + + virtual ChromeNetLog* net_log() OVERRIDE; + virtual prerender::PrerenderTracker* prerender_tracker() OVERRIDE; + virtual component_updater::ComponentUpdateService* + component_updater() OVERRIDE; + virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE; + virtual component_updater::PnaclComponentInstaller* + pnacl_component_installer() OVERRIDE; + virtual MediaFileSystemRegistry* + media_file_system_registry() OVERRIDE; + virtual bool created_local_state() const OVERRIDE; +#if defined(ENABLE_WEBRTC) + virtual WebRtcLogUploader* webrtc_log_uploader() OVERRIDE; +#endif + virtual network_time::NetworkTimeTracker* network_time_tracker() OVERRIDE; + virtual gcm::GCMDriver* gcm_driver() OVERRIDE; + + private: + std::string locale_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserProcessStub); +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_BROWSER_PROCESS_STUB_H_ diff --git a/libcef/browser/chrome_scheme_handler.cc b/libcef/browser/chrome_scheme_handler.cc new file mode 100644 index 000000000..5057131eb --- /dev/null +++ b/libcef/browser/chrome_scheme_handler.cc @@ -0,0 +1,403 @@ +// Copyright (c) 2012 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 "libcef/browser/chrome_scheme_handler.h" + +#include +#include + +#include "include/cef_version.h" +#include "include/cef_web_plugin.h" +#include "libcef/browser/context.h" +#include "libcef/browser/frame_host_impl.h" +#include "libcef/browser/internal_scheme_handler.h" +#include "libcef/browser/scheme_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/content_client.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "content/browser/net/view_http_cache_job_factory.h" +#include "content/browser/net/view_blob_internals_job_factory.h" +#include "content/public/common/url_constants.h" +#include "content/public/common/user_agent.h" +#include "grit/cef_resources.h" +#include "ipc/ipc_channel.h" +#include "net/url_request/url_request.h" +#include "v8/include/v8.h" + +namespace scheme { + +const char kChromeURL[] = "chrome://"; + +namespace { + +const char kChromeCreditsDomain[] = "credits"; +const char kChromeLicenseDomain[] = "license"; +const char kChromeVersionDomain[] = "version"; + +enum ChromeDomain { + CHROME_UNKNOWN = 0, + CHROME_CREDITS, + CHROME_LICENSE, + CHROME_VERSION, +}; + +ChromeDomain GetChromeDomain(const std::string& domain_name) { + static struct { + const char* name; + ChromeDomain domain; + } domains[] = { + { kChromeCreditsDomain, CHROME_CREDITS }, + { kChromeLicenseDomain, CHROME_LICENSE }, + { kChromeVersionDomain, CHROME_VERSION }, + }; + + for (size_t i = 0; i < sizeof(domains) / sizeof(domains[0]); ++i) { + if (base::strcasecmp(domains[i].name, domain_name.c_str()) == 0) + return domains[i].domain; + } + + return CHROME_UNKNOWN; +} + +std::string GetOSType() { +#if defined(OS_WIN) + return "Windows"; +#elif defined(OS_MACOSX) + return "Mac OS X"; +#elif defined(OS_CHROMEOS) + return "Chromium OS"; +#elif defined(OS_ANDROID) + return "Android"; +#elif defined(OS_LINUX) + return "Linux"; +#elif defined(OS_FREEBSD) + return "FreeBSD"; +#elif defined(OS_OPENBSD) + return "OpenBSD"; +#elif defined(OS_SOLARIS) + return "Solaris"; +#else + return "Unknown"; +#endif +} + +std::string GetCommandLine() { +#if defined(OS_WIN) + return base::WideToUTF8( + CommandLine::ForCurrentProcess()->GetCommandLineString()); +#elif defined(OS_POSIX) + std::string command_line = ""; + typedef std::vector ArgvList; + const ArgvList& argv = CommandLine::ForCurrentProcess()->argv(); + for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++) + command_line += " " + *iter; + // TODO(viettrungluu): |command_line| could really have any encoding, whereas + // below we assumes it's UTF-8. + return command_line; +#endif +} + +std::string GetModulePath() { + base::FilePath path; + if (PathService::Get(base::FILE_MODULE, &path)) + return CefString(path.value()); + return std::string(); +} + +class TemplateParser { + public: + TemplateParser() + : ident_start_("$$"), + ident_end_("$$") { + } + + TemplateParser(const std::string& ident_start, + const std::string& ident_end) + : ident_start_(ident_start), + ident_end_(ident_end) { + } + + void Add(const std::string& key, const std::string& value) { + values_.insert(std::make_pair(key, value)); + } + + void Parse(std::string* tmpl) { + int start_pos, end_pos = 0; + int ident_start_len = ident_start_.length(); + int ident_end_len = ident_end_.length(); + + while(true) { + start_pos = tmpl->find(ident_start_, end_pos); + if (start_pos >= 0) { + end_pos = tmpl->find(ident_end_, start_pos + ident_start_len); + if (end_pos >= 0) { + // Found an identifier. Check if a substitution exists. + std::string key = tmpl->substr(start_pos + ident_start_len, + end_pos - start_pos - ident_start_len); + KeyMap::const_iterator it = values_.find(key); + if (it != values_.end()) { + // Peform the substitution. + tmpl->replace(start_pos, end_pos + ident_end_len - start_pos, + it->second); + end_pos = start_pos + it->second.length(); + } else { + // Leave the unknown identifier in place. + end_pos += ident_end_len; + } + + if (end_pos >= static_cast(tmpl->length()) - ident_start_len - + ident_end_len) { + // Not enough room remaining for more identifiers. + break; + } + } else { + // No end identifier found. + break; + } + } else { + // No start identifier found. + break; + } + } + } + + private: + typedef std::map KeyMap; + KeyMap values_; + std::string ident_start_; + std::string ident_end_; +}; + +class Delegate : public InternalHandlerDelegate { + public: + Delegate() {} + + virtual bool OnRequest(CefRefPtr request, + Action* action) OVERRIDE { + GURL url = GURL(request->GetURL().ToString()); + std::string path = url.path(); + if (path.length() > 0) + path = path.substr(1); + + bool handled = false; + + ChromeDomain domain = GetChromeDomain(url.host()); + switch (domain) { + case CHROME_CREDITS: + handled = OnCredits(path, action); + break; + case CHROME_LICENSE: + handled = OnLicense(action); + break; + case CHROME_VERSION: + handled = OnVersion(action); + break; + default: + break; + } + + if (!handled && domain != CHROME_VERSION) { + LOG(INFO) << "Reguest for unknown chrome resource: " << + url.spec().c_str(); + action->redirect_url = + GURL(std::string(kChromeURL) + kChromeVersionDomain); + } + + return true; + } + + bool OnCredits(const std::string& path, Action* action) { + if (path == "credits.js") { + action->resource_id = IDR_CEF_CREDITS_JS; + } else { + action->mime_type = "text/html"; + action->resource_id = IDR_CEF_CREDITS_HTML; + } + return true; + } + + bool OnLicense(Action* action) { + base::StringPiece piece = CefContentClient::Get()->GetDataResource( + IDR_CEF_LICENSE_TXT, ui::SCALE_FACTOR_NONE); + if (piece.empty()) { + NOTREACHED() << "Failed to load license txt resource."; + return false; + } + + std::string html = "License
" +
+                       piece.as_string() + "
"; + + action->mime_type = "text/html"; + action->stream = CefStreamReader::CreateForData( + const_cast(html.c_str()), html.length()); + action->stream_size = html.length(); + + return true; + } + + bool OnVersion(Action* action) { + base::StringPiece piece = CefContentClient::Get()->GetDataResource( + IDR_CEF_VERSION_HTML, ui::SCALE_FACTOR_NONE); + if (piece.empty()) { + NOTREACHED() << "Failed to load version html resource."; + return false; + } + + TemplateParser parser; + parser.Add("YEAR", MAKE_STRING(COPYRIGHT_YEAR)); + parser.Add("CEF", + base::StringPrintf("%d.%d.%d", + CEF_VERSION_MAJOR, + CHROME_VERSION_BUILD, + CEF_REVISION)); + parser.Add("CHROMIUM", + base::StringPrintf("%d.%d.%d.%d", + CHROME_VERSION_MAJOR, + CHROME_VERSION_MINOR, + CHROME_VERSION_BUILD, + CHROME_VERSION_PATCH)); + parser.Add("OS", GetOSType()); + parser.Add("WEBKIT", + base::StringPrintf("%d.%d", + content::GetWebKitMajorVersion(), + content::GetWebKitMinorVersion())); + parser.Add("JAVASCRIPT", v8::V8::GetVersion()); + parser.Add("FLASH", std::string()); // Value populated asynchronously. + parser.Add("USERAGENT", CefContentClient::Get()->GetUserAgent()); + parser.Add("COMMANDLINE", GetCommandLine()); + parser.Add("MODULEPATH", GetModulePath()); + parser.Add("CACHEPATH", CefString(CefContext::Get()->cache_path().value())); + + std::string tmpl = piece.as_string(); + parser.Parse(&tmpl); + + action->mime_type = "text/html"; + action->stream = CefStreamReader::CreateForData( + const_cast(tmpl.c_str()), tmpl.length()); + action->stream_size = tmpl.length(); + + return true; + } +}; + +void DidFinishChromeVersionLoad(CefRefPtr frame) { + // Retieve Flash version information and update asynchronously. + class Visitor : public CefWebPluginInfoVisitor { + public: + Visitor(CefRefPtr frame) + : frame_(frame) { + } + + virtual bool Visit(CefRefPtr info, + int count, int total) OVERRIDE { + std::string name = info->GetName(); + if (name == "Shockwave Flash") { + if (frame_->IsValid()) { + std::string version = info->GetVersion(); + frame_->ExecuteJavaScript( + "document.getElementById('flash').innerText = '" + version + "';", + std::string(), 0); + } + return false; + } + + return true; + } + + private: + CefRefPtr frame_; + + IMPLEMENT_REFCOUNTING(Visitor); + }; + + CefVisitWebPluginInfo(new Visitor(frame)); +} + +// Wrapper for a ChromeProtocolHandler instance from +// content/browser/webui/url_data_manager_backend.cc. +class ChromeProtocolHandlerWrapper : + public net::URLRequestJobFactory::ProtocolHandler { + public: + explicit ChromeProtocolHandlerWrapper( + scoped_ptr chrome_protocol_handler) + : chrome_protocol_handler_(chrome_protocol_handler.Pass()) { + } + + virtual net::URLRequestJob* MaybeCreateJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const OVERRIDE { + // Keep synchronized with the checks in ChromeProtocolHandler::MaybeCreateJob. + if (content::ViewHttpCacheJobFactory::IsSupportedURL(request->url()) || + (request->url().SchemeIs(content::kChromeUIScheme) && + request->url().host() == content::kChromeUIAppCacheInternalsHost) || + content::ViewBlobInternalsJobFactory::IsSupportedURL(request->url()) || +#if defined(USE_TCMALLOC) + (request->url().SchemeIs(content::kChromeUIScheme) && + request->url().host() == content::kChromeUITcmallocHost) || +#endif + (request->url().SchemeIs(content::kChromeUIScheme) && + request->url().host() == content::kChromeUIHistogramHost)) { + return chrome_protocol_handler_->MaybeCreateJob(request, network_delegate); + } + + // Use the protocol handler registered with CEF. + return scheme::GetRequestJob(request, network_delegate); + } + + private: + scoped_ptr chrome_protocol_handler_; +}; + +} // namespace + +void RegisterChromeHandler() { + CefRegisterSchemeHandlerFactory( + content::kChromeUIScheme, + std::string(), + CreateInternalHandlerFactory( + make_scoped_ptr(new Delegate()))); +} + +bool WillHandleBrowserAboutURL(GURL* url, + content::BrowserContext* browser_context) { + std::string text = url->possibly_invalid_spec(); + if (text.find("about:") == 0 && text != "about:blank" && text.length() > 6) { + // Redirect about: URLs to chrome:// + *url = GURL(kChromeURL + text.substr(6)); + } + + // Allow the redirection to proceed. + return false; +} + +void DidFinishChromeLoad(CefRefPtr frame, + const GURL& validated_url) { + ChromeDomain domain = GetChromeDomain(validated_url.host()); + switch (domain) { + case CHROME_VERSION: + DidFinishChromeVersionLoad(frame); + default: + break; + } +} + +scoped_ptr +WrapChromeProtocolHandler( + scoped_ptr + chrome_protocol_handler) { + scoped_ptr ret( + new ChromeProtocolHandlerWrapper(chrome_protocol_handler.Pass())); + return ret.Pass(); +} + +} // namespace scheme diff --git a/libcef/browser/chrome_scheme_handler.h b/libcef/browser/chrome_scheme_handler.h new file mode 100644 index 000000000..f5b35f40e --- /dev/null +++ b/libcef/browser/chrome_scheme_handler.h @@ -0,0 +1,51 @@ +// 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_LIBCEF_BROWSER_CHROME_SCHEME_HANDLER_H_ +#define CEF_LIBCEF_BROWSER_CHROME_SCHEME_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_process_message.h" + +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_request_job_factory.h" +#include "url/gurl.h" + +namespace base { +class ListValue; +} + +namespace content { +class BrowserContext; +} + +namespace scheme { + +extern const char kChromeURL[]; + +// Register the chrome scheme handler. +void RegisterChromeHandler(); + +// Used to redirect about: URLs to chrome: URLs. +bool WillHandleBrowserAboutURL(GURL* url, + content::BrowserContext* browser_context); + +// Used to fire any asynchronous content updates. +void DidFinishChromeLoad(CefRefPtr frame, + const GURL& validated_url); + +// Create a new ProtocolHandler that will filter the URLs passed to the default +// "chrome" protocol handler and forward the rest to CEF's handler. +scoped_ptr +WrapChromeProtocolHandler( + scoped_ptr + chrome_protocol_handler); + +} // namespace scheme + +#endif // CEF_LIBCEF_BROWSER_CHROME_SCHEME_HANDLER_H_ diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc new file mode 100644 index 000000000..d200cfdf0 --- /dev/null +++ b/libcef/browser/content_browser_client.cc @@ -0,0 +1,1049 @@ +// 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 "libcef/browser/content_browser_client.h" + +#include + +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_context_proxy.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_main.h" +#include "libcef/browser/browser_message_filter.h" +#include "libcef/browser/browser_settings.h" +#include "libcef/browser/chrome_scheme_handler.h" +#include "libcef/browser/context.h" +#include "libcef/browser/media_capture_devices_dispatcher.h" +#include "libcef/browser/printing/printing_message_filter.h" +#include "libcef/browser/resource_dispatcher_host_delegate.h" +#include "libcef/browser/speech_recognition_manager_delegate.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/web_plugin_impl.h" +#include "libcef/common/cef_switches.h" +#include "libcef/common/command_line_impl.h" +#include "libcef/common/content_client.h" +#include "libcef/common/scheme_registration.h" + +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "chrome/common/chrome_switches.h" +#include "content/browser/plugin_service_impl.h" +#include "content/public/browser/access_token_store.h" +#include "content/public/browser/browser_url_handler.h" +#include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/plugin_service_filter.h" +#include "content/public/browser/quota_permission_context.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/resource_dispatcher_host.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/storage_quota_params.h" +#include "third_party/WebKit/public/web/WebWindowFeatures.h" +#include "ui/base/ui_base_switches.h" +#include "url/gurl.h" +#include "webkit/common/webpreferences.h" + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +#include "base/debug/leak_annotations.h" +#include "components/breakpad/app/breakpad_linux.h" +#include "components/breakpad/browser/crash_handler_host_linux.h" +#include "content/public/common/content_descriptors.h" +#endif + +namespace { + +// In-memory store for access tokens used by geolocation. +class CefAccessTokenStore : public content::AccessTokenStore { + public: + CefAccessTokenStore() {} + + virtual void LoadAccessTokens( + const LoadAccessTokensCallbackType& callback) OVERRIDE { + callback.Run(access_token_set_, + CefContentBrowserClient::Get()->request_context()); + } + + virtual void SaveAccessToken( + const GURL& server_url, const base::string16& access_token) OVERRIDE { + access_token_set_[server_url] = access_token; + } + + private: + AccessTokenSet access_token_set_; + + DISALLOW_COPY_AND_ASSIGN(CefAccessTokenStore); +}; + +class CefQuotaCallbackImpl : public CefQuotaCallback { + public: + explicit CefQuotaCallbackImpl( + const content::QuotaPermissionContext::PermissionCallback& callback) + : callback_(callback) { + } + + ~CefQuotaCallbackImpl() { + if (!callback_.is_null()) { + // The callback is still pending. Cancel it now. + if (CEF_CURRENTLY_ON_IOT()) { + CancelNow(callback_); + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefQuotaCallbackImpl::CancelNow, callback_)); + } + } + } + + virtual void Continue(bool allow) OVERRIDE { + if (CEF_CURRENTLY_ON_IOT()) { + if (!callback_.is_null()) { + callback_.Run(allow ? + content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW : + content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_DISALLOW); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefQuotaCallbackImpl::Continue, this, allow)); + } + } + + virtual void Cancel() OVERRIDE { + if (CEF_CURRENTLY_ON_IOT()) { + if (!callback_.is_null()) { + CancelNow(callback_); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_IOT, base::Bind(&CefQuotaCallbackImpl::Cancel, this)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void CancelNow( + const content::QuotaPermissionContext::PermissionCallback& callback) { + CEF_REQUIRE_IOT(); + callback.Run( + content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_CANCELLED); + } + + content::QuotaPermissionContext::PermissionCallback callback_; + + IMPLEMENT_REFCOUNTING(CefQuotaCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefQuotaCallbackImpl); +}; + +class CefAllowCertificateErrorCallbackImpl + : public CefAllowCertificateErrorCallback { + public: + typedef base::Callback // NOLINT(readability/function) + CallbackType; + + explicit CefAllowCertificateErrorCallbackImpl(const CallbackType& callback) + : callback_(callback) { + } + + virtual void Continue(bool allow) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + callback_.Run(allow); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefAllowCertificateErrorCallbackImpl::Continue, + this, allow)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + CallbackType callback_; + + IMPLEMENT_REFCOUNTING(CefAllowCertificateErrorCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefAllowCertificateErrorCallbackImpl); +}; + +class CefGeolocationCallbackImpl : public CefGeolocationCallback { + public: + typedef base::Callback // NOLINT(readability/function) + CallbackType; + + explicit CefGeolocationCallbackImpl(const CallbackType& callback) + : callback_(callback) {} + + virtual void Continue(bool allow) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + callback_.Run(allow); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefGeolocationCallbackImpl::Continue, this, allow)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void Run(const CallbackType& callback, bool allow) { + CEF_REQUIRE_UIT(); + callback.Run(allow); + } + + CallbackType callback_; + + IMPLEMENT_REFCOUNTING(CefGeolocationCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefGeolocationCallbackImpl); +}; + +void CancelGeolocationPermission(base::WeakPtr browser, + const GURL& requesting_frame, + int bridge_id) { + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = + client->GetGeolocationHandler(); + if (handler.get()) { + handler->OnCancelGeolocationPermission(browser.get(), + requesting_frame.spec(), + bridge_id); + } + } + } +} + +class CefQuotaPermissionContext : public content::QuotaPermissionContext { + public: + CefQuotaPermissionContext() { + } + + // The callback will be dispatched on the IO thread. + virtual void RequestQuotaPermission( + const content::StorageQuotaParams& params, + int render_process_id, + const PermissionCallback& callback) OVERRIDE { + if (params.storage_type != quota::kStorageTypePersistent) { + // To match Chrome behavior we only support requesting quota with this + // interface for Persistent storage type. + callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW); + return; + } + + bool handled = false; + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForView(render_process_id, + params.render_view_id); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr callbackImpl( + new CefQuotaCallbackImpl(callback)); + handled = handler->OnQuotaRequest(browser.get(), + params.origin_url.spec(), + params.requested_size, + callbackImpl.get()); + if (!handled) + callbackImpl->Disconnect(); + } + } + } + + if (!handled) { + // Disallow the request by default. + callback.Run(QUOTA_PERMISSION_RESPONSE_DISALLOW); + } + } + + private: + virtual ~CefQuotaPermissionContext() { + } + + DISALLOW_COPY_AND_ASSIGN(CefQuotaPermissionContext); +}; + +class CefPluginServiceFilter : public content::PluginServiceFilter { + public: + CefPluginServiceFilter() {} + virtual ~CefPluginServiceFilter() {} + + virtual bool IsPluginAvailable(int render_process_id, + int render_frame_id, + const void* context, + const GURL& url, + const GURL& policy_url, + content::WebPluginInfo* plugin) OVERRIDE { + bool allowed = true; + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForFrame(render_process_id, + render_frame_id); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr pluginInfo( + new CefWebPluginInfoImpl(*plugin)); + allowed = + !handler->OnBeforePluginLoad(browser.get(), + url.possibly_invalid_spec(), + policy_url.possibly_invalid_spec(), + pluginInfo.get()); + } + } + } + + return allowed; + } + + virtual bool CanLoadPlugin(int render_process_id, + const base::FilePath& path) OVERRIDE { + return true; + } + + DISALLOW_COPY_AND_ASSIGN(CefPluginServiceFilter); +}; + +void TranslatePopupFeatures(const blink::WebWindowFeatures& webKitFeatures, + CefPopupFeatures& features) { + features.x = static_cast(webKitFeatures.x); + features.xSet = webKitFeatures.xSet; + features.y = static_cast(webKitFeatures.y); + features.ySet = webKitFeatures.ySet; + features.width = static_cast(webKitFeatures.width); + features.widthSet = webKitFeatures.widthSet; + features.height = static_cast(webKitFeatures.height); + features.heightSet = webKitFeatures.heightSet; + + features.menuBarVisible = webKitFeatures.menuBarVisible; + features.statusBarVisible = webKitFeatures.statusBarVisible; + features.toolBarVisible = webKitFeatures.toolBarVisible; + features.locationBarVisible = webKitFeatures.locationBarVisible; + features.scrollbarsVisible = webKitFeatures.scrollbarsVisible; + features.resizable = webKitFeatures.resizable; + + features.fullscreen = webKitFeatures.fullscreen; + features.dialog = webKitFeatures.dialog; + features.additionalFeatures = NULL; + if (webKitFeatures.additionalFeatures.size() > 0) + features.additionalFeatures = cef_string_list_alloc(); + + CefString str; + for (unsigned int i = 0; i < webKitFeatures.additionalFeatures.size(); ++i) { + str = base::string16(webKitFeatures.additionalFeatures[i]); + cef_string_list_append(features.additionalFeatures, str.GetStruct()); + } +} + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost( + const std::string& process_type) { + base::FilePath dumps_path = + CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kCrashDumpsDir); + { + ANNOTATE_SCOPED_MEMORY_LEAK; + breakpad::CrashHandlerHostLinux* crash_handler = + new breakpad::CrashHandlerHostLinux( + process_type, dumps_path, false); + crash_handler->StartUploaderThread(); + return crash_handler; + } +} + +int GetCrashSignalFD(const CommandLine& command_line) { + if (!breakpad::IsCrashReporterEnabled()) + return -1; + + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + + if (process_type == switches::kRendererProcess) { + static breakpad::CrashHandlerHostLinux* crash_handler = NULL; + if (!crash_handler) + crash_handler = CreateCrashHandlerHost(process_type); + return crash_handler->GetDeathSignalSocket(); + } + + if (process_type == switches::kPluginProcess) { + static breakpad::CrashHandlerHostLinux* crash_handler = NULL; + if (!crash_handler) + crash_handler = CreateCrashHandlerHost(process_type); + return crash_handler->GetDeathSignalSocket(); + } + + if (process_type == switches::kPpapiPluginProcess) { + static breakpad::CrashHandlerHostLinux* crash_handler = NULL; + if (!crash_handler) + crash_handler = CreateCrashHandlerHost(process_type); + return crash_handler->GetDeathSignalSocket(); + } + + if (process_type == switches::kGpuProcess) { + static breakpad::CrashHandlerHostLinux* crash_handler = NULL; + if (!crash_handler) + crash_handler = CreateCrashHandlerHost(process_type); + return crash_handler->GetDeathSignalSocket(); + } + + return -1; +} +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) + +} // namespace + + +CefContentBrowserClient::CefContentBrowserClient() + : browser_main_parts_(NULL), + next_browser_id_(0) { + plugin_service_filter_.reset(new CefPluginServiceFilter); + content::PluginServiceImpl::GetInstance()->SetFilter( + plugin_service_filter_.get()); + + last_create_window_params_.opener_process_id = MSG_ROUTING_NONE; +} + +CefContentBrowserClient::~CefContentBrowserClient() { +} + +// static +CefContentBrowserClient* CefContentBrowserClient::Get() { + return static_cast( + CefContentClient::Get()->browser()); +} + +scoped_refptr CefContentBrowserClient::CreateBrowserInfo( + bool is_popup) { + base::AutoLock lock_scope(browser_info_lock_); + + scoped_refptr browser_info = + new CefBrowserInfo(++next_browser_id_, is_popup); + browser_info_list_.push_back(browser_info); + return browser_info; +} + +scoped_refptr + CefContentBrowserClient::GetOrCreateBrowserInfo( + int render_view_process_id, + int render_view_routing_id, + int render_frame_process_id, + int render_frame_routing_id) { + base::AutoLock lock_scope(browser_info_lock_); + + BrowserInfoList::const_iterator it = browser_info_list_.begin(); + for (; it != browser_info_list_.end(); ++it) { + const scoped_refptr& browser_info = *it; + if (browser_info->is_render_view_id_match(render_view_process_id, + render_view_routing_id)) { + // Make sure the frame id is also registered. + browser_info->add_render_frame_id(render_frame_process_id, + render_frame_routing_id); + return browser_info; + } else if (browser_info->is_render_frame_id_match( + render_frame_process_id, + render_frame_routing_id)) { + // Make sure the view id is also registered. + browser_info->add_render_view_id(render_view_process_id, + render_view_routing_id); + return browser_info; + } + } + + // Must be a popup if it hasn't already been created. + scoped_refptr browser_info = + new CefBrowserInfo(++next_browser_id_, true); + browser_info->add_render_view_id(render_view_process_id, + render_view_routing_id); + browser_info->add_render_frame_id(render_frame_process_id, + render_frame_routing_id); + browser_info_list_.push_back(browser_info); + return browser_info; +} + +void CefContentBrowserClient::RemoveBrowserInfo( + scoped_refptr browser_info) { + base::AutoLock lock_scope(browser_info_lock_); + + BrowserInfoList::iterator it = browser_info_list_.begin(); + for (; it != browser_info_list_.end(); ++it) { + if (*it == browser_info) { + browser_info_list_.erase(it); + return; + } + } + + NOTREACHED(); +} + +void CefContentBrowserClient::DestroyAllBrowsers() { + BrowserInfoList list; + + { + base::AutoLock lock_scope(browser_info_lock_); + list = browser_info_list_; + } + + // Destroy any remaining browser windows. + if (!list.empty()) { + BrowserInfoList::iterator it = list.begin(); + for (; it != list.end(); ++it) { + CefRefPtr browser = (*it)->browser(); + if (browser.get()) { + // DestroyBrowser will call RemoveBrowserInfo. + browser->DestroyBrowser(); + } else { + // Canceled popup windows may have browser info but no browser because + // CefBrowserMessageFilter::OnGetNewBrowserInfo is still called. + DCHECK((*it)->is_popup()); + RemoveBrowserInfo(*it); + } + } + } + +#ifndef NDEBUG + { + // Verify that all browser windows have been destroyed. + base::AutoLock lock_scope(browser_info_lock_); + DCHECK(browser_info_list_.empty()); + } +#endif +} + +scoped_refptr CefContentBrowserClient::GetBrowserInfoForView( + int render_process_id, int render_routing_id) { + base::AutoLock lock_scope(browser_info_lock_); + + BrowserInfoList::const_iterator it = browser_info_list_.begin(); + for (; it != browser_info_list_.end(); ++it) { + const scoped_refptr& browser_info = *it; + if (browser_info->is_render_view_id_match( + render_process_id, render_routing_id)) { + return browser_info; + } + } + + LOG(WARNING) << "No browser info matching view process id " << + render_process_id << " and routing id " << render_routing_id; + + return scoped_refptr(); +} + +scoped_refptr CefContentBrowserClient::GetBrowserInfoForFrame( + int render_process_id, int render_routing_id) { + base::AutoLock lock_scope(browser_info_lock_); + + BrowserInfoList::const_iterator it = browser_info_list_.begin(); + for (; it != browser_info_list_.end(); ++it) { + const scoped_refptr& browser_info = *it; + if (browser_info->is_render_frame_id_match( + render_process_id, render_routing_id)) { + return browser_info; + } + } + + LOG(WARNING) << "No browser info matching frame process id " << + render_process_id << " and routing id " << render_routing_id; + + return scoped_refptr(); +} + +CefBrowserContext* CefContentBrowserClient::CreateBrowserContextProxy( + CefRefPtr handler) { + CEF_REQUIRE_UIT(); + CefBrowserContextProxy* context = + new CefBrowserContextProxy(handler, browser_context()); + browser_main_parts_->AddBrowserContext(context); + context->AddRef(); + return context; +} + +void CefContentBrowserClient::AddBrowserContextReference( + CefBrowserContext* context) { + CEF_REQUIRE_UIT(); + // Skip the global browser context. + if (context == browser_context()) + return; + + CefBrowserContextProxy* proxy = static_cast(context); + proxy->AddRef(); +} + +void CefContentBrowserClient::RemoveBrowserContextReference( + CefBrowserContext* context) { + CEF_REQUIRE_UIT(); + // Skip the global browser context. + if (context == browser_context()) + return; + + CefBrowserContextProxy* proxy = static_cast(context); + if (proxy->Release()) + browser_main_parts_->RemoveBrowserContext(proxy); +} + +content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts( + const content::MainFunctionParams& parameters) { + browser_main_parts_ = new CefBrowserMainParts(parameters); + return browser_main_parts_; +} + +void CefContentBrowserClient::RenderProcessWillLaunch( + content::RenderProcessHost* host) { + host->GetChannel()->AddFilter(new CefBrowserMessageFilter(host)); + host->AddFilter(new PrintingMessageFilter(host->GetID())); + + AddBrowserContextReference( + static_cast(host->GetBrowserContext())); +} + +net::URLRequestContextGetter* CefContentBrowserClient::CreateRequestContext( + content::BrowserContext* content_browser_context, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + CefBrowserContext* cef_browser_context = + static_cast(content_browser_context); + return cef_browser_context->CreateRequestContext( + protocol_handlers, + request_interceptors.Pass()); +} + +net::URLRequestContextGetter* +CefContentBrowserClient::CreateRequestContextForStoragePartition( + content::BrowserContext* content_browser_context, + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + CefBrowserContext* cef_browser_context = + static_cast(content_browser_context); + return cef_browser_context->CreateRequestContextForStoragePartition( + partition_path, + in_memory, + protocol_handlers, + request_interceptors.Pass()); +} + +bool CefContentBrowserClient::IsHandledURL(const GURL& url) { + if (!url.is_valid()) + return false; + const std::string& scheme = url.scheme(); + DCHECK_EQ(scheme, StringToLowerASCII(scheme)); + + if (scheme::IsInternalHandledScheme(scheme)) + return true; + + return CefContentClient::Get()->HasCustomScheme(scheme); +} + +void CefContentBrowserClient::AppendExtraCommandLineSwitches( + CommandLine* command_line, int child_process_id) { + const CommandLine& browser_cmd = *CommandLine::ForCurrentProcess(); + + { + // Propagate the following switches to all command lines (along with any + // associated values) if present in the browser command line. + static const char* const kSwitchNames[] = { +#if !defined(OS_WIN) + switches::kCrashDumpsDir, +#endif + switches::kDisablePackLoading, + switches::kEnableCrashReporter, + switches::kLang, + switches::kLocalesDirPath, + switches::kLogFile, + switches::kLogSeverity, + switches::kResourcesDirPath, + switches::kProductVersion, + }; + command_line->CopySwitchesFrom(browser_cmd, kSwitchNames, + arraysize(kSwitchNames)); + } + + const std::string& process_type = + command_line->GetSwitchValueASCII(switches::kProcessType); + if (process_type == switches::kRendererProcess) { + // Propagate the following switches to the renderer command line (along with + // any associated values) if present in the browser command line. + static const char* const kSwitchNames[] = { + switches::kContextSafetyImplementation, + switches::kEnableMediaStream, + switches::kEnableSpeechInput, + switches::kUncaughtExceptionStackSize, + }; + command_line->CopySwitchesFrom(browser_cmd, kSwitchNames, + arraysize(kSwitchNames)); + } + +#if defined(OS_LINUX) + if (process_type == switches::kZygoteProcess && + browser_cmd.HasSwitch(switches::kBrowserSubprocessPath)) { + // Force use of the sub-process executable path for the zygote process. + const base::FilePath& subprocess_path = + browser_cmd.GetSwitchValuePath(switches::kBrowserSubprocessPath); + if (!subprocess_path.empty()) + command_line->SetProgram(subprocess_path); + } +#endif // defined(OS_LINUX) + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetBrowserProcessHandler(); + if (handler.get()) { + CefRefPtr commandLinePtr( + new CefCommandLineImpl(command_line, false, false)); + handler->OnBeforeChildProcessLaunch(commandLinePtr.get()); + commandLinePtr->Detach(NULL); + } + } +} + +content::QuotaPermissionContext* + CefContentBrowserClient::CreateQuotaPermissionContext() { + return new CefQuotaPermissionContext(); +} + +content::MediaObserver* CefContentBrowserClient::GetMediaObserver() { + return CefMediaCaptureDevicesDispatcher::GetInstance(); +} + +content::SpeechRecognitionManagerDelegate* + CefContentBrowserClient::GetSpeechRecognitionManagerDelegate() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kEnableSpeechInput)) + return new CefSpeechRecognitionManagerDelegate(); + + return NULL; +} + +void CefContentBrowserClient::AllowCertificateError( + int render_process_id, + int render_frame_id, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + ResourceType::Type resource_type, + bool overridable, + bool strict_enforcement, + const base::Callback& callback, + content::CertificateRequestResultType* result) { + CEF_REQUIRE_UIT(); + + if (resource_type != ResourceType::MAIN_FRAME) { + // A sub-resource has a certificate error. The user doesn't really + // have a context for making the right decision, so block the request + // hard. + *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; + return; + } + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForFrame(render_process_id, + render_frame_id); + if (!browser.get()) + return; + CefRefPtr client = browser->GetClient(); + if (!client.get()) + return; + CefRefPtr handler = client->GetRequestHandler(); + if (!handler.get()) + return; + + CefRefPtr callbackImpl; + if (overridable && !strict_enforcement) + callbackImpl = new CefAllowCertificateErrorCallbackImpl(callback); + + bool proceed = handler->OnCertificateError( + static_cast(cert_error), request_url.spec(), + callbackImpl.get()); + if (!proceed && callbackImpl.get()) + callbackImpl->Disconnect(); + + *result = proceed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE : + content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; +} + +content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() { + return new CefAccessTokenStore; +} + +void CefContentBrowserClient::RequestGeolocationPermission( + content::WebContents* web_contents, + int bridge_id, + const GURL& requesting_frame, + bool user_gesture, + base::Callback result_callback, + base::Closure* cancel_callback) { + CEF_REQUIRE_UIT(); + bool proceed = false; + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForContents(web_contents); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = + client->GetGeolocationHandler(); + if (handler.get()) { + CefRefPtr callbackImpl( + new CefGeolocationCallbackImpl(result_callback)); + + // Notify the handler. + proceed = handler->OnRequestGeolocationPermission( + browser.get(), requesting_frame.spec(), bridge_id, + callbackImpl.get()); + if (proceed) { + // The callback reference may outlive the browser so use a WeakPtr. + *cancel_callback = + base::Bind(CancelGeolocationPermission, + browser->GetWeakPtr(), requesting_frame, + bridge_id); + } else { + callbackImpl->Disconnect(); + } + } + } + } + + if (!proceed) { + // Disallow geolocation access by default. + result_callback.Run(false); + } +} + +bool CefContentBrowserClient::CanCreateWindow( + const GURL& opener_url, + const GURL& opener_top_level_frame_url, + const GURL& source_origin, + WindowContainerType container_type, + const GURL& target_url, + const content::Referrer& referrer, + WindowOpenDisposition disposition, + const blink::WebWindowFeatures& features, + bool user_gesture, + bool opener_suppressed, + content::ResourceContext* context, + int render_process_id, + int opener_id, + bool* no_javascript_access) { + CEF_REQUIRE_IOT(); + *no_javascript_access = false; + + DCHECK_NE(last_create_window_params_.opener_process_id, MSG_ROUTING_NONE); + if (last_create_window_params_.opener_process_id == MSG_ROUTING_NONE) + return false; + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForView( + last_create_window_params_.opener_process_id, + last_create_window_params_.opener_view_id); + DCHECK(browser.get()); + if (!browser.get()) { + LOG(WARNING) << "CanCreateWindow called before browser was created"; + return false; + } + + CefRefPtr client = browser->GetClient(); + bool allow = true; + + scoped_ptr pending_info; + pending_info.reset(new CefBrowserHostImpl::PendingPopupInfo); + +#if defined(OS_WIN) + pending_info->window_info.SetAsPopup(NULL, CefString()); +#endif + + // Start with the current browser's settings. + pending_info->client = client; + pending_info->settings = browser->settings(); + + if (client.get()) { + CefRefPtr handler = client->GetLifeSpanHandler(); + if (handler.get()) { + CefRefPtr frame = + browser->GetFrame(last_create_window_params_.opener_frame_id); + + CefPopupFeatures cef_features; + TranslatePopupFeatures(features, cef_features); + +#if (defined(OS_WIN) || defined(OS_MACOSX)) + // Default to the size from the popup features. + if (cef_features.xSet) + pending_info->window_info.x = cef_features.x; + if (cef_features.ySet) + pending_info->window_info.y = cef_features.y; + if (cef_features.widthSet) + pending_info->window_info.width = cef_features.width; + if (cef_features.heightSet) + pending_info->window_info.height = cef_features.height; +#endif + + allow = !handler->OnBeforePopup(browser.get(), + frame, + last_create_window_params_.target_url.spec(), + last_create_window_params_.target_frame_name, + cef_features, + pending_info->window_info, + pending_info->client, + pending_info->settings, + no_javascript_access); + } + } + + if (allow) { + CefRefPtr pending_client = pending_info->client; + allow = browser->SetPendingPopupInfo(pending_info.Pass()); + if (!allow) { + LOG(WARNING) << "Creation of popup window denied because one is already " + "pending."; + } + } + + last_create_window_params_.opener_process_id = MSG_ROUTING_NONE; + + return allow; +} + +void CefContentBrowserClient::ResourceDispatcherHostCreated() { + resource_dispatcher_host_delegate_.reset( + new CefResourceDispatcherHostDelegate()); + content::ResourceDispatcherHost::Get()->SetDelegate( + resource_dispatcher_host_delegate_.get()); +} + +void CefContentBrowserClient::OverrideWebkitPrefs( + content::RenderViewHost* rvh, + const GURL& url, + WebPreferences* prefs) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForHost(rvh); + DCHECK(browser.get()); + + // Populate WebPreferences based on CefBrowserSettings. + BrowserToWebSettings(browser->settings(), *prefs); + + prefs->base_background_color = GetBaseBackgroundColor(rvh); +} + +SkColor CefContentBrowserClient::GetBaseBackgroundColor( + content::RenderViewHost* rvh) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForHost(rvh); + DCHECK(browser.get()); + + const CefBrowserSettings& browser_settings = browser->settings(); + if (CefColorGetA(browser_settings.background_color) > 0) { + return SkColorSetRGB( + CefColorGetR(browser_settings.background_color), + CefColorGetG(browser_settings.background_color), + CefColorGetB(browser_settings.background_color)); + } else { + const CefSettings& settings = CefContext::Get()->settings(); + if (CefColorGetA(settings.background_color) > 0) { + return SkColorSetRGB( + CefColorGetR(settings.background_color), + CefColorGetG(settings.background_color), + CefColorGetB(settings.background_color)); + } + } + + return SK_ColorWHITE; +} + +void CefContentBrowserClient::BrowserURLHandlerCreated( + content::BrowserURLHandler* handler) { + // Used to redirect about: URLs to chrome: URLs. + handler->AddHandlerPair(&scheme::WillHandleBrowserAboutURL, + content::BrowserURLHandler::null_handler()); +} + +std::string CefContentBrowserClient::GetDefaultDownloadName() { + return "download"; +} + + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +void CefContentBrowserClient::GetAdditionalMappedFilesForChildProcess( + const base::CommandLine& command_line, + int child_process_id, + std::vector* mappings) { + int crash_signal_fd = GetCrashSignalFD(command_line); + if (crash_signal_fd >= 0) { + mappings->push_back(content::FileDescriptorInfo( + kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false))); + } +} +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) + + +#if defined(OS_WIN) +const wchar_t* CefContentBrowserClient::GetResourceDllName() { + static wchar_t file_path[MAX_PATH+1] = {0}; + + if (file_path[0] == 0) { + // Retrieve the module path (usually libcef.dll). + base::FilePath module; + PathService::Get(base::FILE_MODULE, &module); + const std::wstring wstr = module.value(); + size_t count = std::min(static_cast(MAX_PATH), wstr.size()); + wcsncpy(file_path, wstr.c_str(), count); + file_path[count] = 0; + } + + return file_path; +} +#endif // defined(OS_WIN) + +void CefContentBrowserClient::RegisterCustomScheme(const std::string& scheme) { + // Register as a Web-safe scheme so that requests for the scheme from a + // render process will be allowed in resource_dispatcher_host_impl.cc + // ShouldServiceRequest. + content::ChildProcessSecurityPolicy* policy = + content::ChildProcessSecurityPolicy::GetInstance(); + if (!policy->IsWebSafeScheme(scheme)) + policy->RegisterWebSafeScheme(scheme); +} + +void CefContentBrowserClient::set_last_create_window_params( + const LastCreateWindowParams& params) { + CEF_REQUIRE_IOT(); + last_create_window_params_ = params; +} + +CefBrowserContext* CefContentBrowserClient::browser_context() const { + return browser_main_parts_->browser_context(); +} + +scoped_refptr +CefContentBrowserClient::request_context() const { + return browser_main_parts_->request_context(); +} + +CefDevToolsDelegate* CefContentBrowserClient::devtools_delegate() const { + return browser_main_parts_->devtools_delegate(); +} + +PrefService* CefContentBrowserClient::pref_service() const { + return browser_main_parts_->pref_service(); +} + +scoped_ptr +CefContentBrowserClient::proxy_config_service() const { + return browser_main_parts_->proxy_config_service(); +} diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h new file mode 100644 index 000000000..cb92d94ec --- /dev/null +++ b/libcef/browser/content_browser_client.h @@ -0,0 +1,199 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_ +#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_ +#pragma once + +#include +#include +#include +#include +#include + +#include "include/cef_request_context_handler.h" + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "content/public/browser/content_browser_client.h" +#include "net/proxy/proxy_config_service.h" +#include "net/url_request/url_request_context_getter.h" +#include "url/gurl.h" + +class CefBrowserContext; +class CefBrowserInfo; +class CefBrowserMainParts; +class CefDevToolsDelegate; +class CefResourceDispatcherHostDelegate; +class PrefService; + +namespace content { +class PluginServiceFilter; +class SiteInstance; +} + +class CefContentBrowserClient : public content::ContentBrowserClient { + public: + CefContentBrowserClient(); + virtual ~CefContentBrowserClient(); + + // Returns the singleton CefContentBrowserClient instance. + static CefContentBrowserClient* Get(); + + // Methods for managing CefBrowserInfo life span. Do not add new callers of + // these methods. + // During popup window creation there is a race between the call to + // CefBrowserMessageFilter::OnGetNewBrowserInfo on the IO thread and the call + // to CefBrowserHostImpl::ShouldCreateWebContents on the UI thread. To resolve + // this race CefBrowserInfo may be created when requested for the first time + // and before the associated CefBrowserHostImpl is created. + scoped_refptr CreateBrowserInfo(bool is_popup); + scoped_refptr GetOrCreateBrowserInfo( + int render_view_process_id, + int render_view_routing_id, + int render_frame_process_id, + int render_frame_routing_id); + void RemoveBrowserInfo(scoped_refptr browser_info); + void DestroyAllBrowsers(); + + // Retrieves the CefBrowserInfo matching the specified IDs or an empty + // pointer if no match is found. It is allowed to add new callers of this + // method but consider using CefBrowserHostImpl::GetBrowserFor[View|Frame]() + // instead. + scoped_refptr GetBrowserInfoForView(int render_process_id, + int render_routing_id); + scoped_refptr GetBrowserInfoForFrame(int render_process_id, + int render_routing_id); + + // Create and return a new CefBrowserContextProxy object. + CefBrowserContext* CreateBrowserContextProxy( + CefRefPtr handler); + + // BrowserContexts are nominally owned by RenderViewHosts and + // CefRequestContextImpls. Keep track of how many objects reference a given + // context and delete the context when the reference count reaches zero. + void AddBrowserContextReference(CefBrowserContext* context); + void RemoveBrowserContextReference(CefBrowserContext* context); + + // ContentBrowserClient implementation. + virtual content::BrowserMainParts* CreateBrowserMainParts( + const content::MainFunctionParams& parameters) OVERRIDE; + virtual void RenderProcessWillLaunch( + content::RenderProcessHost* host) OVERRIDE; + virtual net::URLRequestContextGetter* CreateRequestContext( + content::BrowserContext* browser_context, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition( + content::BrowserContext* browser_context, + const base::FilePath& partition_path, + bool in_memory, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + OVERRIDE; + virtual bool IsHandledURL(const GURL& url) OVERRIDE; + virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, + int child_process_id) OVERRIDE; + virtual content::QuotaPermissionContext* + CreateQuotaPermissionContext() OVERRIDE; + virtual content::MediaObserver* GetMediaObserver() OVERRIDE; + virtual content::SpeechRecognitionManagerDelegate* + GetSpeechRecognitionManagerDelegate() OVERRIDE; + virtual void AllowCertificateError( + int render_process_id, + int render_frame_id, + int cert_error, + const net::SSLInfo& ssl_info, + const GURL& request_url, + ResourceType::Type resource_type, + bool overridable, + bool strict_enforcement, + const base::Callback& callback, + content::CertificateRequestResultType* result) OVERRIDE; + virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE; + virtual void RequestGeolocationPermission( + content::WebContents* web_contents, + int bridge_id, + const GURL& requesting_frame, + bool user_gesture, + base::Callback result_callback, + base::Closure* cancel_callback) OVERRIDE; + virtual bool CanCreateWindow(const GURL& opener_url, + const GURL& opener_top_level_frame_url, + const GURL& source_origin, + WindowContainerType container_type, + const GURL& target_url, + const content::Referrer& referrer, + WindowOpenDisposition disposition, + const blink::WebWindowFeatures& features, + bool user_gesture, + bool opener_suppressed, + content::ResourceContext* context, + int render_process_id, + int opener_id, + bool* no_javascript_access) OVERRIDE; + virtual void ResourceDispatcherHostCreated() OVERRIDE; + virtual void OverrideWebkitPrefs(content::RenderViewHost* rvh, + const GURL& url, + WebPreferences* prefs) OVERRIDE; + virtual SkColor GetBaseBackgroundColor(content::RenderViewHost* rvh) OVERRIDE; + virtual void BrowserURLHandlerCreated( + content::BrowserURLHandler* handler) OVERRIDE; + virtual std::string GetDefaultDownloadName() OVERRIDE; + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + virtual void GetAdditionalMappedFilesForChildProcess( + const base::CommandLine& command_line, + int child_process_id, + std::vector* mappings) OVERRIDE; +#endif + +#if defined(OS_WIN) + const wchar_t* GetResourceDllName() OVERRIDE; +#endif + + // Perform browser process registration for the custom scheme. + void RegisterCustomScheme(const std::string& scheme); + + // Store additional state from the ViewHostMsg_CreateWindow message that will + // be used when CanCreateWindow() is called. + struct LastCreateWindowParams { + int opener_process_id; + int opener_view_id; + int64 opener_frame_id; + GURL target_url; + base::string16 target_frame_name; + }; + void set_last_create_window_params(const LastCreateWindowParams& params); + + CefBrowserContext* browser_context() const; + scoped_refptr request_context() const; + CefDevToolsDelegate* devtools_delegate() const; + PrefService* pref_service() const; + + // Passes ownership. + scoped_ptr proxy_config_service() const; + + private: + CefBrowserMainParts* browser_main_parts_; + + scoped_ptr plugin_service_filter_; + scoped_ptr + resource_dispatcher_host_delegate_; + + base::Lock browser_info_lock_; + + // Access must be protected by |browser_info_lock_|. + typedef std::list > BrowserInfoList; + BrowserInfoList browser_info_list_; + int next_browser_id_; + + // Only accessed on the IO thread. + LastCreateWindowParams last_create_window_params_; +}; + +#endif // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_ diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc new file mode 100644 index 000000000..3754971ba --- /dev/null +++ b/libcef/browser/context.cc @@ -0,0 +1,423 @@ +// 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 "libcef/browser/context.h" +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/browser_main.h" +#include "libcef/browser/browser_message_loop.h" +#include "libcef/browser/chrome_browser_process_stub.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/scheme_handler.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/trace_subscriber.h" +#include "libcef/common/main_delegate.h" +#include "libcef/renderer/content_renderer_client.h" + +#include "base/base_switches.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/debug/debugger.h" +#include "base/file_util.h" +#include "base/synchronization/waitable_event.h" +#include "chrome/browser/printing/print_job_manager.h" +#include "content/public/app/content_main.h" +#include "content/public/app/content_main_runner.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/content_switches.h" +#include "ui/base/ui_base_switches.h" + +#if defined(OS_WIN) +#include "content/public/app/startup_helper_win.h" +#include "sandbox/win/src/sandbox_types.h" +#endif + +namespace { + +CefContext* g_context = NULL; + +// Force shutdown when the process terminates if a context currently exists and +// CefShutdown() has not been explicitly called. +class CefForceShutdown { + public: + ~CefForceShutdown() { + if (g_context) { + g_context->Shutdown(); + delete g_context; + g_context = NULL; + } + } +} g_force_shutdown; + +} // namespace + +int CefExecuteProcess(const CefMainArgs& args, + CefRefPtr application, + void* windows_sandbox_info) { + CommandLine command_line(CommandLine::NO_PROGRAM); +#if defined(OS_WIN) + command_line.ParseFromString(::GetCommandLineW()); +#else + command_line.InitFromArgv(args.argc, args.argv); +#endif + + // Wait for the debugger as early in process initialization as possible. + if (command_line.HasSwitch(switches::kWaitForDebugger)) + base::debug::WaitForDebugger(60, true); + + // If no process type is specified then it represents the browser process and + // we do nothing. + std::string process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + if (process_type.empty()) + return -1; + + CefMainDelegate main_delegate(application); + + // Execute the secondary process. +#if defined(OS_WIN) + sandbox::SandboxInterfaceInfo sandbox_info = {0}; + if (windows_sandbox_info == NULL) { + content::InitializeSandboxInfo(&sandbox_info); + windows_sandbox_info = &sandbox_info; + } + + content::ContentMainParams params(&main_delegate); + params.instance = args.instance; + params.sandbox_info = + static_cast(windows_sandbox_info); + + return content::ContentMain(params); +#else + content::ContentMainParams params(&main_delegate); + params.argc = args.argc; + params.argv = const_cast(args.argv); + + return content::ContentMain(params); +#endif +} + +bool CefInitialize(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application, + void* windows_sandbox_info) { + // Return true if the global context already exists. + if (g_context) + return true; + + if (settings.size != sizeof(cef_settings_t)) { + NOTREACHED() << "invalid CefSettings structure size"; + return false; + } + + g_browser_process = new ChromeBrowserProcessStub(); + + // Create the new global context object. + g_context = new CefContext(); + + // Initialize the global context. + return g_context->Initialize(args, settings, application, + windows_sandbox_info); +} + +void CefShutdown() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + // Must always be called on the same thread as Initialize. + if (!g_context->OnInitThread()) { + NOTREACHED() << "called on invalid thread"; + return; + } + + // Shut down the global context. This will block until shutdown is complete. + g_context->Shutdown(); + + // Delete the global context object. + delete g_context; + g_context = NULL; +} + +void CefDoMessageLoopWork() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + // Must always be called on the same thread as Initialize. + if (!g_context->OnInitThread()) { + NOTREACHED() << "called on invalid thread"; + return; + } + + CefBrowserMessageLoop::current()->DoMessageLoopIteration(); +} + +void CefRunMessageLoop() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + // Must always be called on the same thread as Initialize. + if (!g_context->OnInitThread()) { + NOTREACHED() << "called on invalid thread"; + return; + } + + CefBrowserMessageLoop::current()->RunMessageLoop(); +} + +void CefQuitMessageLoop() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + // Must always be called on the same thread as Initialize. + if (!g_context->OnInitThread()) { + NOTREACHED() << "called on invalid thread"; + return; + } + + CefBrowserMessageLoop::current()->Quit(); +} + +void CefSetOSModalLoop(bool osModalLoop) { +#if defined(OS_WIN) + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (CEF_CURRENTLY_ON_UIT()) + base::MessageLoop::current()->set_os_modal_loop(osModalLoop); + else + CEF_POST_TASK(CEF_UIT, base::Bind(CefSetOSModalLoop, osModalLoop)); +#endif // defined(OS_WIN) +} + + +// CefContext + +CefContext::CefContext() + : initialized_(false), + shutting_down_(false), + init_thread_id_(0) { +} + +CefContext::~CefContext() { +} + +// static +CefContext* CefContext::Get() { + return g_context; +} + +bool CefContext::Initialize(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application, + void* windows_sandbox_info) { + init_thread_id_ = base::PlatformThread::CurrentId(); + settings_ = settings; + + cache_path_ = base::FilePath(CefString(&settings.cache_path)); + if (!cache_path_.empty() && + !base::DirectoryExists(cache_path_) && + !base::CreateDirectory(cache_path_)) { + NOTREACHED() << "The cache_path directory could not be created"; + cache_path_ = base::FilePath(); + } + if (cache_path_.empty()) { + // Create and use a temporary directory. + if (cache_temp_dir_.CreateUniqueTempDir()) { + cache_path_ = cache_temp_dir_.path(); + } else { + NOTREACHED() << "Failed to create temporary cache_path directory"; + } + } + +#if !defined(OS_WIN) + if (settings.multi_threaded_message_loop) { + NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported."; + return false; + } +#endif + + main_delegate_.reset(new CefMainDelegate(application)); + main_runner_.reset(content::ContentMainRunner::Create()); + + int exit_code; + + // Initialize the content runner. +#if defined(OS_WIN) + sandbox::SandboxInterfaceInfo sandbox_info = {0}; + if (windows_sandbox_info == NULL) { + content::InitializeSandboxInfo(&sandbox_info); + windows_sandbox_info = &sandbox_info; + settings_.no_sandbox = true; + } + + content::ContentMainParams params(main_delegate_.get()); + params.instance = args.instance; + params.sandbox_info = + static_cast(windows_sandbox_info); + + exit_code = main_runner_->Initialize(params); +#else + content::ContentMainParams params(main_delegate_.get()); + params.argc = args.argc; + params.argv = const_cast(args.argv); + + exit_code = main_runner_->Initialize(params); +#endif + + DCHECK_LT(exit_code, 0); + if (exit_code >= 0) + return false; + + // Run the process. Results in a call to CefMainDelegate::RunProcess() which + // will create the browser runner and message loop without blocking. + exit_code = main_runner_->Run(); + + initialized_ = true; + + if (CEF_CURRENTLY_ON_UIT()) { + OnContextInitialized(); + } else { + // Continue initialization on the UI thread. + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefContext::OnContextInitialized, base::Unretained(this))); + } + + return true; +} + +void CefContext::Shutdown() { + // Must always be called on the same thread as Initialize. + DCHECK(OnInitThread()); + + shutting_down_ = true; + + if (settings_.multi_threaded_message_loop) { + // Events that will be used to signal when shutdown is complete. Start in + // non-signaled mode so that the event will block. + base::WaitableEvent uithread_shutdown_event(false, false); + + // Finish shutdown on the UI thread. + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefContext::FinishShutdownOnUIThread, + base::Unretained(this), + &uithread_shutdown_event)); + + /// Block until UI thread shutdown is complete. + uithread_shutdown_event.Wait(); + + FinalizeShutdown(); + } else { + // Finish shutdown on the current thread, which should be the UI thread. + FinishShutdownOnUIThread(NULL); + + FinalizeShutdown(); + } +} + +bool CefContext::OnInitThread() { + return (base::PlatformThread::CurrentId() == init_thread_id_); +} + +CefTraceSubscriber* CefContext::GetTraceSubscriber() { + CEF_REQUIRE_UIT(); + if (shutting_down_) + return NULL; + if (!trace_subscriber_.get()) + trace_subscriber_.reset(new CefTraceSubscriber()); + return trace_subscriber_.get(); +} + +void CefContext::OnContextInitialized() { + CEF_REQUIRE_UIT(); + + // Register internal scheme handlers. + scheme::RegisterInternalHandlers(); + + // Register for notifications. + registrar_.reset(new content::NotificationRegistrar()); + registrar_->Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, + content::NotificationService::AllBrowserContextsAndSources()); + registrar_->Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, + content::NotificationService::AllBrowserContextsAndSources()); + + // Must be created after the NotificationService. + print_job_manager_.reset(new printing::PrintJobManager()); + + // Notify the handler. + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetBrowserProcessHandler(); + if (handler.get()) + handler->OnContextInitialized(); + } +} + +void CefContext::FinishShutdownOnUIThread( + base::WaitableEvent* uithread_shutdown_event) { + CEF_REQUIRE_UIT(); + + // Wait for the pending print jobs to finish. Don't do this later, since + // this might cause a nested message loop to run, and we don't want pending + // tasks to run once teardown has started. + print_job_manager_->Shutdown(); + print_job_manager_.reset(NULL); + + CefContentBrowserClient::Get()->DestroyAllBrowsers(); + + registrar_.reset(); + + if (trace_subscriber_.get()) + trace_subscriber_.reset(NULL); + + if (uithread_shutdown_event) + uithread_shutdown_event->Signal(); +} + +void CefContext::FinalizeShutdown() { + if (content::RenderProcessHost::run_renderer_in_process()) { + // Blocks until RenderProcess cleanup is complete. + CefContentRendererClient::Get()->RunSingleProcessCleanup(); + } + + // Shut down the browser runner or UI thread. + main_delegate_->ShutdownBrowser(); + + // Shut down the content runner. + main_runner_->Shutdown(); + + main_runner_.reset(NULL); + main_delegate_.reset(NULL); +} + +void CefContext::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED || + type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED); + content::RenderProcessHost* rph = + content::Source(source).ptr(); + DCHECK(rph); + CefContentBrowserClient::Get()->RemoveBrowserContextReference( + static_cast(rph->GetBrowserContext())); +} diff --git a/libcef/browser/context.h b/libcef/browser/context.h new file mode 100644 index 000000000..cf57d977e --- /dev/null +++ b/libcef/browser/context.h @@ -0,0 +1,115 @@ +// 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_LIBCEF_BROWSER_CONTEXT_H_ +#define CEF_LIBCEF_BROWSER_CONTEXT_H_ +#pragma once + +#include +#include +#include + +#include "include/cef_app.h" + +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/platform_thread.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +namespace base { +class WaitableEvent; +} + +namespace content { +class ContentMainRunner; +} + +namespace printing { +class PrintJobManager; +} + +class CefBrowserHostImpl; +class CefMainDelegate; +class CefTraceSubscriber; + +class CefContext : public content::NotificationObserver { + public: + typedef std::list > BrowserList; + + CefContext(); + ~CefContext(); + + // Returns the singleton CefContext instance. + static CefContext* Get(); + + // These methods will be called on the main application thread. + bool Initialize(const CefMainArgs& args, + const CefSettings& settings, + CefRefPtr application, + void* windows_sandbox_info); + void Shutdown(); + + // Returns true if the current thread is the initialization thread. + bool OnInitThread(); + + // Returns true if the context is initialized. + bool initialized() { return initialized_; } + + // Returns true if the context is shutting down. + bool shutting_down() { return shutting_down_; } + + // Retrieve the path at which cache data will be stored on disk. + const base::FilePath& cache_path() const { return cache_path_; } + + const CefSettings& settings() const { return settings_; } + + printing::PrintJobManager* print_job_manager() const { + return print_job_manager_.get(); + } + + CefTraceSubscriber* GetTraceSubscriber(); + + private: + void OnContextInitialized(); + + // Performs shutdown actions that need to occur on the UI thread before any + // threads are destroyed. + void FinishShutdownOnUIThread(base::WaitableEvent* uithread_shutdown_event); + + // Destroys the main runner and related objects. + void FinalizeShutdown(); + + // NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Track context state. + bool initialized_; + bool shutting_down_; + + // The thread on which the context was initialized. + base::PlatformThreadId init_thread_id_; + + CefSettings settings_; + base::FilePath cache_path_; + base::ScopedTempDir cache_temp_dir_; + + scoped_ptr main_delegate_; + scoped_ptr main_runner_; + scoped_ptr trace_subscriber_; + + // Only accessed on the UI Thread. + scoped_ptr registrar_; + scoped_ptr print_job_manager_; +}; + +// Helper macro that returns true if the global context is in a valid state. +#define CONTEXT_STATE_VALID() \ + (CefContext::Get() && CefContext::Get()->initialized() && \ + !CefContext::Get()->shutting_down()) + +#endif // CEF_LIBCEF_BROWSER_CONTEXT_H_ diff --git a/libcef/browser/context_menu_params_impl.cc b/libcef/browser/context_menu_params_impl.cc new file mode 100644 index 000000000..4883db273 --- /dev/null +++ b/libcef/browser/context_menu_params_impl.cc @@ -0,0 +1,107 @@ +// 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 "libcef/browser/context_menu_params_impl.h" + +#include "base/logging.h" + +CefContextMenuParamsImpl::CefContextMenuParamsImpl( + content::ContextMenuParams* value) + : CefValueBase( + value, NULL, kOwnerNoDelete, true, + new CefValueControllerNonThreadSafe()) { + // Indicate that this object owns the controller. + SetOwnsController(); +} + +int CefContextMenuParamsImpl::GetXCoord() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().x; +} + +int CefContextMenuParamsImpl::GetYCoord() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().y; +} + +CefContextMenuParamsImpl::TypeFlags CefContextMenuParamsImpl::GetTypeFlags() { + CEF_VALUE_VERIFY_RETURN(false, CM_TYPEFLAG_NONE); + const content::ContextMenuParams& params = const_value(); + int type_flags = CM_TYPEFLAG_NONE; + if (!params.page_url.is_empty()) + type_flags |= CM_TYPEFLAG_PAGE; + if (!params.frame_url.is_empty()) + type_flags |= CM_TYPEFLAG_FRAME; + if (!params.link_url.is_empty()) + type_flags |= CM_TYPEFLAG_LINK; + if (params.media_type != blink::WebContextMenuData::MediaTypeNone) + type_flags |= CM_TYPEFLAG_MEDIA; + if (!params.selection_text.empty()) + type_flags |= CM_TYPEFLAG_SELECTION; + if (params.is_editable) + type_flags |= CM_TYPEFLAG_EDITABLE; + return static_cast(type_flags); +} + +CefString CefContextMenuParamsImpl::GetLinkUrl() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().link_url.spec(); +} + +CefString CefContextMenuParamsImpl::GetUnfilteredLinkUrl() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().unfiltered_link_url.spec(); +} + +CefString CefContextMenuParamsImpl::GetSourceUrl() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().src_url.spec(); +} + +bool CefContextMenuParamsImpl::HasImageContents() { + CEF_VALUE_VERIFY_RETURN(false, true); + return const_value().has_image_contents; +} + +CefString CefContextMenuParamsImpl::GetPageUrl() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().page_url.spec(); +} + +CefString CefContextMenuParamsImpl::GetFrameUrl() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().frame_url.spec(); +} + +CefString CefContextMenuParamsImpl::GetFrameCharset() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().frame_charset; +} + +CefContextMenuParamsImpl::MediaType CefContextMenuParamsImpl::GetMediaType() { + CEF_VALUE_VERIFY_RETURN(false, CM_MEDIATYPE_NONE); + return static_cast(const_value().media_type); +} + +CefContextMenuParamsImpl::MediaStateFlags + CefContextMenuParamsImpl::GetMediaStateFlags() { + CEF_VALUE_VERIFY_RETURN(false, CM_MEDIAFLAG_NONE); + return static_cast(const_value().media_flags); +} + +CefString CefContextMenuParamsImpl::GetSelectionText() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().selection_text; +} + +bool CefContextMenuParamsImpl::IsEditable() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().is_editable; +} + +CefContextMenuParamsImpl::EditStateFlags + CefContextMenuParamsImpl::GetEditStateFlags() { + CEF_VALUE_VERIFY_RETURN(false, CM_EDITFLAG_NONE); + return static_cast(const_value().edit_flags); +} diff --git a/libcef/browser/context_menu_params_impl.h b/libcef/browser/context_menu_params_impl.h new file mode 100644 index 000000000..0877db2ab --- /dev/null +++ b/libcef/browser/context_menu_params_impl.h @@ -0,0 +1,40 @@ +// 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_LIBCEF_BROWSER_CONTEXT_MENU_PARAMS_IMPL_H_ +#define CEF_LIBCEF_BROWSER_CONTEXT_MENU_PARAMS_IMPL_H_ +#pragma once + +#include "include/cef_context_menu_handler.h" +#include "libcef/common/value_base.h" + +#include "content/public/common/context_menu_params.h" + +// CefContextMenuParams implementation. This class is not thread safe. +class CefContextMenuParamsImpl + : public CefValueBase { + public: + explicit CefContextMenuParamsImpl(content::ContextMenuParams* value); + + // CefContextMenuParams methods. + virtual int GetXCoord() OVERRIDE; + virtual int GetYCoord() OVERRIDE; + virtual TypeFlags GetTypeFlags() OVERRIDE; + virtual CefString GetLinkUrl() OVERRIDE; + virtual CefString GetUnfilteredLinkUrl() OVERRIDE; + virtual CefString GetSourceUrl() OVERRIDE; + virtual bool HasImageContents() OVERRIDE; + virtual CefString GetPageUrl() OVERRIDE; + virtual CefString GetFrameUrl() OVERRIDE; + virtual CefString GetFrameCharset() OVERRIDE; + virtual MediaType GetMediaType() OVERRIDE; + virtual MediaStateFlags GetMediaStateFlags() OVERRIDE; + virtual CefString GetSelectionText() OVERRIDE; + virtual bool IsEditable() OVERRIDE; + virtual EditStateFlags GetEditStateFlags() OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(CefContextMenuParamsImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_CONTEXT_MENU_PARAMS_IMPL_H_ diff --git a/libcef/browser/cookie_manager_impl.cc b/libcef/browser/cookie_manager_impl.cc new file mode 100644 index 000000000..443e5b795 --- /dev/null +++ b/libcef/browser/cookie_manager_impl.cc @@ -0,0 +1,449 @@ +// 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 "libcef/browser/cookie_manager_impl.h" + +#include +#include +#include + +#include "libcef/browser/browser_context.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_context_getter.h" +#include "libcef/common/time_util.h" + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/format_macros.h" +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" +#include "content/browser/net/sqlite_persistent_cookie_store.h" +#include "content/public/browser/cookie_crypto_delegate.h" +#include "net/cookies/cookie_util.h" +#include "net/cookies/parsed_cookie.h" +#include "net/url_request/url_request_context.h" +#include "url/gurl.h" + +using content::BrowserThread; + +namespace { + +// Callback class for visiting cookies. +class VisitCookiesCallback : public base::RefCounted { + public: + explicit VisitCookiesCallback(net::CookieMonster* cookie_monster, + CefRefPtr visitor) + : cookie_monster_(cookie_monster), + visitor_(visitor) { + } + + void Run(const net::CookieList& list) { + CEF_REQUIRE_IOT(); + + int total = list.size(), count = 0; + + net::CookieList::const_iterator it = list.begin(); + for (; it != list.end(); ++it, ++count) { + CefCookie cookie; + const net::CanonicalCookie& cc = *(it); + CefCookieManagerImpl::GetCefCookie(cc, cookie); + + bool deleteCookie = false; + bool keepLooping = visitor_->Visit(cookie, count, total, deleteCookie); + if (deleteCookie) { + cookie_monster_->DeleteCanonicalCookieAsync(cc, + net::CookieMonster::DeleteCookieCallback()); + } + if (!keepLooping) + break; + } + } + + private: + scoped_refptr cookie_monster_; + CefRefPtr visitor_; +}; + + +// Methods extracted from net/cookies/cookie_monster.cc + +// Determine the cookie domain to use for setting the specified cookie. +bool GetCookieDomain(const GURL& url, + const net::ParsedCookie& pc, + std::string* result) { + std::string domain_string; + if (pc.HasDomain()) + domain_string = pc.Domain(); + return net::cookie_util::GetCookieDomainWithString(url, domain_string, + result); +} + +void RunCompletionOnIOThread(CefRefPtr callback) { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefCompletionCallback::OnComplete, callback.get())); +} + +} // namespace + + +CefCookieManagerImpl::CefCookieManagerImpl(bool is_global) + : is_global_(is_global) { +} + +CefCookieManagerImpl::~CefCookieManagerImpl() { +} + +void CefCookieManagerImpl::Initialize( + const CefString& path, + bool persist_session_cookies) { + if (is_global_) + SetGlobal(); + else + SetStoragePath(path, persist_session_cookies); +} + +void CefCookieManagerImpl::SetSupportedSchemes( + const std::vector& schemes) { + if (CEF_CURRENTLY_ON_IOT()) { + if (!cookie_monster_) + return; + + if (is_global_) { + // Global changes are handled by the request context. + scoped_refptr getter = + static_cast( + CefContentBrowserClient::Get()->request_context().get()); + + std::vector scheme_vec; + std::vector::const_iterator it = schemes.begin(); + for (; it != schemes.end(); ++it) + scheme_vec.push_back(it->ToString()); + + getter->SetCookieSupportedSchemes(scheme_vec); + return; + } + + supported_schemes_ = schemes; + + if (supported_schemes_.empty()) { + supported_schemes_.push_back("http"); + supported_schemes_.push_back("https"); + } + + std::set scheme_set; + std::vector::const_iterator it = supported_schemes_.begin(); + for (; it != supported_schemes_.end(); ++it) + scheme_set.insert(*it); + + const char** arr = new const char*[scheme_set.size()]; + std::set::const_iterator it2 = scheme_set.begin(); + for (int i = 0; it2 != scheme_set.end(); ++it2, ++i) + arr[i] = it2->c_str(); + + cookie_monster_->SetCookieableSchemes(arr, scheme_set.size()); + + delete [] arr; + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefCookieManagerImpl::SetSupportedSchemes, + this, schemes)); + } +} + +bool CefCookieManagerImpl::VisitAllCookies( + CefRefPtr visitor) { + if (CEF_CURRENTLY_ON_IOT()) { + if (!cookie_monster_) + return false; + + scoped_refptr callback( + new VisitCookiesCallback(cookie_monster_, visitor)); + + cookie_monster_->GetAllCookiesAsync( + base::Bind(&VisitCookiesCallback::Run, callback.get())); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitAllCookies), + this, visitor)); + } + + return true; +} + +bool CefCookieManagerImpl::VisitUrlCookies( + const CefString& url, bool includeHttpOnly, + CefRefPtr visitor) { + if (CEF_CURRENTLY_ON_IOT()) { + if (!cookie_monster_) + return false; + + net::CookieOptions options; + if (includeHttpOnly) + options.set_include_httponly(); + + scoped_refptr callback( + new VisitCookiesCallback(cookie_monster_, visitor)); + + GURL gurl = GURL(url.ToString()); + cookie_monster_->GetAllCookiesForURLWithOptionsAsync(gurl, options, + base::Bind(&VisitCookiesCallback::Run, callback.get())); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitUrlCookies), + this, url, includeHttpOnly, visitor)); + } + + return true; +} + +bool CefCookieManagerImpl::SetCookie(const CefString& url, + const CefCookie& cookie) { + CEF_REQUIRE_IOT_RETURN(false); + + if (!cookie_monster_) + return false; + + GURL gurl = GURL(url.ToString()); + if (!gurl.is_valid()) + return false; + + std::string name = CefString(&cookie.name).ToString(); + std::string value = CefString(&cookie.value).ToString(); + std::string domain = CefString(&cookie.domain).ToString(); + std::string path = CefString(&cookie.path).ToString(); + + base::Time expiration_time; + if (cookie.has_expires) + cef_time_to_basetime(cookie.expires, expiration_time); + + cookie_monster_->SetCookieWithDetailsAsync( + gurl, name, value, domain, path, + expiration_time, + cookie.secure ? true : false, + cookie.httponly ? true : false, + net::COOKIE_PRIORITY_DEFAULT, + net::CookieStore::SetCookiesCallback()); + return true; +} + +bool CefCookieManagerImpl::DeleteCookies(const CefString& url, + const CefString& cookie_name) { + CEF_REQUIRE_IOT_RETURN(false); + + if (!cookie_monster_) + return false; + + if (url.empty()) { + // Delete all cookies. + cookie_monster_->DeleteAllAsync(net::CookieMonster::DeleteCallback()); + return true; + } + + GURL gurl = GURL(url.ToString()); + if (!gurl.is_valid()) + return false; + + if (cookie_name.empty()) { + // Delete all matching host cookies. + cookie_monster_->DeleteAllForHostAsync(gurl, + net::CookieMonster::DeleteCallback()); + } else { + // Delete all matching host and domain cookies. + cookie_monster_->DeleteCookieAsync(gurl, cookie_name, base::Closure()); + } + return true; +} + +bool CefCookieManagerImpl::SetStoragePath( + const CefString& path, + bool persist_session_cookies) { + if (CEF_CURRENTLY_ON_IOT()) { + base::FilePath new_path; + if (!path.empty()) + new_path = base::FilePath(path); + + if (is_global_) { + // Global path changes are handled by the request context. + scoped_refptr getter = + static_cast( + CefContentBrowserClient::Get()->request_context().get()); + getter->SetCookieStoragePath(new_path, persist_session_cookies); + cookie_monster_ = getter->GetURLRequestContext()->cookie_store()-> + GetCookieMonster(); + return true; + } + + if (cookie_monster_ && ((storage_path_.empty() && path.empty()) || + storage_path_ == new_path)) { + // The path has not changed so don't do anything. + return true; + } + + scoped_refptr persistent_store; + if (!new_path.empty()) { + // TODO(cef): Move directory creation to the blocking pool instead of + // allowing file IO on this thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (base::DirectoryExists(new_path) || + base::CreateDirectory(new_path)) { + const base::FilePath& cookie_path = new_path.AppendASCII("Cookies"); + persistent_store = + new content::SQLitePersistentCookieStore( + cookie_path, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), + persist_session_cookies, + NULL, + NULL); + } else { + NOTREACHED() << "The cookie storage directory could not be created"; + storage_path_.clear(); + } + } + + // Set the new cookie store that will be used for all new requests. The old + // cookie store, if any, will be automatically flushed and closed when no + // longer referenced. + cookie_monster_ = new net::CookieMonster(persistent_store.get(), NULL); + if (persistent_store.get() && persist_session_cookies) + cookie_monster_->SetPersistSessionCookies(true); + storage_path_ = new_path; + + // Restore the previously supported schemes. + SetSupportedSchemes(supported_schemes_); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::SetStoragePath), + this, path, persist_session_cookies)); + } + + return true; +} + +bool CefCookieManagerImpl::FlushStore( + CefRefPtr callback) { + if (CEF_CURRENTLY_ON_IOT()) { + if (!cookie_monster_) { + if (callback.get()) + RunCompletionOnIOThread(callback); + return true; + } + + base::Closure flush_callback; + if (callback.get()) + flush_callback = base::Bind(RunCompletionOnIOThread, callback); + else + flush_callback = base::Bind(&base::DoNothing); + + cookie_monster_->FlushStore(flush_callback); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::FlushStore), + this, callback)); + } + + return true; +} + +void CefCookieManagerImpl::SetGlobal() { + if (CEF_CURRENTLY_ON_IOT()) { + if (CefContentBrowserClient::Get()->request_context()) { + cookie_monster_ = CefContentBrowserClient::Get()->request_context()-> + GetURLRequestContext()->cookie_store()->GetCookieMonster(); + DCHECK(cookie_monster_); + } + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, base::Bind(&CefCookieManagerImpl::SetGlobal, this)); + } +} + +// static +bool CefCookieManagerImpl::GetCefCookie(const net::CanonicalCookie& cc, + CefCookie& cookie) { + CefString(&cookie.name).FromString(cc.Name()); + CefString(&cookie.value).FromString(cc.Value()); + CefString(&cookie.domain).FromString(cc.Domain()); + CefString(&cookie.path).FromString(cc.Path()); + cookie.secure = cc.IsSecure(); + cookie.httponly = cc.IsHttpOnly(); + cef_time_from_basetime(cc.CreationDate(), cookie.creation); + cef_time_from_basetime(cc.LastAccessDate(), cookie.last_access); + cookie.has_expires = cc.IsPersistent(); + if (cookie.has_expires) + cef_time_from_basetime(cc.ExpiryDate(), cookie.expires); + + return true; +} + +// static +bool CefCookieManagerImpl::GetCefCookie(const GURL& url, + const std::string& cookie_line, + CefCookie& cookie) { + // Parse the cookie. + net::ParsedCookie pc(cookie_line); + if (!pc.IsValid()) + return false; + + std::string cookie_domain; + if (!GetCookieDomain(url, pc, &cookie_domain)) + return false; + + std::string cookie_path = net::CanonicalCookie::CanonPath(url, pc); + base::Time creation_time = base::Time::Now(); + base::Time cookie_expires = + net::CanonicalCookie::CanonExpiration(pc, creation_time, creation_time); + + CefString(&cookie.name).FromString(pc.Name()); + CefString(&cookie.value).FromString(pc.Value()); + CefString(&cookie.domain).FromString(cookie_domain); + CefString(&cookie.path).FromString(cookie_path); + cookie.secure = pc.IsSecure(); + cookie.httponly = pc.IsHttpOnly(); + cef_time_from_basetime(creation_time, cookie.creation); + cef_time_from_basetime(creation_time, cookie.last_access); + cookie.has_expires = !cookie_expires.is_null(); + if (cookie.has_expires) + cef_time_from_basetime(cookie_expires, cookie.expires); + + return true; +} + + +// CefCookieManager methods ---------------------------------------------------- + +// static +CefRefPtr CefCookieManager::GetGlobalManager() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + CefRefPtr manager(new CefCookieManagerImpl(true)); + manager->Initialize(CefString(), false); + return manager.get(); +} + +// static +CefRefPtr CefCookieManager::CreateManager( + const CefString& path, + bool persist_session_cookies) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + CefRefPtr manager(new CefCookieManagerImpl(false)); + manager->Initialize(path, persist_session_cookies); + return manager.get(); +} diff --git a/libcef/browser/cookie_manager_impl.h b/libcef/browser/cookie_manager_impl.h new file mode 100644 index 000000000..9de25ed5d --- /dev/null +++ b/libcef/browser/cookie_manager_impl.h @@ -0,0 +1,53 @@ +// 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_LIBCEF_BROWSER_COOKIE_MANAGER_IMPL_H_ +#define CEF_LIBCEF_BROWSER_COOKIE_MANAGER_IMPL_H_ + +#include "include/cef_cookie.h" +#include "base/files/file_path.h" +#include "net/cookies/cookie_monster.h" + +// Implementation of the CefCookieManager interface. +class CefCookieManagerImpl : public CefCookieManager { + public: + CefCookieManagerImpl(bool is_global); + ~CefCookieManagerImpl(); + + // Initialize the cookie manager. + void Initialize(const CefString& path, + bool persist_session_cookies); + + // CefCookieManager methods. + virtual void SetSupportedSchemes(const std::vector& schemes) + OVERRIDE; + virtual bool VisitAllCookies(CefRefPtr visitor) OVERRIDE; + virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, + CefRefPtr visitor) OVERRIDE; + virtual bool SetCookie(const CefString& url, + const CefCookie& cookie) OVERRIDE; + virtual bool DeleteCookies(const CefString& url, + const CefString& cookie_name) OVERRIDE; + virtual bool SetStoragePath(const CefString& path, + bool persist_session_cookies) OVERRIDE; + virtual bool FlushStore(CefRefPtr callback) OVERRIDE; + + net::CookieMonster* cookie_monster() { return cookie_monster_; } + + static bool GetCefCookie(const net::CanonicalCookie& cc, CefCookie& cookie); + static bool GetCefCookie(const GURL& url, const std::string& cookie_line, + CefCookie& cookie); + + private: + void SetGlobal(); + + scoped_refptr cookie_monster_; + bool is_global_; + base::FilePath storage_path_; + std::vector supported_schemes_; + + IMPLEMENT_REFCOUNTING(CefCookieManagerImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_COOKIE_MANAGER_IMPL_H_ diff --git a/libcef/browser/devtools_delegate.cc b/libcef/browser/devtools_delegate.cc new file mode 100644 index 000000000..db0fb8076 --- /dev/null +++ b/libcef/browser/devtools_delegate.cc @@ -0,0 +1,172 @@ +// Copyright 2013 the Chromium Embedded Framework Authors. Portions Copyright +// 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 "libcef/browser/devtools_delegate.h" +#include "libcef/browser/devtools_scheme_handler.h" +#include "libcef/common/content_client.h" + +#include +#include + +#include "base/command_line.h" +#include "base/md5.h" +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/devtools_agent_host.h" +#include "base/time/time.h" +#include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/devtools_target.h" +#include "content/public/browser/favicon_status.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_iterator.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/url_constants.h" +#include "grit/cef_resources.h" +#include "net/socket/tcp_listen_socket.h" +#include "ui/base/layout.h" +#include "ui/base/resource/resource_bundle.h" + +namespace { + +const char kTargetTypePage[] = "page"; + +class Target : public content::DevToolsTarget { + public: + explicit Target(content::WebContents* web_contents); + + virtual std::string GetId() const OVERRIDE { return id_; } + virtual std::string GetParentId() const OVERRIDE { return std::string(); } + virtual std::string GetType() const OVERRIDE { return kTargetTypePage; } + virtual std::string GetTitle() const OVERRIDE { return title_; } + virtual std::string GetDescription() const OVERRIDE { return std::string(); } + virtual GURL GetURL() const OVERRIDE { return url_; } + virtual GURL GetFaviconURL() const OVERRIDE { return favicon_url_; } + virtual base::TimeTicks GetLastActivityTime() const OVERRIDE { + return last_activity_time_; + } + virtual bool IsAttached() const OVERRIDE { + return agent_host_->IsAttached(); + } + virtual scoped_refptr GetAgentHost() const + OVERRIDE { + return agent_host_; + } + virtual bool Activate() const OVERRIDE; + virtual bool Close() const OVERRIDE; + + private: + scoped_refptr agent_host_; + std::string id_; + std::string title_; + GURL url_; + GURL favicon_url_; + base::TimeTicks last_activity_time_; +}; + +Target::Target(content::WebContents* web_contents) { + agent_host_ = + content::DevToolsAgentHost::GetOrCreateFor( + web_contents->GetRenderViewHost()); + id_ = agent_host_->GetId(); + title_ = base::UTF16ToUTF8(web_contents->GetTitle()); + url_ = web_contents->GetURL(); + content::NavigationController& controller = web_contents->GetController(); + content::NavigationEntry* entry = controller.GetActiveEntry(); + if (entry != NULL && entry->GetURL().is_valid()) + favicon_url_ = entry->GetFavicon().url; + last_activity_time_ = web_contents->GetLastActiveTime(); +} + +bool Target::Activate() const { + content::RenderViewHost* rvh = agent_host_->GetRenderViewHost(); + if (!rvh) + return false; + content::WebContents* web_contents = + content::WebContents::FromRenderViewHost(rvh); + if (!web_contents) + return false; + web_contents->GetDelegate()->ActivateContents(web_contents); + return true; +} + +bool Target::Close() const { + content::RenderViewHost* rvh = agent_host_->GetRenderViewHost(); + if (!rvh) + return false; + rvh->ClosePage(); + return true; +} + +} // namespace + +// CefDevToolsDelegate + +CefDevToolsDelegate::CefDevToolsDelegate(int port) { + devtools_http_handler_ = content::DevToolsHttpHandler::Start( + new net::TCPListenSocketFactory("127.0.0.1", port), + "", + this, + base::FilePath()); +} + +CefDevToolsDelegate::~CefDevToolsDelegate() { +} + +void CefDevToolsDelegate::Stop() { + // The call below destroys this. + devtools_http_handler_->Stop(); +} + +std::string CefDevToolsDelegate::GetDiscoveryPageHTML() { + return CefContentClient::Get()->GetDataResource( + IDR_CEF_DEVTOOLS_DISCOVERY_PAGE, ui::SCALE_FACTOR_NONE).as_string(); +} + +bool CefDevToolsDelegate::BundlesFrontendResources() { + return true; +} + +base::FilePath CefDevToolsDelegate::GetDebugFrontendDir() { + return base::FilePath(); +} + +std::string CefDevToolsDelegate::GetPageThumbnailData(const GURL& url) { + return std::string(); +} + +scoped_ptr CefDevToolsDelegate::CreateNewTarget( + const GURL& url) { + return scoped_ptr(); +} + +void CefDevToolsDelegate::EnumerateTargets(TargetCallback callback) { + TargetList targets; + std::vector rvh_list = + content::DevToolsAgentHost::GetValidRenderViewHosts(); + for (std::vector::iterator it = rvh_list.begin(); + it != rvh_list.end(); ++it) { + content::WebContents* web_contents = + content::WebContents::FromRenderViewHost(*it); + if (web_contents) + targets.push_back(new Target(web_contents)); + } + callback.Run(targets); +} + +scoped_ptr + CefDevToolsDelegate::CreateSocketForTethering( + net::StreamListenSocket::Delegate* delegate, + std::string* name) { + return scoped_ptr(); +} + +std::string CefDevToolsDelegate::GetChromeDevToolsURL() { + return base::StringPrintf("%s://%s/devtools.html", + content::kChromeDevToolsScheme, scheme::kChromeDevToolsHost); +} diff --git a/libcef/browser/devtools_delegate.h b/libcef/browser/devtools_delegate.h new file mode 100644 index 000000000..b4f731b86 --- /dev/null +++ b/libcef/browser/devtools_delegate.h @@ -0,0 +1,52 @@ +// Copyright 2013 the Chromium Embedded Framework Authors. Portions Copyright +// 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_LIBCEF_BROWSER_DEVTOOLS_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_DEVTOOLS_DELEGATE_H_ +#pragma once + +#include +#include + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/devtools_http_handler_delegate.h" + +namespace content { +class RenderViewHost; +} + +class CefDevToolsDelegate : public content::DevToolsHttpHandlerDelegate { + public: + explicit CefDevToolsDelegate(int port); + virtual ~CefDevToolsDelegate(); + + // Stops http server. + void Stop(); + + // DevToolsHttpProtocolHandler::Delegate overrides. + virtual std::string GetDiscoveryPageHTML() OVERRIDE; + virtual bool BundlesFrontendResources() OVERRIDE; + virtual base::FilePath GetDebugFrontendDir() OVERRIDE; + virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE; + virtual scoped_ptr CreateNewTarget(const GURL& url) + OVERRIDE; + virtual void EnumerateTargets(TargetCallback callback) OVERRIDE; + virtual scoped_ptr CreateSocketForTethering( + net::StreamListenSocket::Delegate* delegate, + std::string* name) OVERRIDE; + + // Returns the chrome-devtools URL. + std::string GetChromeDevToolsURL(); + + private: + content::DevToolsHttpHandler* devtools_http_handler_; + + DISALLOW_COPY_AND_ASSIGN(CefDevToolsDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_DEVTOOLS_DELEGATE_H_ diff --git a/libcef/browser/devtools_frontend.cc b/libcef/browser/devtools_frontend.cc new file mode 100644 index 000000000..231ef1d1d --- /dev/null +++ b/libcef/browser/devtools_frontend.cc @@ -0,0 +1,107 @@ +// Copyright 2013 the Chromium Embedded Framework Authors. Portions Copyright +// 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 "libcef/browser/devtools_frontend.h" + +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/devtools_delegate.h" +#include "libcef/browser/request_context_impl.h" + +#include "base/command_line.h" +#include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/devtools_manager.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_client.h" +#include "net/base/net_util.h" +#include "third_party/skia/include/core/SkColor.h" + +// static +CefDevToolsFrontend* CefDevToolsFrontend::Show( + CefRefPtr inspected_browser, + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) { + CefBrowserSettings new_settings = settings; + if (CefColorGetA(new_settings.background_color) == 0) { + // Use white as the default background color for DevTools instead of the + // CefSettings.background_color value. + new_settings.background_color = SK_ColorWHITE; + } + + CefRefPtr frontend_browser = + CefBrowserHostImpl::Create(windowInfo, client, CefString(), + new_settings, + inspected_browser->GetWindowHandle(), true, + inspected_browser->GetRequestContext()); + + // CefDevToolsFrontend will delete itself when the frontend WebContents is + // destroyed. + CefDevToolsFrontend* devtools_frontend = new CefDevToolsFrontend( + static_cast(frontend_browser.get()), + content::DevToolsAgentHost::GetOrCreateFor( + inspected_browser->GetWebContents()->GetRenderViewHost()).get()); + + // Need to load the URL after creating the DevTools objects. + CefDevToolsDelegate* delegate = + CefContentBrowserClient::Get()->devtools_delegate(); + frontend_browser->GetMainFrame()->LoadURL(delegate->GetChromeDevToolsURL()); + + devtools_frontend->Activate(); + devtools_frontend->Focus(); + + return devtools_frontend; +} + +void CefDevToolsFrontend::Activate() { + frontend_browser_->ActivateContents(web_contents()); +} + +void CefDevToolsFrontend::Focus() { + web_contents()->Focus(); +} + +void CefDevToolsFrontend::Close() { + frontend_browser_->CloseBrowser(true); +} + +CefDevToolsFrontend::CefDevToolsFrontend( + CefRefPtr frontend_browser, + content::DevToolsAgentHost* agent_host) + : WebContentsObserver(frontend_browser->GetWebContents()), + frontend_browser_(frontend_browser), + agent_host_(agent_host) { + frontend_host_.reset( + content::DevToolsClientHost::CreateDevToolsFrontendHost( + web_contents(), this)); +} + +CefDevToolsFrontend::~CefDevToolsFrontend() { +} + +void CefDevToolsFrontend::RenderViewCreated( + content::RenderViewHost* render_view_host) { + content::DevToolsClientHost::SetupDevToolsFrontendClient( + web_contents()->GetRenderViewHost()); + content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor( + agent_host_.get(), frontend_host_.get()); +} + +void CefDevToolsFrontend::DocumentOnLoadCompletedInMainFrame() { + web_contents()->GetMainFrame()->ExecuteJavaScript( + base::ASCIIToUTF16("InspectorFrontendAPI.setUseSoftMenu(true);")); +} + +void CefDevToolsFrontend::WebContentsDestroyed() { + content::DevToolsManager::GetInstance()->ClientHostClosing( + frontend_host_.get()); + delete this; +} + +void CefDevToolsFrontend::InspectedContentsClosing() { + Close(); +} diff --git a/libcef/browser/devtools_frontend.h b/libcef/browser/devtools_frontend.h new file mode 100644 index 000000000..4e0acf780 --- /dev/null +++ b/libcef/browser/devtools_frontend.h @@ -0,0 +1,64 @@ +// Copyright 2013 the Chromium Embedded Framework Authors. Portions Copyright +// 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_LIBCEF_BROWSER_DEVTOOLS_FRONTEND_H_ +#define CEF_LIBCEF_BROWSER_DEVTOOLS_FRONTEND_H_ + +#include "libcef/browser/browser_host_impl.h" + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/devtools_client_host.h" +#include "content/public/browser/devtools_frontend_host_delegate.h" +#include "content/public/browser/web_contents_observer.h" + +namespace content { +class RenderViewHost; +class WebContents; +} + +class CefDevToolsFrontend : public content::WebContentsObserver, + public content::DevToolsFrontendHostDelegate { + public: + static CefDevToolsFrontend* Show( + CefRefPtr inspected_browser, + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings); + + void Activate(); + void Focus(); + void Close(); + + CefRefPtr frontend_browser() const { + return frontend_browser_; + } + + private: + CefDevToolsFrontend(CefRefPtr frontend_browser, + content::DevToolsAgentHost* agent_host); + virtual ~CefDevToolsFrontend(); + + // WebContentsObserver overrides + virtual void RenderViewCreated( + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DocumentOnLoadCompletedInMainFrame() OVERRIDE; + virtual void WebContentsDestroyed() OVERRIDE; + + // DevToolsFrontendHostDelegate implementation + virtual void DispatchOnEmbedder(const std::string& message) OVERRIDE {} + + virtual void InspectedContentsClosing() OVERRIDE; + + CefRefPtr frontend_browser_; + scoped_refptr agent_host_; + scoped_ptr frontend_host_; + + DISALLOW_COPY_AND_ASSIGN(CefDevToolsFrontend); +}; + +#endif // CEF_LIBCEF_BROWSER_DEVTOOLS_FRONTEND_H_ diff --git a/libcef/browser/devtools_scheme_handler.cc b/libcef/browser/devtools_scheme_handler.cc new file mode 100644 index 000000000..115596496 --- /dev/null +++ b/libcef/browser/devtools_scheme_handler.cc @@ -0,0 +1,54 @@ +// 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 "libcef/browser/devtools_scheme_handler.h" + +#include + +#include "libcef/browser/internal_scheme_handler.h" + +#include "base/strings/string_util.h" +#include "content/public/common/url_constants.h" +#include "grit/devtools_resources_map.h" + +namespace scheme { + +const char kChromeDevToolsHost[] = "devtools"; + +namespace { + +class Delegate : public InternalHandlerDelegate { + public: + Delegate() {} + + virtual bool OnRequest(CefRefPtr request, + Action* action) OVERRIDE { + GURL url = GURL(request->GetURL().ToString()); + std::string path = url.path(); + if (path.length() > 0) + path = path.substr(1); + + for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { + if (base::strcasecmp(kDevtoolsResources[i].name, + path.c_str()) == 0) { + action->resource_id = kDevtoolsResources[i].value; + return true; + } + } + + return false; + } +}; + +} // namespace + +void RegisterChromeDevToolsHandler() { + CefRegisterSchemeHandlerFactory( + content::kChromeDevToolsScheme, + kChromeDevToolsHost, + CreateInternalHandlerFactory( + make_scoped_ptr(new Delegate()))); +} + +} // namespace scheme diff --git a/libcef/browser/devtools_scheme_handler.h b/libcef/browser/devtools_scheme_handler.h new file mode 100644 index 000000000..57168b17b --- /dev/null +++ b/libcef/browser/devtools_scheme_handler.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. + +#ifndef CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ +#define CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ +#pragma once + +namespace scheme { + +extern const char kChromeDevToolsHost[]; + +// Register the chrome-devtools scheme handler. +void RegisterChromeDevToolsHandler(); + +} // namespace scheme + +#endif // CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ diff --git a/libcef/browser/download_item_impl.cc b/libcef/browser/download_item_impl.cc new file mode 100644 index 000000000..ae8787744 --- /dev/null +++ b/libcef/browser/download_item_impl.cc @@ -0,0 +1,102 @@ +// 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 "libcef/browser/download_item_impl.h" + +#include "libcef/common/time_util.h" + +#include "content/public/browser/download_item.h" +#include "url/gurl.h" + + +CefDownloadItemImpl::CefDownloadItemImpl(content::DownloadItem* value) + : CefValueBase( + value, NULL, kOwnerNoDelete, true, + new CefValueControllerNonThreadSafe()) { + // Indicate that this object owns the controller. + SetOwnsController(); +} + +bool CefDownloadItemImpl::IsValid() { + return !detached(); +} + +bool CefDownloadItemImpl::IsInProgress() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().GetState() == content::DownloadItem::IN_PROGRESS; +} + +bool CefDownloadItemImpl::IsComplete() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().GetState() == content::DownloadItem::COMPLETE; +} + +bool CefDownloadItemImpl::IsCanceled() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().GetState() == content::DownloadItem::CANCELLED; +} + +int64 CefDownloadItemImpl::GetCurrentSpeed() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().CurrentSpeed(); +} + +int CefDownloadItemImpl::GetPercentComplete() { + CEF_VALUE_VERIFY_RETURN(false, -1); + return const_value().PercentComplete(); +} + +int64 CefDownloadItemImpl::GetTotalBytes() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().GetTotalBytes(); +} + +int64 CefDownloadItemImpl::GetReceivedBytes() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().GetReceivedBytes(); +} + +CefTime CefDownloadItemImpl::GetStartTime() { + CefTime time; + CEF_VALUE_VERIFY_RETURN(false, time); + cef_time_from_basetime(const_value().GetStartTime(), time); + return time; +} + +CefTime CefDownloadItemImpl::GetEndTime() { + CefTime time; + CEF_VALUE_VERIFY_RETURN(false, time); + cef_time_from_basetime(const_value().GetEndTime(), time); + return time; +} + +CefString CefDownloadItemImpl::GetFullPath() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetFullPath().value(); +} + +uint32 CefDownloadItemImpl::GetId() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().GetId(); +} + +CefString CefDownloadItemImpl::GetURL() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetURL().spec(); +} + +CefString CefDownloadItemImpl::GetSuggestedFileName() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetSuggestedFilename(); +} + +CefString CefDownloadItemImpl::GetContentDisposition() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetContentDisposition(); +} + +CefString CefDownloadItemImpl::GetMimeType() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetMimeType(); +} diff --git a/libcef/browser/download_item_impl.h b/libcef/browser/download_item_impl.h new file mode 100644 index 000000000..6f3fcc8df --- /dev/null +++ b/libcef/browser/download_item_impl.h @@ -0,0 +1,44 @@ +// 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_LIBCEF_BROWSER_DOWNLOAD_ITEM_IMPL_H_ +#define CEF_LIBCEF_BROWSER_DOWNLOAD_ITEM_IMPL_H_ +#pragma once + +#include "include/cef_download_item.h" +#include "libcef/common/value_base.h" + +namespace content { +class DownloadItem; +} + +// CefDownloadItem implementation +class CefDownloadItemImpl + : public CefValueBase { + public: + explicit CefDownloadItemImpl(content::DownloadItem* value); + + // CefDownloadItem methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsInProgress() OVERRIDE; + virtual bool IsComplete() OVERRIDE; + virtual bool IsCanceled() OVERRIDE; + virtual int64 GetCurrentSpeed() OVERRIDE; + virtual int GetPercentComplete() OVERRIDE; + virtual int64 GetTotalBytes() OVERRIDE; + virtual int64 GetReceivedBytes() OVERRIDE; + virtual CefTime GetStartTime() OVERRIDE; + virtual CefTime GetEndTime() OVERRIDE; + virtual CefString GetFullPath() OVERRIDE; + virtual uint32 GetId() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual CefString GetSuggestedFileName() OVERRIDE; + virtual CefString GetContentDisposition() OVERRIDE; + virtual CefString GetMimeType() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(CefDownloadItemImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_DOWNLOAD_ITEM_IMPL_H_ diff --git a/libcef/browser/download_manager_delegate.cc b/libcef/browser/download_manager_delegate.cc new file mode 100644 index 000000000..b263c9fe2 --- /dev/null +++ b/libcef/browser/download_manager_delegate.cc @@ -0,0 +1,349 @@ +// 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 "libcef/browser/download_manager_delegate.h" + +#include "include/cef_download_handler.h" +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/context.h" +#include "libcef/browser/download_item_impl.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/file_chooser_params.h" +#include "net/base/filename_util.h" + +using content::DownloadItem; +using content::DownloadManager; +using content::WebContents; + + +namespace { + +// Helper function to retrieve the CefBrowserHostImpl. +CefRefPtr GetBrowser(DownloadItem* item) { + content::WebContents* contents = item->GetWebContents(); + if (!contents) + return NULL; + + return CefBrowserHostImpl::GetBrowserForContents(contents).get(); +} + +// Helper function to retrieve the CefDownloadHandler. +CefRefPtr GetDownloadHandler( + CefRefPtr browser) { + CefRefPtr client = browser->GetClient(); + if (client.get()) + return client->GetDownloadHandler(); + return NULL; +} + + +// CefBeforeDownloadCallback implementation. +class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback { + public: + CefBeforeDownloadCallbackImpl( + const base::WeakPtr& manager, + uint32 download_id, + const base::FilePath& suggested_name, + const content::DownloadTargetCallback& callback) + : manager_(manager), + download_id_(download_id), + suggested_name_(suggested_name), + callback_(callback) { + } + + virtual void Continue(const CefString& download_path, + bool show_dialog) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (download_id_ <= 0) + return; + + if (manager_) { + base::FilePath path = base::FilePath(download_path); + CEF_POST_TASK(CEF_FILET, + base::Bind(&CefBeforeDownloadCallbackImpl::GenerateFilename, + manager_, download_id_, suggested_name_, path, + show_dialog, callback_)); + } + + download_id_ = 0; + callback_.Reset(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBeforeDownloadCallbackImpl::Continue, this, + download_path, show_dialog)); + } + } + + private: + static void GenerateFilename( + base::WeakPtr manager, + uint32 download_id, + const base::FilePath& suggested_name, + const base::FilePath& download_path, + bool show_dialog, + const content::DownloadTargetCallback& callback) { + base::FilePath suggested_path = download_path; + if (!suggested_path.empty()) { + // Create the directory if necessary. + base::FilePath dir_path = suggested_path.DirName(); + if (!base::DirectoryExists(dir_path) && + !base::CreateDirectory(dir_path)) { + NOTREACHED() << "failed to create the download directory"; + suggested_path.clear(); + } + } + + if (suggested_path.empty()) { + if (PathService::Get(base::DIR_TEMP, &suggested_path)) { + // Use the temp directory. + suggested_path = suggested_path.Append(suggested_name); + } else { + // Use the current working directory. + suggested_path = suggested_name; + } + } + + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBeforeDownloadCallbackImpl::ChooseDownloadPath, + manager, download_id, suggested_path, show_dialog, + callback)); + } + + static void ChooseDownloadPath( + base::WeakPtr manager, + uint32 download_id, + const base::FilePath& suggested_path, + bool show_dialog, + const content::DownloadTargetCallback& callback) { + if (!manager) + return; + + DownloadItem* item = manager->GetDownload(download_id); + if (!item || item->GetState() != content::DownloadItem::IN_PROGRESS) + return; + + bool handled = false; + + if (show_dialog) { + WebContents* web_contents = item->GetWebContents(); + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForContents(web_contents); + if (browser.get()) { + handled = true; + + content::FileChooserParams params; + params.mode = content::FileChooserParams::Save; + if (!suggested_path.empty()) { + params.default_file_name = suggested_path; + if (!suggested_path.Extension().empty()) { + params.accept_types.push_back( + CefString(suggested_path.Extension())); + } + } + + browser->RunFileChooser(params, + base::Bind( + &CefBeforeDownloadCallbackImpl::ChooseDownloadPathCallback, + callback)); + } + } + + if (!handled) { + callback.Run(suggested_path, + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + suggested_path); + } + } + + static void ChooseDownloadPathCallback( + const content::DownloadTargetCallback& callback, + const std::vector& file_paths) { + DCHECK_LE(file_paths.size(), (size_t) 1); + + base::FilePath path; + if (file_paths.size() > 0) + path = file_paths.front(); + + // The download will be cancelled if |path| is empty. + callback.Run(path, + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + path); + } + + base::WeakPtr manager_; + uint32 download_id_; + base::FilePath suggested_name_; + content::DownloadTargetCallback callback_; + + IMPLEMENT_REFCOUNTING(CefBeforeDownloadCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefBeforeDownloadCallbackImpl); +}; + + +// CefDownloadItemCallback implementation. +class CefDownloadItemCallbackImpl : public CefDownloadItemCallback { + public: + explicit CefDownloadItemCallbackImpl( + const base::WeakPtr& manager, + uint32 download_id) + : manager_(manager), + download_id_(download_id) { + } + + virtual void Cancel() OVERRIDE { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefDownloadItemCallbackImpl::DoCancel, this)); + } + + private: + void DoCancel() { + if (download_id_ <= 0) + return; + + if (manager_) { + DownloadItem* item = manager_->GetDownload(download_id_); + if (item && item->GetState() == content::DownloadItem::IN_PROGRESS) + item->Cancel(true); + } + + download_id_ = 0; + } + + base::WeakPtr manager_; + uint32 download_id_; + + IMPLEMENT_REFCOUNTING(CefDownloadItemCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefDownloadItemCallbackImpl); +}; + +} // namespace + + +CefDownloadManagerDelegate::CefDownloadManagerDelegate( + DownloadManager* manager) + : manager_(manager), + manager_ptr_factory_(manager) { + DCHECK(manager); + manager->AddObserver(this); + + DownloadManager::DownloadVector items; + manager->GetAllDownloads(&items); + DownloadManager::DownloadVector::const_iterator it = items.begin(); + for (; it != items.end(); ++it) { + (*it)->AddObserver(this); + observing_.insert(*it); + } +} + +CefDownloadManagerDelegate::~CefDownloadManagerDelegate() { + if (manager_) { + manager_->SetDelegate(NULL); + manager_->RemoveObserver(this); + } + + std::set::const_iterator it = observing_.begin(); + for (; it != observing_.end(); ++it) + (*it)->RemoveObserver(this); + observing_.clear(); +} + +void CefDownloadManagerDelegate::OnDownloadUpdated( + DownloadItem* download) { + CefRefPtr browser = GetBrowser(download); + CefRefPtr handler; + if (browser.get()) + handler = GetDownloadHandler(browser); + + if (handler.get()) { + CefRefPtr download_item( + new CefDownloadItemImpl(download)); + CefRefPtr callback( + new CefDownloadItemCallbackImpl(manager_ptr_factory_.GetWeakPtr(), + download->GetId())); + + handler->OnDownloadUpdated(browser.get(), download_item.get(), callback); + + download_item->Detach(NULL); + } +} + +void CefDownloadManagerDelegate::OnDownloadDestroyed( + DownloadItem* download) { + download->RemoveObserver(this); + observing_.erase(download); +} + +void CefDownloadManagerDelegate::OnDownloadCreated( + DownloadManager* manager, + DownloadItem* item) { + item->AddObserver(this); + observing_.insert(item); +} + +void CefDownloadManagerDelegate::ManagerGoingDown( + DownloadManager* manager) { + DCHECK_EQ(manager, manager_); + manager->SetDelegate(NULL); + manager->RemoveObserver(this); + manager_ptr_factory_.InvalidateWeakPtrs(); + manager_ = NULL; +} + +bool CefDownloadManagerDelegate::DetermineDownloadTarget( + DownloadItem* item, + const content::DownloadTargetCallback& callback) { + if (!item->GetForcedFilePath().empty()) { + callback.Run(item->GetForcedFilePath(), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + item->GetForcedFilePath()); + return true; + } + + CefRefPtr browser = GetBrowser(item); + CefRefPtr handler; + if (browser.get()) + handler = GetDownloadHandler(browser); + + if (handler.get()) { + base::FilePath suggested_name = net::GenerateFileName( + item->GetURL(), + item->GetContentDisposition(), + std::string(), + item->GetSuggestedFilename(), + item->GetMimeType(), + "download"); + + CefRefPtr download_item(new CefDownloadItemImpl(item)); + CefRefPtr callbackObj( + new CefBeforeDownloadCallbackImpl(manager_ptr_factory_.GetWeakPtr(), + item->GetId(), suggested_name, + callback)); + + handler->OnBeforeDownload(browser.get(), download_item.get(), + suggested_name.value(), callbackObj); + + download_item->Detach(NULL); + } + + return true; +} + +void CefDownloadManagerDelegate::GetNextId( + const content::DownloadIdCallback& callback) { + static uint32 next_id = DownloadItem::kInvalidId + 1; + callback.Run(next_id++); +} diff --git a/libcef/browser/download_manager_delegate.h b/libcef/browser/download_manager_delegate.h new file mode 100644 index 000000000..86f01f78c --- /dev/null +++ b/libcef/browser/download_manager_delegate.h @@ -0,0 +1,48 @@ +// 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_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_ +#pragma once + +#include + +#include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/download_item.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_manager_delegate.h" + +class CefDownloadManagerDelegate + : public content::DownloadItem::Observer, + public content::DownloadManager::Observer, + public content::DownloadManagerDelegate { + public: + explicit CefDownloadManagerDelegate(content::DownloadManager* manager); + ~CefDownloadManagerDelegate(); + + private: + // DownloadItem::Observer methods. + virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; + virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE; + + // DownloadManager::Observer methods. + virtual void OnDownloadCreated(content::DownloadManager* manager, + content::DownloadItem* item) OVERRIDE; + virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE; + + // DownloadManagerDelegate methods. + virtual bool DetermineDownloadTarget( + content::DownloadItem* item, + const content::DownloadTargetCallback& callback) OVERRIDE; + virtual void GetNextId(const content::DownloadIdCallback& callback) OVERRIDE; + + content::DownloadManager* manager_; + base::WeakPtrFactory manager_ptr_factory_; + std::set observing_; + + DISALLOW_COPY_AND_ASSIGN(CefDownloadManagerDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_DOWNLOAD_MANAGER_DELEGATE_H_ diff --git a/libcef/browser/frame_host_impl.cc b/libcef/browser/frame_host_impl.cc new file mode 100644 index 000000000..2cf4905bf --- /dev/null +++ b/libcef/browser/frame_host_impl.cc @@ -0,0 +1,279 @@ +// 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 "libcef/browser/frame_host_impl.h" +#include "include/cef_request.h" +#include "include/cef_stream.h" +#include "include/cef_v8.h" +#include "libcef/common/cef_messages.h" +#include "libcef/browser/browser_host_impl.h" + +namespace { + +// Implementation of CommandResponseHandler for calling a CefStringVisitor. +class StringVisitHandler : public CefResponseManager::Handler { + public: + explicit StringVisitHandler(CefRefPtr visitor) + : visitor_(visitor) { + } + virtual void OnResponse(const Cef_Response_Params& params) OVERRIDE { + visitor_->Visit(params.response); + } + private: + CefRefPtr visitor_; + + IMPLEMENT_REFCOUNTING(StringVisitHandler); +}; + +// Implementation of CommandResponseHandler for calling ViewText(). +class ViewTextHandler : public CefResponseManager::Handler { + public: + explicit ViewTextHandler(CefRefPtr frame) + : frame_(frame) { + } + virtual void OnResponse(const Cef_Response_Params& params) OVERRIDE { + CefRefPtr browser = frame_->GetBrowser(); + if (browser.get()) { + static_cast(browser.get())->ViewText( + params.response); + } + } + private: + CefRefPtr frame_; + + IMPLEMENT_REFCOUNTING(ViewTextHandler); +}; + +} // namespace + +CefFrameHostImpl::CefFrameHostImpl(CefBrowserHostImpl* browser, + int64 frame_id, + bool is_main_frame, + const CefString& url, + const CefString& name, + int64 parent_frame_id) + : frame_id_(frame_id), + is_main_frame_(is_main_frame), + browser_(browser), + is_focused_(false), + url_(url), + name_(name), + parent_frame_id_(parent_frame_id == kUnspecifiedFrameId ? + kInvalidFrameId : parent_frame_id) { +} + +CefFrameHostImpl::~CefFrameHostImpl() { +} + +bool CefFrameHostImpl::IsValid() { + base::AutoLock lock_scope(state_lock_); + return (browser_ != NULL); +} + +void CefFrameHostImpl::Undo() { + SendCommand("Undo", NULL); +} + +void CefFrameHostImpl::Redo() { + SendCommand("Redo", NULL); +} + +void CefFrameHostImpl::Cut() { + SendCommand("Cut", NULL); +} + +void CefFrameHostImpl::Copy() { + SendCommand("Copy", NULL); +} + +void CefFrameHostImpl::Paste() { + SendCommand("Paste", NULL); +} + +void CefFrameHostImpl::Delete() { + SendCommand("Delete", NULL); +} + +void CefFrameHostImpl::SelectAll() { + SendCommand("SelectAll", NULL); +} + +void CefFrameHostImpl::ViewSource() { + SendCommand("GetSource", new ViewTextHandler(this)); +} + +void CefFrameHostImpl::GetSource(CefRefPtr visitor) { + SendCommand("GetSource", new StringVisitHandler(visitor)); +} + +void CefFrameHostImpl::GetText(CefRefPtr visitor) { + SendCommand("GetText", new StringVisitHandler(visitor)); +} + +void CefFrameHostImpl::LoadRequest(CefRefPtr request) { + CefRefPtr browser; + int64 frame_id; + + { + base::AutoLock lock_scope(state_lock_); + browser = browser_; + frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); + } + + if (browser) + browser->LoadRequest(frame_id, request); +} + +void CefFrameHostImpl::LoadURL(const CefString& url) { + CefRefPtr browser; + int64 frame_id; + + { + base::AutoLock lock_scope(state_lock_); + browser = browser_; + frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); + } + + if (browser) { + browser->LoadURL(frame_id, url, content::Referrer(), + content::PAGE_TRANSITION_TYPED, std::string()); + } +} + +void CefFrameHostImpl::LoadString(const CefString& string, + const CefString& url) { + CefRefPtr browser; + int64 frame_id; + + { + base::AutoLock lock_scope(state_lock_); + browser = browser_; + frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); + } + + if (browser) + browser->LoadString(frame_id, string, url); +} + +void CefFrameHostImpl::ExecuteJavaScript(const CefString& jsCode, + const CefString& scriptUrl, + int startLine) { + SendJavaScript(jsCode, scriptUrl, startLine); +} + +bool CefFrameHostImpl::IsMain() { + return is_main_frame_; +} + +bool CefFrameHostImpl::IsFocused() { + base::AutoLock lock_scope(state_lock_); + return is_focused_; +} + +CefString CefFrameHostImpl::GetName() { + base::AutoLock lock_scope(state_lock_); + return name_; +} + +int64 CefFrameHostImpl::GetIdentifier() { + return frame_id_; +} + +CefRefPtr CefFrameHostImpl::GetParent() { + CefRefPtr browser; + int64 parent_frame_id; + + { + base::AutoLock lock_scope(state_lock_); + if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId) + return NULL; + browser = browser_; + parent_frame_id = parent_frame_id_; + } + + if (browser) + return browser->GetFrame(parent_frame_id); + + return NULL; +} + +CefString CefFrameHostImpl::GetURL() { + base::AutoLock lock_scope(state_lock_); + return url_; +} + +CefRefPtr CefFrameHostImpl::GetBrowser() { + base::AutoLock lock_scope(state_lock_); + return browser_; +} + +void CefFrameHostImpl::SetFocused(bool focused) { + base::AutoLock lock_scope(state_lock_); + is_focused_ = focused; +} + +void CefFrameHostImpl::SetAttributes(const CefString& url, + const CefString& name, + int64 parent_frame_id) { + base::AutoLock lock_scope(state_lock_); + if (!url.empty() && url != url_) + url_ = url; + if (!name.empty() && name != name_) + name_ = name; + if (parent_frame_id != kUnspecifiedFrameId) + parent_frame_id_ = parent_frame_id; +} + +CefRefPtr CefFrameHostImpl::GetV8Context() { + NOTREACHED() << "GetV8Context cannot be called from the browser process"; + return NULL; +} + +void CefFrameHostImpl::VisitDOM(CefRefPtr visitor) { + NOTREACHED() << "VisitDOM cannot be called from the browser process"; +} + +void CefFrameHostImpl::SendJavaScript( + const std::string& jsCode, + const std::string& scriptUrl, + int startLine) { + if (jsCode.empty()) + return; + if (startLine < 0) + startLine = 0; + + CefRefPtr browser; + int64 frame_id; + + { + base::AutoLock lock_scope(state_lock_); + browser = browser_; + frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); + } + + if (browser) + browser->SendCode(frame_id, true, jsCode, scriptUrl, startLine, NULL); +} + +void CefFrameHostImpl::Detach() { + base::AutoLock lock_scope(state_lock_); + browser_ = NULL; +} + +void CefFrameHostImpl::SendCommand( + const std::string& command, + CefRefPtr responseHandler) { + CefRefPtr browser; + int64 frame_id; + + { + base::AutoLock lock_scope(state_lock_); + browser = browser_; + // Commands can only be sent to known frame ids. + frame_id = frame_id_; + } + + if (browser && frame_id != kInvalidFrameId) + browser->SendCommand(frame_id, command, responseHandler); +} diff --git a/libcef/browser/frame_host_impl.h b/libcef/browser/frame_host_impl.h new file mode 100644 index 000000000..0089b8103 --- /dev/null +++ b/libcef/browser/frame_host_impl.h @@ -0,0 +1,96 @@ +// 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_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_ +#define CEF_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_ +#pragma once + +#include +#include "include/cef_frame.h" +#include "libcef/common/response_manager.h" +#include "base/synchronization/lock.h" + +class CefBrowserHostImpl; + +// Implementation of CefFrame. CefFrameHostImpl objects are owned by the +// CefBrowerHostImpl and will be detached when the browser is notified that the +// associated renderer WebFrame will close. +class CefFrameHostImpl : public CefFrame { + public: + CefFrameHostImpl(CefBrowserHostImpl* browser, + int64 frame_id, + bool is_main_frame, + const CefString& url, + const CefString& name, + int64 parent_frame_id); + virtual ~CefFrameHostImpl(); + + // CefFrame methods + virtual bool IsValid() OVERRIDE; + virtual void Undo() OVERRIDE; + virtual void Redo() OVERRIDE; + virtual void Cut() OVERRIDE; + virtual void Copy() OVERRIDE; + virtual void Paste() OVERRIDE; + virtual void Delete() OVERRIDE; + virtual void SelectAll() OVERRIDE; + virtual void ViewSource() OVERRIDE; + virtual void GetSource(CefRefPtr visitor) OVERRIDE; + virtual void GetText(CefRefPtr visitor) OVERRIDE; + virtual void LoadRequest(CefRefPtr request) OVERRIDE; + virtual void LoadURL(const CefString& url) OVERRIDE; + virtual void LoadString(const CefString& string, + const CefString& url) OVERRIDE; + virtual void ExecuteJavaScript(const CefString& jsCode, + const CefString& scriptUrl, + int startLine) OVERRIDE; + virtual bool IsMain() OVERRIDE; + virtual bool IsFocused() OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual int64 GetIdentifier() OVERRIDE; + virtual CefRefPtr GetParent() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual CefRefPtr GetV8Context() OVERRIDE; + virtual void VisitDOM(CefRefPtr visitor) OVERRIDE; + + void SetFocused(bool focused); + void SetAttributes(const CefString& url, + const CefString& name, + int64 parent_frame_id); + + // Avoids unnecessary string type conversions. + void SendJavaScript(const std::string& jsCode, + const std::string& scriptUrl, + int startLine); + + // Detach the frame from the browser. + void Detach(); + + // kMainFrameId must be -1 to align with renderer expectations. + static const int64 kMainFrameId = -1; + static const int64 kFocusedFrameId = -2; + static const int64 kUnspecifiedFrameId = -3; + static const int64 kInvalidFrameId = -4; + + protected: + void SendCommand(const std::string& command, + CefRefPtr responseHandler); + + int64 frame_id_; + bool is_main_frame_; + + // Volatile state information. All access must be protected by the state lock. + base::Lock state_lock_; + CefBrowserHostImpl* browser_; + bool is_focused_; + CefString url_; + CefString name_; + int64 parent_frame_id_; + + IMPLEMENT_REFCOUNTING(CefFrameHostImpl); + DISALLOW_EVIL_CONSTRUCTORS(CefFrameHostImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_ diff --git a/libcef/browser/geolocation_impl.cc b/libcef/browser/geolocation_impl.cc new file mode 100644 index 000000000..8e6f7247f --- /dev/null +++ b/libcef/browser/geolocation_impl.cc @@ -0,0 +1,101 @@ +// 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 "include/cef_geolocation.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/time_util.h" +#include "base/logging.h" +#include "content/public/browser/geolocation_provider.h" +#include "content/public/common/geoposition.h" + +namespace { + +class CefLocationRequest : + public base::RefCountedThreadSafe { + public: + explicit CefLocationRequest(CefRefPtr callback) + : callback_(callback) { + CEF_REQUIRE_UIT(); + geo_callback_ = base::Bind(&CefLocationRequest::OnLocationUpdate, this); + content::GeolocationProvider* provider = + content::GeolocationProvider::GetInstance(); + subscription_ = provider->AddLocationUpdateCallback(geo_callback_, true); + provider->UserDidOptIntoLocationServices(); + } + + private: + void OnLocationUpdate(const content::Geoposition& position) { + CEF_REQUIRE_UIT(); + if (callback_) { + CefGeoposition cef_position; + SetPosition(position, cef_position); + callback_->OnLocationUpdate(cef_position); + callback_ = NULL; + } + subscription_.reset(); + geo_callback_.Reset(); + } + + void SetPosition(const content::Geoposition& source, CefGeoposition& target) { + target.latitude = source.latitude; + target.longitude = source.longitude; + target.altitude = source.altitude; + target.accuracy = source.accuracy; + target.altitude_accuracy = source.altitude_accuracy; + target.heading = source.heading; + target.speed = source.speed; + cef_time_from_basetime(source.timestamp, target.timestamp); + + switch (source.error_code) { + case content::Geoposition::ERROR_CODE_NONE: + target.error_code = GEOPOSITON_ERROR_NONE; + break; + case content::Geoposition::ERROR_CODE_PERMISSION_DENIED: + target.error_code = GEOPOSITON_ERROR_PERMISSION_DENIED; + break; + case content::Geoposition::ERROR_CODE_POSITION_UNAVAILABLE: + target.error_code = GEOPOSITON_ERROR_POSITION_UNAVAILABLE; + break; + case content::Geoposition::ERROR_CODE_TIMEOUT: + target.error_code = GEOPOSITON_ERROR_TIMEOUT; + break; + } + + CefString(&target.error_message) = source.error_message; + } + + CefRefPtr callback_; + content::GeolocationProvider::LocationUpdateCallback geo_callback_; + scoped_ptr subscription_; + + DISALLOW_COPY_AND_ASSIGN(CefLocationRequest); +}; + +} // namespace + +bool CefGetGeolocation(CefRefPtr callback) { + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return false; + } + + if (!callback.get()) { + NOTREACHED() << "invalid parameter"; + return false; + } + + if (CEF_CURRENTLY_ON_UIT()) { + if (content::GeolocationProvider::GetInstance()) { + // Will be released after the callback executes. + new CefLocationRequest(callback); + return true; + } + return false; + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(CefGetGeolocation), callback)); + return true; + } +} diff --git a/libcef/browser/internal_scheme_handler.cc b/libcef/browser/internal_scheme_handler.cc new file mode 100644 index 000000000..2bc824cbe --- /dev/null +++ b/libcef/browser/internal_scheme_handler.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2012 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 "libcef/browser/internal_scheme_handler.h" +#include +#include "libcef/common/content_client.h" +#include "base/strings/string_util.h" +#include "ui/base/resource/resource_bundle.h" + +namespace scheme { + +namespace { + +static std::string GetMimeType(const std::string& filename) { + if (EndsWith(filename, ".html", false)) { + return "text/html"; + } else if (EndsWith(filename, ".css", false)) { + return "text/css"; + } else if (EndsWith(filename, ".jpg", false)) { + return "image/jpeg"; + } else if (EndsWith(filename, ".js", false)) { + return "application/javascript"; + } else if (EndsWith(filename, ".png", false)) { + return "image/png"; + } else if (EndsWith(filename, ".gif", false)) { + return "image/gif"; + } + NOTREACHED() << "No known mime type for file: " << filename.c_str(); + return "text/plain"; +} + +class RedirectHandler : public CefResourceHandler { + public: + explicit RedirectHandler(const GURL& url) + : url_(url) { + } + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) OVERRIDE { + callback->Continue(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = 0; + redirectUrl = url_.spec(); + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) OVERRIDE { + return false; + } + + virtual void Cancel() OVERRIDE { + } + + private: + GURL url_; + + IMPLEMENT_REFCOUNTING(RedirectHandler); +}; + +class InternalHandler : public CefResourceHandler { + public: + InternalHandler(const std::string& mime_type, + CefRefPtr reader, + int size) + : mime_type_(mime_type), + reader_(reader), + size_(size) { + } + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) OVERRIDE { + callback->Continue(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = size_; + + response->SetMimeType(mime_type_); + response->SetStatus(200); + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) OVERRIDE { + bytes_read = reader_->Read(data_out, 1, bytes_to_read); + return (bytes_read > 0); + } + + virtual void Cancel() OVERRIDE { + } + + private: + std::string mime_type_; + CefRefPtr reader_; + int size_; + + IMPLEMENT_REFCOUNTING(InternalHandler); +}; + +class InternalHandlerFactory : public CefSchemeHandlerFactory { + public: + explicit InternalHandlerFactory( + scoped_ptr delegate) + : delegate_(delegate.Pass()) { + } + + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) OVERRIDE { + GURL url = GURL(request->GetURL().ToString()); + + InternalHandlerDelegate::Action action; + if (delegate_->OnRequest(request, &action)) { + if (!action.redirect_url.is_empty() && action.redirect_url.is_valid()) + return new RedirectHandler(action.redirect_url); + + if (action.mime_type.empty()) + action.mime_type = GetMimeType(url.path()); + + if (action.resource_id >= 0) { + base::StringPiece piece = CefContentClient::Get()->GetDataResource( + action.resource_id, ui::SCALE_FACTOR_NONE); + if (!piece.empty()) { + action.stream = + CefStreamReader::CreateForData(const_cast(piece.data()), + piece.size()); + action.stream_size = piece.size(); + } else { + NOTREACHED() << "Failed to load internal resource for id: " << + action.resource_id << " URL: " << url.spec().c_str(); + return NULL; + } + } + + if (action.stream.get()) { + return new InternalHandler(action.mime_type, action.stream, + action.stream_size); + } + } + + return NULL; + } + + private: + scoped_ptr delegate_; + + IMPLEMENT_REFCOUNTING(InternalHandlerFactory); +}; + +} // namespace + +InternalHandlerDelegate::Action::Action() + : stream_size(-1), + resource_id(-1) { +} + +CefRefPtr CreateInternalHandlerFactory( + scoped_ptr delegate) { + DCHECK(delegate.get()); + return new InternalHandlerFactory(delegate.Pass()); +} + +} // namespace scheme diff --git a/libcef/browser/internal_scheme_handler.h b/libcef/browser/internal_scheme_handler.h new file mode 100644 index 000000000..f29637374 --- /dev/null +++ b/libcef/browser/internal_scheme_handler.h @@ -0,0 +1,53 @@ +// 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_LIBCEF_BROWSER_INTERNAL_SCHEME_HANDLER_H_ +#define CEF_LIBCEF_BROWSER_INTERNAL_SCHEME_HANDLER_H_ +#pragma once + +#include +#include "include/cef_scheme.h" +#include "base/memory/scoped_ptr.h" +#include "url/gurl.h" + +namespace scheme { + +// All methods will be called on the browser process IO thread. +class InternalHandlerDelegate { + public: + class Action { + public: + Action(); + + // Set to the appropriate value or leave empty to have it determined based + // on the file extension. + std::string mime_type; + + // Option 1: Provide a stream for the resource contents. Set |stream_size| + // to the stream size or to -1 if unknown. + CefRefPtr stream; + int stream_size; + + // Option 2: Specify a resource id to load static content. + int resource_id; + + // Option 3: Redirect to the specified URL. + GURL redirect_url; + }; + + virtual ~InternalHandlerDelegate() {} + + // Populate |action| and return true if the request was handled. + virtual bool OnRequest(CefRefPtr request, + Action* action) = 0; +}; + +// Create an internal scheme handler factory. The factory will take ownership of +// |delegate|. +CefRefPtr CreateInternalHandlerFactory( + scoped_ptr delegate); + +} // namespace scheme + +#endif // CEF_LIBCEF_BROWSER_INTERNAL_SCHEME_HANDLER_H_ diff --git a/libcef/browser/javascript_dialog.h b/libcef/browser/javascript_dialog.h new file mode 100644 index 000000000..4e1da5a27 --- /dev/null +++ b/libcef/browser/javascript_dialog.h @@ -0,0 +1,67 @@ +// Copyright (c) 2012 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_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_ +#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_ +#pragma once + +#include "content/public/browser/javascript_dialog_manager.h" + +#if defined(OS_MACOSX) +#if __OBJC__ +@class CefJavaScriptDialogHelper; +#else +class CefJavaScriptDialogHelper; +#endif // __OBJC__ +#endif // defined(OS_MACOSX) + +class CefJavaScriptDialogManager; + +class CefJavaScriptDialog { + public: + CefJavaScriptDialog( + CefJavaScriptDialogManager* creator, + content::JavaScriptMessageType message_type, + const base::string16& display_url, + const base::string16& message_text, + const base::string16& default_prompt_text, + const content::JavaScriptDialogManager::DialogClosedCallback& callback); + ~CefJavaScriptDialog(); + + // Called to cancel a dialog mid-flight. + void Cancel(); + + // Activate the dialog. + void Activate(); + + private: + CefJavaScriptDialogManager* creator_; + content::JavaScriptDialogManager::DialogClosedCallback callback_; + +#if defined(OS_MACOSX) + CefJavaScriptDialogHelper* helper_; // owned +#elif defined(OS_WIN) + content::JavaScriptMessageType message_type_; + HWND dialog_win_; + HWND parent_win_; + base::string16 message_text_; + base::string16 default_prompt_text_; + static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam, + LPARAM lparam); + + // Since the message loop we expect to run in isn't going to be nicely + // calling IsDialogMessage(), we need to hook the wnd proc and call it + // ourselves. See http://support.microsoft.com/kb/q187988/ + static bool InstallMessageHook(); + static bool UninstallMessageHook(); + static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam); + static HHOOK msg_hook_; + static int msg_hook_user_count_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialog); +}; + +#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_ diff --git a/libcef/browser/javascript_dialog_linux.cc b/libcef/browser/javascript_dialog_linux.cc new file mode 100644 index 000000000..83bcdfdd9 --- /dev/null +++ b/libcef/browser/javascript_dialog_linux.cc @@ -0,0 +1,28 @@ +// Copyright (c) 2012 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 "libcef/browser/javascript_dialog.h" +#include "libcef/browser/javascript_dialog_manager.h" + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogManager* creator, + content::JavaScriptMessageType message_type, + const base::string16& display_url, + const base::string16& message_text, + const base::string16& default_prompt_text, + const content::JavaScriptDialogManager::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback) { + NOTIMPLEMENTED(); + callback_.Run(false, base::string16()); + creator_->DialogClosed(this); +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { +} + +void CefJavaScriptDialog::Cancel() { +} + diff --git a/libcef/browser/javascript_dialog_mac.mm b/libcef/browser/javascript_dialog_mac.mm new file mode 100644 index 000000000..83de49cf3 --- /dev/null +++ b/libcef/browser/javascript_dialog_mac.mm @@ -0,0 +1,155 @@ +// Copyright (c) 2012 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 "libcef/browser/javascript_dialog.h" +#include "libcef/browser/javascript_dialog_manager.h" + +#import + +#import "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" + +// Helper object that receives the notification that the dialog/sheet is +// going away. Is responsible for cleaning itself up. +@interface CefJavaScriptDialogHelper : NSObject { + @private + base::scoped_nsobject alert_; + NSTextField* textField_; // WEAK; owned by alert_ + + // Copies of the fields in CefJavaScriptDialog because they're private. + CefJavaScriptDialogManager* creator_; + content::JavaScriptDialogManager::DialogClosedCallback callback_; +} + +- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator + andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback; +- (NSAlert*)alert; +- (NSTextField*)textField; +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo; +- (void)cancel; + +@end + +@implementation CefJavaScriptDialogHelper + +- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator + andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback { + if (self = [super init]) { + creator_ = creator; + callback_ = callback; + } + + return self; +} + +- (NSAlert*)alert { + alert_.reset([[NSAlert alloc] init]); + return alert_; +} + +- (NSTextField*)textField { + textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; + [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; + [alert_ setAccessoryView:textField_]; + [textField_ release]; + + return textField_; +} + +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + if (returnCode == NSRunStoppedResponse) + return; + + bool success = returnCode == NSAlertFirstButtonReturn; + base::string16 input; + if (textField_) + input = base::SysNSStringToUTF16([textField_ stringValue]); + + CefJavaScriptDialog* native_dialog = + reinterpret_cast(contextInfo); + callback_.Run(success, input); + creator_->DialogClosed(native_dialog); +} + +- (void)cancel { + [NSApp endSheet:[alert_ window]]; + alert_.reset(); +} + +@end + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogManager* creator, + content::JavaScriptMessageType message_type, + const base::string16& display_url, + const base::string16& message_text, + const base::string16& default_prompt_text, + const content::JavaScriptDialogManager::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback) { + bool text_field = + message_type == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT; + bool one_button = + message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT; + + helper_ = + [[CefJavaScriptDialogHelper alloc] initHelperWithCreator:creator + andCallback:callback]; + + // Show the modal dialog. + NSAlert* alert = [helper_ alert]; + NSTextField* field = nil; + if (text_field) { + field = [helper_ textField]; + [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)]; + } + [alert setDelegate:helper_]; + [alert setInformativeText:base::SysUTF16ToNSString(message_text)]; + + base::string16 label; + switch (message_type) { + case content::JAVASCRIPT_MESSAGE_TYPE_ALERT: + label = base::ASCIIToUTF16("JavaScript Alert"); + break; + case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT: + label = base::ASCIIToUTF16("JavaScript Prompt"); + break; + case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM: + label = base::ASCIIToUTF16("JavaScript Confirm"); + break; + } + if (!display_url.empty()) + label += base::ASCIIToUTF16(" - ") + display_url; + + [alert setMessageText:base::SysUTF16ToNSString(label)]; + + [alert addButtonWithTitle:@"OK"]; + if (!one_button) { + NSButton* other = [alert addButtonWithTitle:@"Cancel"]; + [other setKeyEquivalent:@"\e"]; + } + + [alert + beginSheetModalForWindow:nil // nil here makes it app-modal + modalDelegate:helper_ + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:this]; + + if ([alert accessoryView]) + [[alert window] makeFirstResponder:[alert accessoryView]]; +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { + [helper_ release]; +} + +void CefJavaScriptDialog::Cancel() { + [helper_ cancel]; +} diff --git a/libcef/browser/javascript_dialog_manager.cc b/libcef/browser/javascript_dialog_manager.cc new file mode 100644 index 000000000..cae3a2b4e --- /dev/null +++ b/libcef/browser/javascript_dialog_manager.cc @@ -0,0 +1,226 @@ +// Copyright (c) 2012 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 "libcef/browser/javascript_dialog_manager.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/javascript_dialog.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "net/base/net_util.h" + +namespace { + +class CefJSDialogCallbackImpl : public CefJSDialogCallback { + public: + CefJSDialogCallbackImpl( + const content::JavaScriptDialogManager::DialogClosedCallback& callback) + : callback_(callback) { + } + ~CefJSDialogCallbackImpl() { + if (!callback_.is_null()) { + // The callback is still pending. Cancel it now. + if (CEF_CURRENTLY_ON_UIT()) { + CancelNow(callback_); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefJSDialogCallbackImpl::CancelNow, callback_)); + } + } + } + + virtual void Continue(bool success, + const CefString& user_input) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + callback_.Run(success, user_input); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefJSDialogCallbackImpl::Continue, this, success, + user_input)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void CancelNow( + const content::JavaScriptDialogManager::DialogClosedCallback& callback) { + CEF_REQUIRE_UIT(); + callback.Run(false, base::string16()); + } + + content::JavaScriptDialogManager::DialogClosedCallback callback_; + + IMPLEMENT_REFCOUNTING(CefJSDialogCallbackImpl); +}; + +} // namespace + + +CefJavaScriptDialogManager::CefJavaScriptDialogManager( + CefBrowserHostImpl* browser) + : browser_(browser) { +} + +CefJavaScriptDialogManager::~CefJavaScriptDialogManager() { +} + +void CefJavaScriptDialogManager::RunJavaScriptDialog( + content::WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + content::JavaScriptMessageType message_type, + const base::string16& message_text, + const base::string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + *did_suppress_message = false; + + CefRefPtr callbackPtr( + new CefJSDialogCallbackImpl(callback)); + + // Execute the user callback. + bool handled = handler->OnJSDialog(browser_, origin_url.spec(), + accept_lang, + static_cast(message_type), + message_text, default_prompt_text, callbackPtr.get(), + *did_suppress_message); + if (handled) { + // Invalid combination of values. Crash sooner rather than later. + CHECK(!*did_suppress_message); + return; + } + + callbackPtr->Disconnect(); + if (*did_suppress_message) + return; + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK) + *did_suppress_message = false; + + if (dialog_.get()) { + // One dialog at a time, please. + *did_suppress_message = true; + return; + } + + base::string16 display_url = net::FormatUrl(origin_url, accept_lang); + + dialog_.reset(new CefJavaScriptDialog(this, + message_type, + display_url, + message_text, + default_prompt_text, + callback)); +#else + // TODO(port): implement CefJavaScriptDialog for other platforms. + *did_suppress_message = true; + return; +#endif +} + +void CefJavaScriptDialogManager::RunBeforeUnloadDialog( + content::WebContents* web_contents, + const base::string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) { + if (browser_->destruction_state() >= + CefBrowserHostImpl::DESTRUCTION_STATE_ACCEPTED) { + // Currently destroying the browser. Accept the unload without showing + // the prompt. + callback.Run(true, base::string16()); + return; + } + + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + CefRefPtr callbackPtr( + new CefJSDialogCallbackImpl(callback)); + + // Execute the user callback. + bool handled = handler->OnBeforeUnloadDialog(browser_, message_text, + is_reload, callbackPtr.get()); + if (handled) + return; + + callbackPtr->Disconnect(); + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK) + if (dialog_.get()) { + // Seriously!? + callback.Run(true, base::string16()); + return; + } + + base::string16 new_message_text = + message_text + + base::ASCIIToUTF16("\n\nIs it OK to leave/reload this page?"); + + dialog_.reset( + new CefJavaScriptDialog(this, + content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM, + base::string16(), // display_url + new_message_text, + base::string16(), // default_prompt_text + callback)); +#else + // TODO(port): implement CefJavaScriptDialog for other platforms. + callback.Run(true, base::string16()); + return; +#endif +} + +void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs( + content::WebContents* web_contents) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + // Execute the user callback. + handler->OnResetDialogState(browser_); + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK) + if (dialog_.get()) { + dialog_->Cancel(); + dialog_.reset(); + } +#endif +} + +void CefJavaScriptDialogManager::WebContentsDestroyed( + content::WebContents* web_contents) { +} + +void CefJavaScriptDialogManager::DialogClosed(CefJavaScriptDialog* dialog) { +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK) + DCHECK_EQ(dialog, dialog_.get()); + dialog_.reset(); + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) + handler->OnDialogClosed(browser_); + } +#endif +} diff --git a/libcef/browser/javascript_dialog_manager.h b/libcef/browser/javascript_dialog_manager.h new file mode 100644 index 000000000..445499bff --- /dev/null +++ b/libcef/browser/javascript_dialog_manager.h @@ -0,0 +1,64 @@ +// Copyright (c) 2012 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_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_ +#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_ +#pragma once + +#include + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/javascript_dialog_manager.h" + +class CefBrowserHostImpl; +class CefJavaScriptDialog; + +class CefJavaScriptDialogManager : public content::JavaScriptDialogManager { + public: + explicit CefJavaScriptDialogManager(CefBrowserHostImpl* browser); + virtual ~CefJavaScriptDialogManager(); + + // JavaScriptDialogManager methods. + virtual void RunJavaScriptDialog( + content::WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + content::JavaScriptMessageType message_type, + const base::string16& message_text, + const base::string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) OVERRIDE; + + virtual void RunBeforeUnloadDialog( + content::WebContents* web_contents, + const base::string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) OVERRIDE; + + virtual void CancelActiveAndPendingDialogs( + content::WebContents* web_contents) OVERRIDE; + + virtual void WebContentsDestroyed( + content::WebContents* web_contents) OVERRIDE; + + // Called by the CefJavaScriptDialog when it closes. + void DialogClosed(CefJavaScriptDialog* dialog); + + CefBrowserHostImpl* browser() const { return browser_; } + + private: + // This pointer is guaranteed to outlive the CefJavaScriptDialogManager. + CefBrowserHostImpl* browser_; + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK) + // The dialog being shown. No queueing. + scoped_ptr dialog_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogManager); +}; + +#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_ diff --git a/libcef/browser/javascript_dialog_win.cc b/libcef/browser/javascript_dialog_win.cc new file mode 100644 index 000000000..861978c2c --- /dev/null +++ b/libcef/browser/javascript_dialog_win.cc @@ -0,0 +1,228 @@ +// Copyright (c) 2012 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 "libcef/browser/javascript_dialog.h" +#include "libcef/browser/javascript_dialog_manager.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef_dll/resource.h" + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" + +class CefJavaScriptDialog; + +HHOOK CefJavaScriptDialog::msg_hook_ = NULL; +int CefJavaScriptDialog::msg_hook_user_count_ = 0; + +INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_INITDIALOG: { + SetWindowLongPtr(dialog, DWLP_USER, static_cast(lparam)); + CefJavaScriptDialog* owner = + reinterpret_cast(lparam); + owner->dialog_win_ = dialog; + SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str()); + if (owner->message_type_ == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) + SetDlgItemText(dialog, IDC_PROMPTEDIT, + owner->default_prompt_text_.c_str()); + break; + } + case WM_CLOSE: { + CefJavaScriptDialog* owner = reinterpret_cast( + GetWindowLongPtr(dialog, DWLP_USER)); + if (owner) { + owner->Cancel(); + owner->callback_.Run(false, base::string16()); + owner->creator_->DialogClosed(owner); + + // No need for the system to call DestroyWindow() because it will be + // called by the Cancel() method. + return 0; + } + break; + } + case WM_COMMAND: { + CefJavaScriptDialog* owner = reinterpret_cast( + GetWindowLongPtr(dialog, DWLP_USER)); + base::string16 user_input; + bool finish = false; + bool result; + switch (LOWORD(wparam)) { + case IDOK: + finish = true; + result = true; + if (owner->message_type_ == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) { + size_t length = + GetWindowTextLength(GetDlgItem(dialog, IDC_PROMPTEDIT)) + 1; + if (length > 1) { + GetDlgItemText(dialog, IDC_PROMPTEDIT, + WriteInto(&user_input, length), length); + } + } + break; + case IDCANCEL: + finish = true; + result = false; + break; + } + if (finish) { + owner->Cancel(); + owner->callback_.Run(result, user_input); + owner->creator_->DialogClosed(owner); + } + break; + } + default: + return DefWindowProc(dialog, message, wparam, lparam); + } + return 0; +} + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogManager* creator, + content::JavaScriptMessageType message_type, + const base::string16& display_url, + const base::string16& message_text, + const base::string16& default_prompt_text, + const content::JavaScriptDialogManager::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback), + message_text_(message_text), + default_prompt_text_(default_prompt_text), + message_type_(message_type) { + InstallMessageHook(); + + int dialog_type; + if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT) + dialog_type = IDD_ALERT; + else if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM) + dialog_type = IDD_CONFIRM; + else // JAVASCRIPT_MESSAGE_TYPE_PROMPT + dialog_type = IDD_PROMPT; + + base::FilePath file_path; + HMODULE hModule = NULL; + + // Try to load the dialog from the DLL. + if (PathService::Get(base::FILE_MODULE, &file_path)) + hModule = ::GetModuleHandle(file_path.value().c_str()); + if (!hModule) + hModule = ::GetModuleHandle(NULL); + DCHECK(hModule); + + parent_win_ = GetAncestor(creator->browser()->GetWindowHandle(), GA_ROOT); + dialog_win_ = CreateDialogParam(hModule, + MAKEINTRESOURCE(dialog_type), + parent_win_, + DialogProc, + reinterpret_cast(this)); + DCHECK(dialog_win_); + + if (!display_url.empty()) { + // Add the display URL to the window title. + TCHAR text[64]; + GetWindowText(dialog_win_, text, sizeof(text)/sizeof(TCHAR)); + + base::string16 new_window_text = + text + base::ASCIIToUTF16(" - ") + display_url; + SetWindowText(dialog_win_, new_window_text.c_str()); + } + + // Disable the parent window so the user can't interact with it. + if (IsWindowEnabled(parent_win_)) + EnableWindow(parent_win_, FALSE); + + ShowWindow(dialog_win_, SW_SHOWNORMAL); +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { + Cancel(); + UninstallMessageHook(); +} + +void CefJavaScriptDialog::Cancel() { + HWND parent = NULL; + + // Re-enable the parent before closing the popup to avoid focus/activation/ + // z-order issues. + if (parent_win_ && IsWindow(parent_win_) && !IsWindowEnabled(parent_win_)) { + parent = parent_win_; + EnableWindow(parent_win_, TRUE); + parent_win_ = NULL; + } + + if (dialog_win_ && IsWindow(dialog_win_)) { + SetWindowLongPtr(dialog_win_, DWLP_USER, NULL); + DestroyWindow(dialog_win_); + dialog_win_ = NULL; + } + + // Return focus to the parent window. + if (parent) + SetFocus(parent); +} + +// static +LRESULT CALLBACK CefJavaScriptDialog::GetMsgProc(int code, WPARAM wparam, + LPARAM lparam) { + // Mostly borrowed from http://support.microsoft.com/kb/q187988/ + // and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx. + LPMSG msg = reinterpret_cast(lparam); + if (code >= 0 && wparam == PM_REMOVE && + msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST) { + HWND hwnd = GetActiveWindow(); + if (::IsWindow(hwnd) && ::IsDialogMessage(hwnd, msg)) { + // The value returned from this hookproc is ignored, and it cannot + // be used to tell Windows the message has been handled. To avoid + // further processing, convert the message to WM_NULL before + // returning. + msg->hwnd = NULL; + msg->message = WM_NULL; + msg->lParam = 0L; + msg->wParam = 0; + } + } + + // Passes the hook information to the next hook procedure in + // the current hook chain. + return ::CallNextHookEx(msg_hook_, code, wparam, lparam); +} + +// static +bool CefJavaScriptDialog::InstallMessageHook() { + msg_hook_user_count_++; + + // Make sure we only call this once. + if (msg_hook_ != NULL) + return true; + + msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, + &CefJavaScriptDialog::GetMsgProc, + NULL, + GetCurrentThreadId()); + DCHECK(msg_hook_ != NULL); + return msg_hook_ != NULL; +} + +// static +bool CefJavaScriptDialog::UninstallMessageHook() { + msg_hook_user_count_--; + DCHECK_GE(msg_hook_user_count_, 0); + + if (msg_hook_user_count_ > 0) + return true; + + DCHECK(msg_hook_ != NULL); + BOOL result = ::UnhookWindowsHookEx(msg_hook_); + DCHECK(result); + msg_hook_ = NULL; + + return result != FALSE; +} diff --git a/libcef/browser/media_capture_devices_dispatcher.cc b/libcef/browser/media_capture_devices_dispatcher.cc new file mode 100644 index 000000000..0bd4082dc --- /dev/null +++ b/libcef/browser/media_capture_devices_dispatcher.cc @@ -0,0 +1,141 @@ +// 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 "libcef/browser/media_capture_devices_dispatcher.h" + +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/pref_service.h" +#include "chrome/common/pref_names.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/media_capture_devices.h" + +using content::BrowserThread; +using content::MediaStreamDevices; + +namespace { + +const content::MediaStreamDevice* FindDefaultDeviceWithId( + const content::MediaStreamDevices& devices, + const std::string& device_id) { + if (devices.empty()) + return NULL; + + content::MediaStreamDevices::const_iterator iter = devices.begin(); + for (; iter != devices.end(); ++iter) { + if (iter->id == device_id) { + return &(*iter); + } + } + + return &(*devices.begin()); +}; + +} // namespace + + +CefMediaCaptureDevicesDispatcher* + CefMediaCaptureDevicesDispatcher::GetInstance() { + return Singleton::get(); +} + +CefMediaCaptureDevicesDispatcher::CefMediaCaptureDevicesDispatcher() {} + +CefMediaCaptureDevicesDispatcher::~CefMediaCaptureDevicesDispatcher() {} + +void CefMediaCaptureDevicesDispatcher::RegisterPrefs( + PrefRegistrySimple* registry) { + registry->RegisterStringPref(prefs::kDefaultAudioCaptureDevice, + std::string()); + registry->RegisterStringPref(prefs::kDefaultVideoCaptureDevice, + std::string()); +} + +void CefMediaCaptureDevicesDispatcher::GetDefaultDevices( + PrefService* prefs, + bool audio, + bool video, + content::MediaStreamDevices* devices) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(audio || video); + + std::string default_device; + if (audio) { + default_device = prefs->GetString(prefs::kDefaultAudioCaptureDevice); + GetRequestedDevice(default_device, true, false, devices); + } + + if (video) { + default_device = prefs->GetString(prefs::kDefaultVideoCaptureDevice); + GetRequestedDevice(default_device, false, true, devices); + } +} + +void CefMediaCaptureDevicesDispatcher::GetRequestedDevice( + const std::string& requested_device_id, + bool audio, + bool video, + content::MediaStreamDevices* devices) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(audio || video); + + if (audio) { + const content::MediaStreamDevices& audio_devices = GetAudioCaptureDevices(); + const content::MediaStreamDevice* const device = + FindDefaultDeviceWithId(audio_devices, requested_device_id); + if (device) + devices->push_back(*device); + } + if (video) { + const content::MediaStreamDevices& video_devices = GetVideoCaptureDevices(); + const content::MediaStreamDevice* const device = + FindDefaultDeviceWithId(video_devices, requested_device_id); + if (device) + devices->push_back(*device); + } +} + +void CefMediaCaptureDevicesDispatcher::OnAudioCaptureDevicesChanged() { +} + +void CefMediaCaptureDevicesDispatcher::OnVideoCaptureDevicesChanged() { +} + +void CefMediaCaptureDevicesDispatcher::OnMediaRequestStateChanged( + int render_process_id, + int render_view_id, + int page_request_id, + const GURL& security_origin, + const content::MediaStreamDevice& device, + content::MediaRequestState state) { +} + +void CefMediaCaptureDevicesDispatcher::OnCreatingAudioStream( + int render_process_id, + int render_view_id) { +} + +void CefMediaCaptureDevicesDispatcher::OnAudioStreamPlaying( + int render_process_id, + int render_frame_id, + int stream_id, + const ReadPowerAndClipCallback& power_read_callback) { +} + +void CefMediaCaptureDevicesDispatcher::OnAudioStreamStopped( + int render_process_id, + int render_frame_id, + int stream_id) { +} + +const MediaStreamDevices& +CefMediaCaptureDevicesDispatcher::GetAudioCaptureDevices() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return content::MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices(); +} + +const MediaStreamDevices& +CefMediaCaptureDevicesDispatcher::GetVideoCaptureDevices() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return content::MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(); +} diff --git a/libcef/browser/media_capture_devices_dispatcher.h b/libcef/browser/media_capture_devices_dispatcher.h new file mode 100644 index 000000000..bde4f05ef --- /dev/null +++ b/libcef/browser/media_capture_devices_dispatcher.h @@ -0,0 +1,76 @@ +// 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_LIBCEF_BROWSER_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ +#define CEF_LIBCEF_BROWSER_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "base/observer_list.h" +#include "content/public/browser/media_observer.h" +#include "content/public/common/media_stream_request.h" + +class PrefRegistrySimple; +class PrefService; + +// This singleton is used to receive updates about media events from the content +// layer. Based on chrome/browser/media/media_capture_devices_dispatcher.[h|cc]. +class CefMediaCaptureDevicesDispatcher : public content::MediaObserver { + public: + static CefMediaCaptureDevicesDispatcher* GetInstance(); + + // Registers the preferences related to Media Stream default devices. + static void RegisterPrefs(PrefRegistrySimple* registry); + + // Helper to get the default devices which can be used by the media request, + // if the return list is empty, it means there is no available device on the + // OS. Called on the UI thread. + void GetDefaultDevices(PrefService* prefs, + bool audio, + bool video, + content::MediaStreamDevices* devices); + + // Helper for picking the device that was requested for an OpenDevice request. + // If the device requested is not available it will revert to using the first + // available one instead or will return an empty list if no devices of the + // requested kind are present. Called on the UI thread. + void GetRequestedDevice(const std::string& requested_device_id, + bool audio, + bool video, + content::MediaStreamDevices* devices); + + // Overridden from content::MediaObserver: + virtual void OnAudioCaptureDevicesChanged() OVERRIDE; + virtual void OnVideoCaptureDevicesChanged() OVERRIDE; + virtual void OnMediaRequestStateChanged( + int render_process_id, + int render_view_id, + int page_request_id, + const GURL& security_origin, + const content::MediaStreamDevice& device, + content::MediaRequestState state) OVERRIDE; + virtual void OnCreatingAudioStream(int render_process_id, + int render_view_id) OVERRIDE; + virtual void OnAudioStreamPlaying( + int render_process_id, + int render_frame_id, + int stream_id, + const ReadPowerAndClipCallback& power_read_callback) OVERRIDE; + virtual void OnAudioStreamStopped( + int render_process_id, + int render_frame_id, + int stream_id) OVERRIDE; + + private: + friend struct DefaultSingletonTraits; + + CefMediaCaptureDevicesDispatcher(); + virtual ~CefMediaCaptureDevicesDispatcher(); + + const content::MediaStreamDevices& GetAudioCaptureDevices(); + const content::MediaStreamDevices& GetVideoCaptureDevices(); +}; + +#endif // CEF_LIBCEF_BROWSER_MEDIA_CAPTURE_DEVICES_DISPATCHER_H_ diff --git a/libcef/browser/menu_creator.cc b/libcef/browser/menu_creator.cc new file mode 100644 index 000000000..80291ec23 --- /dev/null +++ b/libcef/browser/menu_creator.cc @@ -0,0 +1,310 @@ +// 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 "libcef/browser/menu_creator.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/context_menu_params_impl.h" +#include "libcef/common/content_client.h" + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "grit/cef_strings.h" + +#if defined(OS_WIN) +#include "libcef/browser/menu_creator_runner_win.h" +#elif defined(OS_MACOSX) +#include "libcef/browser/menu_creator_runner_mac.h" +#elif defined(OS_LINUX) +#include "libcef/browser/menu_creator_runner_linux.h" +#endif + +namespace { + +CefString GetLabel(int message_id) { + base::string16 label = + CefContentClient::Get()->GetLocalizedString(message_id); + DCHECK(!label.empty()); + return label; +} + +} // namespace + +CefMenuCreator::CefMenuCreator(CefBrowserHostImpl* browser) + : browser_(browser) { + model_ = new CefMenuModelImpl(this); +} + +CefMenuCreator::~CefMenuCreator() { + // The model may outlive the delegate if the context menu is visible when the + // application is closed. + model_->set_delegate(NULL); +} + +bool CefMenuCreator::IsShowingContextMenu() { + content::WebContents* web_contents = browser_->GetWebContents(); + if (!web_contents) + return false; + content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView(); + return (view && view->IsShowingContextMenu()); +} + +bool CefMenuCreator::CreateContextMenu( + const content::ContextMenuParams& params) { + if (!CreateRunner()) + return true; + + // The renderer may send the "show context menu" message multiple times, one + // for each right click mouse event it receives. Normally, this doesn't happen + // because mouse events are not forwarded once the context menu is showing. + // However, there's a race - the context menu may not yet be showing when + // the second mouse event arrives. In this case, |HandleContextMenu()| will + // get called multiple times - if so, don't create another context menu. + // TODO(asvitkine): Fix the renderer so that it doesn't do this. + if (IsShowingContextMenu()) + return true; + + params_ = params; + model_->Clear(); + + // Create the default menu model. + CreateDefaultModel(); + + // Give the client a chance to modify the model. + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = + client->GetContextMenuHandler(); + if (handler.get()) { + CefRefPtr paramsPtr( + new CefContextMenuParamsImpl(¶ms_)); + + handler->OnBeforeContextMenu(browser_, + browser_->GetFocusedFrame(), + paramsPtr.get(), + model_.get()); + + // Do not keep references to the parameters in the callback. + paramsPtr->Detach(NULL); + DCHECK(paramsPtr->HasOneRef()); + DCHECK(model_->VerifyRefCount()); + + // Menu is empty so notify the client and return. + if (model_->GetCount() == 0) { + MenuClosed(model_); + return true; + } + } + } + + return runner_->RunContextMenu(this); +} + +void CefMenuCreator::CancelContextMenu() { + if (IsShowingContextMenu()) + runner_->CancelContextMenu(); +} + +bool CefMenuCreator::CreateRunner() { + if (!runner_.get()) { + // Create the menu runner. +#if defined(OS_WIN) + runner_.reset(new CefMenuCreatorRunnerWin); +#elif defined(OS_MACOSX) + runner_.reset(new CefMenuCreatorRunnerMac); +#elif defined(OS_LINUX) + runner_.reset(new CefMenuCreatorRunnerLinux); +#else + // Need an implementation. + NOTREACHED(); +#endif + } + return (runner_.get() != NULL); +} + +void CefMenuCreator::ExecuteCommand(CefRefPtr source, + int command_id, + cef_event_flags_t event_flags) { + // Give the client a chance to handle the command. + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = + client->GetContextMenuHandler(); + if (handler.get()) { + CefRefPtr paramsPtr( + new CefContextMenuParamsImpl(¶ms_)); + + bool handled = handler->OnContextMenuCommand( + browser_, + browser_->GetFocusedFrame(), + paramsPtr.get(), + command_id, + event_flags); + + // Do not keep references to the parameters in the callback. + paramsPtr->Detach(NULL); + DCHECK(paramsPtr->HasOneRef()); + + if (handled) + return; + } + } + + // Execute the default command handling. + ExecuteDefaultCommand(command_id); +} + +void CefMenuCreator::MenuWillShow(CefRefPtr source) { + // May be called for sub-menus as well. + if (source.get() != model_.get()) + return; + + content::WebContents* web_contents = browser_->GetWebContents(); + if (!web_contents) + return; + + // Notify the host before showing the context menu. + content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView(); + if (view) + view->SetShowingContextMenu(true); +} + +void CefMenuCreator::MenuClosed(CefRefPtr source) { + // May be called for sub-menus as well. + if (source.get() != model_.get()) + return; + + // Notify the client. + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = + client->GetContextMenuHandler(); + if (handler.get()) { + handler->OnContextMenuDismissed(browser_, browser_->GetFocusedFrame()); + } + } + + if (IsShowingContextMenu()) { + // Notify the host after closing the context menu. + content::WebContents* web_contents = browser_->GetWebContents(); + content::RenderWidgetHostView* view = + web_contents->GetRenderWidgetHostView(); + if (view) + view->SetShowingContextMenu(false); + web_contents->NotifyContextMenuClosed(params_.custom_context); + } +} + +bool CefMenuCreator::FormatLabel(base::string16& label) { + return runner_->FormatLabel(label); +} + +void CefMenuCreator::CreateDefaultModel() { + if (params_.is_editable) { + // Editable node. + model_->AddItem(MENU_ID_UNDO, GetLabel(IDS_MENU_UNDO)); + model_->AddItem(MENU_ID_REDO, GetLabel(IDS_MENU_REDO)); + + model_->AddSeparator(); + model_->AddItem(MENU_ID_CUT, GetLabel(IDS_MENU_CUT)); + model_->AddItem(MENU_ID_COPY, GetLabel(IDS_MENU_COPY)); + model_->AddItem(MENU_ID_PASTE, GetLabel(IDS_MENU_PASTE)); + model_->AddItem(MENU_ID_DELETE, GetLabel(IDS_MENU_DELETE)); + + model_->AddSeparator(); + model_->AddItem(MENU_ID_SELECT_ALL, GetLabel(IDS_MENU_SELECT_ALL)); + + if (!(params_.edit_flags & CM_EDITFLAG_CAN_UNDO)) + model_->SetEnabled(MENU_ID_UNDO, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_REDO)) + model_->SetEnabled(MENU_ID_REDO, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_CUT)) + model_->SetEnabled(MENU_ID_CUT, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_COPY)) + model_->SetEnabled(MENU_ID_COPY, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_PASTE)) + model_->SetEnabled(MENU_ID_PASTE, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_DELETE)) + model_->SetEnabled(MENU_ID_DELETE, false); + if (!(params_.edit_flags & CM_EDITFLAG_CAN_SELECT_ALL)) + model_->SetEnabled(MENU_ID_SELECT_ALL, false); + } else if (!params_.selection_text.empty()) { + // Something is selected. + model_->AddItem(MENU_ID_COPY, GetLabel(IDS_MENU_COPY)); + } else if (!params_.page_url.is_empty() || !params_.frame_url.is_empty()) { + // Page or frame. + model_->AddItem(MENU_ID_BACK, GetLabel(IDS_MENU_BACK)); + model_->AddItem(MENU_ID_FORWARD, GetLabel(IDS_MENU_FORWARD)); + + model_->AddSeparator(); + model_->AddItem(MENU_ID_PRINT, GetLabel(IDS_MENU_PRINT)); + model_->AddItem(MENU_ID_VIEW_SOURCE, GetLabel(IDS_MENU_VIEW_SOURCE)); + + if (!browser_->CanGoBack()) + model_->SetEnabled(MENU_ID_BACK, false); + if (!browser_->CanGoForward()) + model_->SetEnabled(MENU_ID_FORWARD, false); + } +} + +void CefMenuCreator::ExecuteDefaultCommand(int command_id) { + switch (command_id) { + // Navigation. + case MENU_ID_BACK: + browser_->GoBack(); + break; + case MENU_ID_FORWARD: + browser_->GoForward(); + break; + case MENU_ID_RELOAD: + browser_->Reload(); + break; + case MENU_ID_RELOAD_NOCACHE: + browser_->ReloadIgnoreCache(); + break; + case MENU_ID_STOPLOAD: + browser_->StopLoad(); + break; + + // Editing. + case MENU_ID_UNDO: + browser_->GetFocusedFrame()->Undo(); + break; + case MENU_ID_REDO: + browser_->GetFocusedFrame()->Redo(); + break; + case MENU_ID_CUT: + browser_->GetFocusedFrame()->Cut(); + break; + case MENU_ID_COPY: + browser_->GetFocusedFrame()->Copy(); + break; + case MENU_ID_PASTE: + browser_->GetFocusedFrame()->Paste(); + break; + case MENU_ID_DELETE: + browser_->GetFocusedFrame()->Delete(); + break; + case MENU_ID_SELECT_ALL: + browser_->GetFocusedFrame()->SelectAll(); + break; + + // Miscellaneous. + case MENU_ID_FIND: + // TODO(cef): Implement. + NOTIMPLEMENTED(); + break; + case MENU_ID_PRINT: + browser_->Print(); + break; + case MENU_ID_VIEW_SOURCE: + browser_->GetFocusedFrame()->ViewSource(); + break; + + default: + break; + } +} diff --git a/libcef/browser/menu_creator.h b/libcef/browser/menu_creator.h new file mode 100644 index 000000000..2955fd439 --- /dev/null +++ b/libcef/browser/menu_creator.h @@ -0,0 +1,72 @@ +// 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_LIBCEF_BROWSER_MENU_MANAGER_H_ +#define CEF_LIBCEF_BROWSER_MENU_MANAGER_H_ +#pragma once + +#include "libcef/browser/menu_model_impl.h" + +#include "base/memory/scoped_ptr.h" +#include "content/public/common/context_menu_params.h" + +namespace content { +class RenderFrameHost; +}; + +class CefBrowserHostImpl; + +class CefMenuCreator : public CefMenuModelImpl::Delegate { + public: + // Used for OS-specific menu implementations. + class Runner { + public: + virtual ~Runner() {} + virtual bool RunContextMenu(CefMenuCreator* manager) =0; + virtual void CancelContextMenu() {} + virtual bool FormatLabel(base::string16& label) { return false; } + }; + + explicit CefMenuCreator(CefBrowserHostImpl* browser); + virtual ~CefMenuCreator(); + + // Returns true if the context menu is currently showing. + bool IsShowingContextMenu(); + + // Create the context menu. + bool CreateContextMenu(const content::ContextMenuParams& params); + void CancelContextMenu(); + + CefBrowserHostImpl* browser() { return browser_; } + ui::MenuModel* model() { return model_->model(); } + const content::ContextMenuParams& params() const { return params_; } + + private: + // Create the menu runner if it doesn't already exist. + bool CreateRunner(); + + // CefMenuModelImpl::Delegate methods. + virtual void ExecuteCommand(CefRefPtr source, + int command_id, + cef_event_flags_t event_flags) OVERRIDE; + virtual void MenuWillShow(CefRefPtr source) OVERRIDE; + virtual void MenuClosed(CefRefPtr source) OVERRIDE; + virtual bool FormatLabel(base::string16& label) OVERRIDE; + + // Create the default menu model. + void CreateDefaultModel(); + // Execute the default command handling. + void ExecuteDefaultCommand(int command_id); + + // CefBrowserHostImpl pointer is guaranteed to outlive this object. + CefBrowserHostImpl* browser_; + + CefRefPtr model_; + content::ContextMenuParams params_; + scoped_ptr runner_; + + DISALLOW_COPY_AND_ASSIGN(CefMenuCreator); +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_H_ diff --git a/libcef/browser/menu_creator_runner_linux.cc b/libcef/browser/menu_creator_runner_linux.cc new file mode 100644 index 000000000..6505d8789 --- /dev/null +++ b/libcef/browser/menu_creator_runner_linux.cc @@ -0,0 +1,77 @@ +// Copyright 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 "libcef/browser/menu_creator_runner_linux.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/window_x11.h" + +#include "base/strings/string_util.h" +#include "ui/aura/window.h" +#include "ui/gfx/point.h" + +// Used to silence warnings about unused variables. +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) +#endif + +CefMenuCreatorRunnerLinux::CefMenuCreatorRunnerLinux() { +} + +CefMenuCreatorRunnerLinux::~CefMenuCreatorRunnerLinux() { +} + +bool CefMenuCreatorRunnerLinux::RunContextMenu(CefMenuCreator* manager) { + menu_.reset(new views::MenuRunner(manager->model())); + + gfx::Point screen_point; + + if (manager->browser()->IsWindowless()) { + CefRefPtr client = manager->browser()->GetClient(); + if (!client.get()) + return false; + + CefRefPtr handler = client->GetRenderHandler(); + if (!handler.get()) + return false; + + int screenX = 0, screenY = 0; + if (!handler->GetScreenPoint(manager->browser(), + manager->params().x, manager->params().y, + screenX, screenY)) { + return false; + } + + screen_point = gfx::Point(screenX, screenY); + } else { + // We can't use aura::Window::GetBoundsInScreen on Linux because it will + // return bounds from DesktopWindowTreeHostX11 which in our case is relative + // to the parent window instead of the root window (screen). + const gfx::Rect& bounds_in_screen = + manager->browser()->window_x11()->GetBoundsInScreen(); + screen_point = gfx::Point(bounds_in_screen.x() + manager->params().x, + bounds_in_screen.y() + manager->params().y); + } + + views::MenuRunner::RunResult result = + menu_->RunMenuAt(manager->browser()->window_widget(), + NULL, gfx::Rect(screen_point, gfx::Size()), + views::MENU_ANCHOR_TOPRIGHT, + ui::MENU_SOURCE_NONE, + views::MenuRunner::CONTEXT_MENU); + UNUSED(result); + + return true; +} + +void CefMenuCreatorRunnerLinux::CancelContextMenu() { + if (menu_) + menu_->Cancel(); +} + +bool CefMenuCreatorRunnerLinux::FormatLabel(base::string16& label) { + // Remove the accelerator indicator (&) from label strings. + const char16 replace[] = {L'&', 0}; + return base::ReplaceChars(label, replace, base::string16(), &label); +} + diff --git a/libcef/browser/menu_creator_runner_linux.h b/libcef/browser/menu_creator_runner_linux.h new file mode 100644 index 000000000..eb28c5707 --- /dev/null +++ b/libcef/browser/menu_creator_runner_linux.h @@ -0,0 +1,28 @@ +// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ +#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ +#pragma once + +#include "libcef/browser/menu_creator.h" + +#include "base/memory/scoped_ptr.h" +#include "ui/views/controls/menu/menu_runner.h" + +class CefMenuCreatorRunnerLinux: public CefMenuCreator::Runner { + public: + CefMenuCreatorRunnerLinux(); + virtual ~CefMenuCreatorRunnerLinux(); + + // CefMemoryManager::Runner methods. + virtual bool RunContextMenu(CefMenuCreator* manager) OVERRIDE; + virtual void CancelContextMenu() OVERRIDE; + virtual bool FormatLabel(base::string16& label) OVERRIDE; + + private: + scoped_ptr menu_; +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_ diff --git a/libcef/browser/menu_creator_runner_mac.h b/libcef/browser/menu_creator_runner_mac.h new file mode 100644 index 000000000..d4ccc6d79 --- /dev/null +++ b/libcef/browser/menu_creator_runner_mac.h @@ -0,0 +1,29 @@ +// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_ +#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_ +#pragma once + +#include "libcef/browser/menu_creator.h" + +#if __OBJC__ +@class MenuController; +#else +class MenuController; +#endif + +class CefMenuCreatorRunnerMac : public CefMenuCreator::Runner { + public: + CefMenuCreatorRunnerMac(); + virtual ~CefMenuCreatorRunnerMac(); + + // CefMemoryManager::Runner methods. + virtual bool RunContextMenu(CefMenuCreator* manager) OVERRIDE; + + private: + MenuController* menu_controller_; +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_ diff --git a/libcef/browser/menu_creator_runner_mac.mm b/libcef/browser/menu_creator_runner_mac.mm new file mode 100644 index 000000000..151d80042 --- /dev/null +++ b/libcef/browser/menu_creator_runner_mac.mm @@ -0,0 +1,94 @@ +// 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 "libcef/browser/menu_creator_runner_mac.h" +#include "libcef/browser/browser_host_impl.h" + +#include "base/message_loop/message_loop.h" +#include "base/compiler_specific.h" +#import "base/mac/scoped_sending_event.h" +#import "ui/base/cocoa/menu_controller.h" + +CefMenuCreatorRunnerMac::CefMenuCreatorRunnerMac() + : menu_controller_(nil) { +} + +CefMenuCreatorRunnerMac::~CefMenuCreatorRunnerMac() { + if (menu_controller_ != nil) + [menu_controller_ release]; +} + +bool CefMenuCreatorRunnerMac::RunContextMenu(CefMenuCreator* manager) { + // Create a menu controller based on the model. + if (menu_controller_ != nil) + [menu_controller_ release]; + menu_controller_ = + [[MenuController alloc] initWithModel:manager->model() + useWithPopUpButtonCell:NO]; + + NSView* parent_view = + manager->browser()->GetWebContents()->GetContentNativeView(); + + // Synthesize an event for the click, as there is no certainty that + // [NSApp currentEvent] will return a valid event. + NSEvent* currentEvent = [NSApp currentEvent]; + NSWindow* window = [parent_view window]; + + NSPoint position = [window mouseLocationOutsideOfEventStream]; + + NSTimeInterval eventTime = [currentEvent timestamp]; + NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown + location:position + modifierFlags:NSRightMouseDownMask + timestamp:eventTime + windowNumber:[window windowNumber] + context:nil + eventNumber:0 + clickCount:1 + pressure:1.0]; + + { + // Make sure events can be pumped while the menu is up. + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + + // One of the events that could be pumped is |window.close()|. + // User-initiated event-tracking loops protect against this by + // setting flags in -[CrApplication sendEvent:], but since + // web-content menus are initiated by IPC message the setup has to + // be done manually. + base::mac::ScopedSendingEvent sendingEventScoper; + + // Show the menu. Blocks until the menu is dismissed. + if (manager->browser()->IsWindowless()) { + // Showing the menu in OSR is pretty much self contained, only using + // the initialized menu_controller_ in this function, and the scoped + // variables in this block. + int screenX = 0, screenY = 0; + CefRefPtr handler = + manager->browser()->GetClient()->GetRenderHandler(); + if (!handler->GetScreenPoint(manager->browser(), + manager->params().x, manager->params().y, + screenX, screenY)) { + return false; + } + + // Don't show the menu unless there is a parent native window to tie it to + if (!manager->browser()->GetWindowHandle()) + return false; + + NSPoint screen_position = + NSPointFromCGPoint(gfx::Point(screenX, screenY).ToCGPoint()); + [[menu_controller_ menu] popUpMenuPositioningItem:nil + atLocation:screen_position + inView:nil]; + } else { + [NSMenu popUpContextMenu:[menu_controller_ menu] + withEvent:clickEvent + forView:parent_view]; + } + } + + return true; +} diff --git a/libcef/browser/menu_creator_runner_win.cc b/libcef/browser/menu_creator_runner_win.cc new file mode 100644 index 000000000..669e23bf7 --- /dev/null +++ b/libcef/browser/menu_creator_runner_win.cc @@ -0,0 +1,55 @@ +// 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 "libcef/browser/menu_creator_runner_win.h" +#include "libcef/browser/browser_host_impl.h" + +#include "base/message_loop/message_loop.h" +#include "ui/aura/window.h" +#include "ui/gfx/point.h" +#include "ui/views/controls/menu/menu_2.h" + +CefMenuCreatorRunnerWin::CefMenuCreatorRunnerWin() { +} + +bool CefMenuCreatorRunnerWin::RunContextMenu(CefMenuCreator* manager) { + // Create a menu based on the model. + menu_.reset(new views::NativeMenuWin(manager->model(), NULL)); + menu_->Rebuild(NULL); + + // Make sure events can be pumped while the menu is up. + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + + gfx::Point screen_point; + + if (manager->browser()->IsWindowless()) { + CefRefPtr client = manager->browser()->GetClient(); + if (!client.get()) + return false; + + CefRefPtr handler = client->GetRenderHandler(); + if (!handler.get()) + return false; + + int screenX = 0, screenY = 0; + if (!handler->GetScreenPoint(manager->browser(), + manager->params().x, manager->params().y, + screenX, screenY)) { + return false; + } + + screen_point = gfx::Point(screenX, screenY); + } else { + aura::Window* window = manager->browser()->GetContentView(); + const gfx::Rect& bounds_in_screen = window->GetBoundsInScreen(); + screen_point = gfx::Point(bounds_in_screen.x() + manager->params().x, + bounds_in_screen.y() + manager->params().y); + } + + // Show the menu. Blocks until the menu is dismissed. + menu_->RunMenuAt(screen_point, views::Menu2::ALIGN_TOPLEFT); + + return true; +} diff --git a/libcef/browser/menu_creator_runner_win.h b/libcef/browser/menu_creator_runner_win.h new file mode 100644 index 000000000..c78e953b6 --- /dev/null +++ b/libcef/browser/menu_creator_runner_win.h @@ -0,0 +1,25 @@ +// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_ +#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_ +#pragma once + +#include "libcef/browser/menu_creator.h" + +#include "base/memory/scoped_ptr.h" +#include "ui/views/controls/menu/native_menu_win.h" + +class CefMenuCreatorRunnerWin : public CefMenuCreator::Runner { + public: + CefMenuCreatorRunnerWin(); + + // CefMemoryManager::Runner methods. + virtual bool RunContextMenu(CefMenuCreator* manager) OVERRIDE; + + private: + scoped_ptr menu_; +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_ diff --git a/libcef/browser/menu_model_impl.cc b/libcef/browser/menu_model_impl.cc new file mode 100644 index 000000000..babe2509b --- /dev/null +++ b/libcef/browser/menu_model_impl.cc @@ -0,0 +1,706 @@ +// Copyright (c) 2012 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 "libcef/browser/menu_model_impl.h" + +#include + +#include "base/bind.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "ui/base/accelerators/accelerator.h" + +namespace { + +const int kSeparatorId = -1; + +// A simple MenuModel implementation that delegates to CefMenuModelImpl. +class CefSimpleMenuModel : public ui::MenuModel { + public: + // The Delegate can be NULL, though if it is items can't be checked or + // disabled. + explicit CefSimpleMenuModel(CefMenuModelImpl* impl) + : impl_(impl), + menu_model_delegate_(NULL) { + } + + virtual ~CefSimpleMenuModel() { + } + + // MenuModel methods. + virtual bool HasIcons() const OVERRIDE { + return false; + } + + virtual int GetItemCount() const OVERRIDE { + return impl_->GetCount(); + } + + virtual ItemType GetTypeAt(int index) const OVERRIDE { + switch (impl_->GetTypeAt(index)) { + case MENUITEMTYPE_COMMAND: + return TYPE_COMMAND; + case MENUITEMTYPE_CHECK: + return TYPE_CHECK; + case MENUITEMTYPE_RADIO: + return TYPE_RADIO; + case MENUITEMTYPE_SEPARATOR: + return TYPE_SEPARATOR; + case MENUITEMTYPE_SUBMENU: + return TYPE_SUBMENU; + default: + NOTREACHED(); + return TYPE_COMMAND; + } + } + + virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE { + return ui::NORMAL_SEPARATOR; + } + + virtual int GetCommandIdAt(int index) const OVERRIDE { + return impl_->GetCommandIdAt(index); + } + + virtual base::string16 GetLabelAt(int index) const OVERRIDE { + return impl_->GetFormattedLabelAt(index); + } + + virtual bool IsItemDynamicAt(int index) const OVERRIDE { + return false; + } + + virtual bool GetAcceleratorAt(int index, + ui::Accelerator* accelerator) const OVERRIDE { + int key_code = 0; + bool shift_pressed = false; + bool ctrl_pressed = false; + bool alt_pressed = false; + if (impl_->GetAcceleratorAt(index, key_code, shift_pressed, ctrl_pressed, + alt_pressed)) { + int modifiers = 0; + if (shift_pressed) + modifiers |= ui::EF_SHIFT_DOWN; + if (ctrl_pressed) + modifiers |= ui::EF_CONTROL_DOWN; + if (alt_pressed) + modifiers |= ui::EF_ALT_DOWN; + + *accelerator = ui::Accelerator(static_cast(key_code), + modifiers); + return true; + } + return false; + } + + virtual bool IsItemCheckedAt(int index) const OVERRIDE { + return impl_->IsCheckedAt(index); + } + + virtual int GetGroupIdAt(int index) const OVERRIDE { + return impl_->GetGroupIdAt(index); + } + + virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE { + return false; + } + + virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt( + int index) const OVERRIDE { + return NULL; + } + + virtual bool IsEnabledAt(int index) const OVERRIDE { + return impl_->IsEnabledAt(index); + } + + virtual bool IsVisibleAt(int index) const OVERRIDE { + return impl_->IsVisibleAt(index); + } + + virtual void HighlightChangedTo(int index) OVERRIDE { + } + + virtual void ActivatedAt(int index) OVERRIDE { + ActivatedAt(index, 0); + } + + virtual void ActivatedAt(int index, int event_flags) OVERRIDE { + impl_->ActivatedAt(index, static_cast(event_flags)); + } + + virtual MenuModel* GetSubmenuModelAt(int index) const OVERRIDE { + CefRefPtr submenu = impl_->GetSubMenuAt(index); + if (submenu.get()) + return static_cast(submenu.get())->model(); + return NULL; + } + + virtual void MenuWillShow() OVERRIDE { + impl_->MenuWillShow(); + } + + virtual void MenuClosed() OVERRIDE { + impl_->MenuClosed(); + } + + virtual void SetMenuModelDelegate( + ui::MenuModelDelegate* menu_model_delegate) OVERRIDE { + menu_model_delegate_ = menu_model_delegate; + } + + virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE { + return menu_model_delegate_; + } + + private: + CefMenuModelImpl* impl_; + ui::MenuModelDelegate* menu_model_delegate_; + + DISALLOW_COPY_AND_ASSIGN(CefSimpleMenuModel); +}; + +} // namespace + + +struct CefMenuModelImpl::Item { + Item(cef_menu_item_type_t type, + int command_id, + const CefString& label, + int group_id) + : type_(type), + command_id_(command_id), + label_(label), + group_id_(group_id), + enabled_(true), + visible_(true), + checked_(false), + has_accelerator_(false), + key_code_(0), + shift_pressed_(false), + ctrl_pressed_(false), + alt_pressed_(false) { + } + + // Basic information. + cef_menu_item_type_t type_; + int command_id_; + CefString label_; + int group_id_; + CefRefPtr submenu_; + + // State information. + bool enabled_; + bool visible_; + bool checked_; + + // Accelerator information. + bool has_accelerator_; + int key_code_; + bool shift_pressed_; + bool ctrl_pressed_; + bool alt_pressed_; +}; + + +CefMenuModelImpl::CefMenuModelImpl(Delegate* delegate) + : supported_thread_id_(base::PlatformThread::CurrentId()), + delegate_(delegate) { + model_.reset(new CefSimpleMenuModel(this)); +} + +CefMenuModelImpl::~CefMenuModelImpl() { +} + +bool CefMenuModelImpl::Clear() { + if (!VerifyContext()) + return false; + + items_.clear(); + return true; +} + +int CefMenuModelImpl::GetCount() { + if (!VerifyContext()) + return 0; + + return static_cast(items_.size()); +} + +bool CefMenuModelImpl::AddSeparator() { + if (!VerifyContext()) + return false; + + AppendItem(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1)); + return true; +} + +bool CefMenuModelImpl::AddItem(int command_id, const CefString& label) { + if (!VerifyContext()) + return false; + + AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, -1)); + return true; +} + +bool CefMenuModelImpl::AddCheckItem(int command_id, const CefString& label) { + if (!VerifyContext()) + return false; + + AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, -1)); + return true; +} + +bool CefMenuModelImpl::AddRadioItem(int command_id, const CefString& label, + int group_id) { + if (!VerifyContext()) + return false; + + AppendItem(Item(MENUITEMTYPE_RADIO, command_id, label, group_id)); + return true; +} + +CefRefPtr CefMenuModelImpl::AddSubMenu(int command_id, + const CefString& label) { + if (!VerifyContext()) + return NULL; + + Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); + item.submenu_ = new CefMenuModelImpl(delegate_); + AppendItem(item); + return item.submenu_.get(); +} + +bool CefMenuModelImpl::InsertSeparatorAt(int index) { + if (!VerifyContext()) + return false; + + InsertItemAt(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1), + index); + return true; +} + +bool CefMenuModelImpl::InsertItemAt(int index, int command_id, + const CefString& label) { + if (!VerifyContext()) + return false; + + InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, -1), index); + return true; +} + +bool CefMenuModelImpl::InsertCheckItemAt(int index, int command_id, + const CefString& label) { + if (!VerifyContext()) + return false; + + InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, -1), index); + return true; +} + +bool CefMenuModelImpl::InsertRadioItemAt(int index, int command_id, + const CefString& label, int group_id) { + if (!VerifyContext()) + return false; + + InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, -1), index); + return true; +} + +CefRefPtr CefMenuModelImpl::InsertSubMenuAt( + int index, int command_id, const CefString& label) { + if (!VerifyContext()) + return NULL; + + Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); + item.submenu_ = new CefMenuModelImpl(delegate_); + InsertItemAt(item, index); + return item.submenu_.get(); +} + +bool CefMenuModelImpl::Remove(int command_id) { + return RemoveAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::RemoveAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_.erase(items_.begin()+index); + return true; + } + return false; +} + +int CefMenuModelImpl::GetIndexOf(int command_id) { + if (!VerifyContext()) + return -1; + + for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) { + if ((*i).command_id_ == command_id) { + return static_cast(std::distance(items_.begin(), i)); + } + } + return -1; +} + +int CefMenuModelImpl::GetCommandIdAt(int index) { + if (!VerifyContext()) + return -1; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].command_id_; + return -1; +} + +bool CefMenuModelImpl::SetCommandIdAt(int index, int command_id) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].command_id_ = command_id; + return true; + } + return false; +} + +CefString CefMenuModelImpl::GetLabel(int command_id) { + return GetLabelAt(GetIndexOf(command_id)); +} + +CefString CefMenuModelImpl::GetLabelAt(int index) { + if (!VerifyContext()) + return CefString(); + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].label_; + return CefString(); +} + +bool CefMenuModelImpl::SetLabel(int command_id, const CefString& label) { + return SetLabelAt(GetIndexOf(command_id), label); +} + +bool CefMenuModelImpl::SetLabelAt(int index, const CefString& label) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].label_ = label; + return true; + } + return false; +} + +CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetType(int command_id) { + return GetTypeAt(GetIndexOf(command_id)); +} + +CefMenuModelImpl::MenuItemType CefMenuModelImpl::GetTypeAt(int index) { + if (!VerifyContext()) + return MENUITEMTYPE_NONE; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].type_; + return MENUITEMTYPE_NONE; +} + +int CefMenuModelImpl::GetGroupId(int command_id) { + return GetGroupIdAt(GetIndexOf(command_id)); +} + +int CefMenuModelImpl::GetGroupIdAt(int index) { + if (!VerifyContext()) + return -1; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].group_id_; + return -1; +} + +bool CefMenuModelImpl::SetGroupId(int command_id, int group_id) { + return SetGroupIdAt(GetIndexOf(command_id), group_id); +} + +bool CefMenuModelImpl::SetGroupIdAt(int index, int group_id) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].group_id_ = group_id; + return true; + } + return false; +} + +CefRefPtr CefMenuModelImpl::GetSubMenu(int command_id) { + return GetSubMenuAt(GetIndexOf(command_id)); +} + +CefRefPtr CefMenuModelImpl::GetSubMenuAt(int index) { + if (!VerifyContext()) + return NULL; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].submenu_.get(); + return NULL; +} + +bool CefMenuModelImpl::IsVisible(int command_id) { + return IsVisibleAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::IsVisibleAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].visible_; + return false; +} + +bool CefMenuModelImpl::SetVisible(int command_id, bool visible) { + return SetVisibleAt(GetIndexOf(command_id), visible); +} + +bool CefMenuModelImpl::SetVisibleAt(int index, bool visible) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].visible_ = visible; + return true; + } + return false; +} + +bool CefMenuModelImpl::IsEnabled(int command_id) { + return IsEnabledAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::IsEnabledAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].enabled_; + return false; +} + +bool CefMenuModelImpl::SetEnabled(int command_id, bool enabled) { + return SetEnabledAt(GetIndexOf(command_id), enabled); +} + +bool CefMenuModelImpl::SetEnabledAt(int index, bool enabled) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].enabled_ = enabled; + return true; + } + return false; +} + +bool CefMenuModelImpl::IsChecked(int command_id) { + return IsCheckedAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::IsCheckedAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].checked_; + return false; +} + +bool CefMenuModelImpl::SetChecked(int command_id, bool checked) { + return SetCheckedAt(GetIndexOf(command_id), checked); +} + +bool CefMenuModelImpl::SetCheckedAt(int index, bool checked) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + items_[index].checked_ = checked; + return true; + } + return false; +} + +bool CefMenuModelImpl::HasAccelerator(int command_id) { + return HasAcceleratorAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::HasAcceleratorAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) + return items_[index].has_accelerator_; + return false; +} + +bool CefMenuModelImpl::SetAccelerator(int command_id, int key_code, + bool shift_pressed, bool ctrl_pressed, + bool alt_pressed) { + return SetAcceleratorAt(GetIndexOf(command_id), key_code, shift_pressed, + ctrl_pressed, alt_pressed); +} + +bool CefMenuModelImpl::SetAcceleratorAt(int index, int key_code, + bool shift_pressed, bool ctrl_pressed, + bool alt_pressed) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + Item& item = items_[index]; + item.has_accelerator_ = true; + item.key_code_ = key_code; + item.shift_pressed_ = shift_pressed; + item.ctrl_pressed_ = ctrl_pressed; + item.alt_pressed_ = alt_pressed; + return true; + } + return false; +} + +bool CefMenuModelImpl::RemoveAccelerator(int command_id) { + return RemoveAcceleratorAt(GetIndexOf(command_id)); +} + +bool CefMenuModelImpl::RemoveAcceleratorAt(int index) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + Item& item = items_[index]; + if (item.has_accelerator_) { + item.has_accelerator_ = false; + item.key_code_ = 0; + item.shift_pressed_ = false; + item.ctrl_pressed_ = false; + item.alt_pressed_ = false; + } + return true; + } + return false; +} + +bool CefMenuModelImpl::GetAccelerator(int command_id, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, + bool& alt_pressed) { + return GetAcceleratorAt(GetIndexOf(command_id), key_code, shift_pressed, + ctrl_pressed, alt_pressed); +} + +bool CefMenuModelImpl::GetAcceleratorAt(int index, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, + bool& alt_pressed) { + if (!VerifyContext()) + return false; + + if (index >= 0 && index < static_cast(items_.size())) { + const Item& item = items_[index]; + if (item.has_accelerator_) { + key_code = item.key_code_; + shift_pressed = item.shift_pressed_; + ctrl_pressed = item.ctrl_pressed_; + alt_pressed = item.alt_pressed_; + return true; + } + } + return false; +} + +void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) { + if (VerifyContext() && delegate_) + delegate_->ExecuteCommand(this, GetCommandIdAt(index), event_flags); +} + +void CefMenuModelImpl::MenuWillShow() { + if (VerifyContext() && delegate_) + delegate_->MenuWillShow(this); +} + +void CefMenuModelImpl::MenuClosed() { + if (!VerifyContext()) + return; + + // Due to how menus work on the different platforms, ActivatedAt will be + // called after this. It's more convenient for the delegate to be called + // afterwards, though, so post a task. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&CefMenuModelImpl::OnMenuClosed, this)); +} + +base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) { + base::string16 label = GetLabelAt(index).ToString16(); + delegate_->FormatLabel(label); + return label; +} + +bool CefMenuModelImpl::VerifyRefCount() { + if (!VerifyContext()) + return false; + + if (!HasOneRef()) + return false; + + for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) { + if ((*i).submenu_.get()) { + if (!(*i).submenu_->VerifyRefCount()) + return false; + } + } + + return true; +} + +void CefMenuModelImpl::AppendItem(const Item& item) { + ValidateItem(item); + items_.push_back(item); +} + +void CefMenuModelImpl::InsertItemAt(const Item& item, int index) { + // Sanitize the index. + if (index < 0) + index = 0; + else if (index > static_cast(items_.size())) + index = items_.size(); + + ValidateItem(item); + items_.insert(items_.begin() + index, item); +} + +void CefMenuModelImpl::ValidateItem(const Item& item) { +#ifndef NDEBUG + if (item.type_ == MENUITEMTYPE_SEPARATOR) { + DCHECK_EQ(item.command_id_, kSeparatorId); + } else { + DCHECK_GE(item.command_id_, 0); + } +#endif // NDEBUG +} + +void CefMenuModelImpl::OnMenuClosed() { + if (delegate_) + delegate_->MenuClosed(this); +} + +bool CefMenuModelImpl::VerifyContext() { + if (base::PlatformThread::CurrentId() != supported_thread_id_) { + // This object should only be accessed from the thread that created it. + NOTREACHED(); + return false; + } + + return true; +} diff --git a/libcef/browser/menu_model_impl.h b/libcef/browser/menu_model_impl.h new file mode 100644 index 000000000..62aa7ebff --- /dev/null +++ b/libcef/browser/menu_model_impl.h @@ -0,0 +1,144 @@ +// Copyright (c) 2012 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_LIBCEF_BROWSER_MENU_MODEL_IMPL_H_ +#define CEF_LIBCEF_BROWSER_MENU_MODEL_IMPL_H_ +#pragma once + +#include + +#include "include/cef_menu_model.h" + +#include "base/memory/scoped_ptr.h" +#include "base/threading/platform_thread.h" +#include "ui/base/models/menu_model.h" + +class CefMenuModelImpl : public CefMenuModel { + public: + class Delegate { + public: + // Perform the action associated with the specified |command_id| and + // optional |event_flags|. + virtual void ExecuteCommand(CefRefPtr source, + int command_id, + cef_event_flags_t event_flags) =0; + + // Notifies the delegate that the menu is about to show. + virtual void MenuWillShow(CefRefPtr source) =0; + + // Notifies the delegate that the menu has closed. + virtual void MenuClosed(CefRefPtr source) =0; + + // Allows the delegate to modify a menu item label before it's displayed. + virtual bool FormatLabel(base::string16& label) =0; + + protected: + virtual ~Delegate() {} + }; + + // The delegate must outlive this class. + explicit CefMenuModelImpl(Delegate* delegate); + virtual ~CefMenuModelImpl(); + + // CefMenuModel methods. + virtual bool Clear() OVERRIDE; + virtual int GetCount() OVERRIDE; + virtual bool AddSeparator() OVERRIDE; + virtual bool AddItem(int command_id, const CefString& label) OVERRIDE; + virtual bool AddCheckItem(int command_id, const CefString& label) OVERRIDE; + virtual bool AddRadioItem(int command_id, const CefString& label, + int group_id) OVERRIDE; + virtual CefRefPtr AddSubMenu(int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertSeparatorAt(int index) OVERRIDE; + virtual bool InsertItemAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertCheckItemAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertRadioItemAt(int index, int command_id, + const CefString& label, int group_id) OVERRIDE; + virtual CefRefPtr InsertSubMenuAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool Remove(int command_id) OVERRIDE; + virtual bool RemoveAt(int index) OVERRIDE; + virtual int GetIndexOf(int command_id) OVERRIDE; + virtual int GetCommandIdAt(int index) OVERRIDE; + virtual bool SetCommandIdAt(int index, int command_id) OVERRIDE; + virtual CefString GetLabel(int command_id) OVERRIDE; + virtual CefString GetLabelAt(int index) OVERRIDE; + virtual bool SetLabel(int command_id, const CefString& label) OVERRIDE; + virtual bool SetLabelAt(int index, const CefString& label) OVERRIDE; + virtual MenuItemType GetType(int command_id) OVERRIDE; + virtual MenuItemType GetTypeAt(int index) OVERRIDE; + virtual int GetGroupId(int command_id) OVERRIDE; + virtual int GetGroupIdAt(int index) OVERRIDE; + virtual bool SetGroupId(int command_id, int group_id) OVERRIDE; + virtual bool SetGroupIdAt(int index, int group_id) OVERRIDE; + virtual CefRefPtr GetSubMenu(int command_id) OVERRIDE; + virtual CefRefPtr GetSubMenuAt(int index) OVERRIDE; + virtual bool IsVisible(int command_id) OVERRIDE; + virtual bool IsVisibleAt(int index) OVERRIDE; + virtual bool SetVisible(int command_id, bool visible) OVERRIDE; + virtual bool SetVisibleAt(int index, bool visible) OVERRIDE; + virtual bool IsEnabled(int command_id) OVERRIDE; + virtual bool IsEnabledAt(int index) OVERRIDE; + virtual bool SetEnabled(int command_id, bool enabled) OVERRIDE; + virtual bool SetEnabledAt(int index, bool enabled) OVERRIDE; + virtual bool IsChecked(int command_id) OVERRIDE; + virtual bool IsCheckedAt(int index) OVERRIDE; + virtual bool SetChecked(int command_id, bool checked) OVERRIDE; + virtual bool SetCheckedAt(int index, bool checked) OVERRIDE; + virtual bool HasAccelerator(int command_id) OVERRIDE; + virtual bool HasAcceleratorAt(int index) OVERRIDE; + virtual bool SetAccelerator(int command_id, int key_code, bool shift_pressed, + bool ctrl_pressed, bool alt_pressed) OVERRIDE; + virtual bool SetAcceleratorAt(int index, int key_code, bool shift_pressed, + bool ctrl_pressed, bool alt_pressed) OVERRIDE; + virtual bool RemoveAccelerator(int command_id) OVERRIDE; + virtual bool RemoveAcceleratorAt(int index) OVERRIDE; + virtual bool GetAccelerator(int command_id, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; + virtual bool GetAcceleratorAt(int index, int& key_code, bool& shift_pressed, + bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; + + // Callbacks from the ui::MenuModel implementation. + void ActivatedAt(int index, cef_event_flags_t event_flags); + void MenuWillShow(); + void MenuClosed(); + base::string16 GetFormattedLabelAt(int index); + + // Verify that only a single reference exists to all CefMenuModelImpl objects. + bool VerifyRefCount(); + + ui::MenuModel* model() { return model_.get(); } + Delegate* delegate() { return delegate_; } + void set_delegate(Delegate* delegate) { delegate_ = NULL; } + + private: + struct Item; + + typedef std::vector ItemVector; + + // Functions for inserting items into |items_|. + void AppendItem(const Item& item); + void InsertItemAt(const Item& item, int index); + void ValidateItem(const Item& item); + + // Notify the delegate that the menu is closed. + void OnMenuClosed(); + + // Verify that the object is being accessed from the correct thread. + bool VerifyContext(); + + base::PlatformThreadId supported_thread_id_; + Delegate* delegate_; + ItemVector items_; + scoped_ptr model_; + + IMPLEMENT_REFCOUNTING(CefMenuModelImpl); + DISALLOW_COPY_AND_ASSIGN(CefMenuModelImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_MENU_MODEL_IMPL_H_ diff --git a/libcef/browser/navigate_params.cc b/libcef/browser/navigate_params.cc new file mode 100644 index 000000000..85222a4d1 --- /dev/null +++ b/libcef/browser/navigate_params.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2012 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 "libcef/browser/navigate_params.h" + +CefNavigateParams::CefNavigateParams( + const GURL& a_url, + content::PageTransition a_transition) + : url(a_url), + frame_id(-1), + disposition(CURRENT_TAB), + transition(a_transition), + is_renderer_initiated(false), + user_gesture(true) { +} + +CefNavigateParams::~CefNavigateParams() { +} diff --git a/libcef/browser/navigate_params.h b/libcef/browser/navigate_params.h new file mode 100644 index 000000000..b5058b106 --- /dev/null +++ b/libcef/browser/navigate_params.h @@ -0,0 +1,85 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_ +#define CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_ +#pragma once + +#include + +#include "libcef/common/upload_data.h" + +#include "content/public/browser/global_request_id.h" +#include "content/public/common/page_transition_types.h" +#include "content/public/common/referrer.h" +#include "ui/base/window_open_disposition.h" +#include "url/gurl.h" + +// Parameters that tell CefBrowserHostImpl::Navigate() what to do. +struct CefNavigateParams { + CefNavigateParams(const GURL& a_url, + content::PageTransition a_transition); + ~CefNavigateParams(); + + // The following parameters are sent to the renderer via CefMsg_LoadRequest. + // --------------------------------------------------------------------------- + + // Request method. + std::string method; + + // The URL/referrer to be loaded. + GURL url; + content::Referrer referrer; + + // The frame that the request should be loaded in or -1 to use the main frame. + int64 frame_id; + + // Usually the URL of the document in the top-level window, which may be + // checked by the third-party cookie blocking policy. Leaving it empty may + // lead to undesired cookie blocking. Third-party cookie blocking can be + // bypassed by setting first_party_for_cookies = url, but this should ideally + // only be done if there really is no way to determine the correct value. + GURL first_party_for_cookies; + + // Additional HTTP request headers. + std::string headers; + + // net::URLRequest load flags (0 by default). + int load_flags; + + // Upload data (may be NULL). + scoped_refptr upload_data; + + + // The following parameters are used to define browser behavior when servicing + // the navigation request. + // --------------------------------------------------------------------------- + + // The disposition requested by the navigation source. Default is CURRENT_TAB. + WindowOpenDisposition disposition; + + // The transition type of the navigation. + content::PageTransition transition; + + // Whether this navigation was initiated by the renderer process. + bool is_renderer_initiated; + + // If non-empty, the new tab contents encoding is overriden by this value. + std::string override_encoding; + + // If false then the navigation was not initiated by a user gesture. Default + // is true. + bool user_gesture; + + // Refers to a navigation that was parked in the browser in order to be + // transferred to another RVH. Only used in case of a redirection of a request + // to a different site that created a new RVH. + content::GlobalRequestID transferred_global_request_id; + + private: + CefNavigateParams(); +}; + +#endif // CEF_LIBCEF_BROWSER_NAVIGATE_PARAMS_H_ diff --git a/libcef/browser/origin_whitelist_impl.cc b/libcef/browser/origin_whitelist_impl.cc new file mode 100644 index 000000000..209cb7dc7 --- /dev/null +++ b/libcef/browser/origin_whitelist_impl.cc @@ -0,0 +1,288 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "libcef/browser/origin_whitelist_impl.h" + +#include +#include + +#include "include/cef_origin_whitelist.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/cef_messages.h" + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/synchronization/lock.h" +#include "content/public/browser/render_process_host.h" +#include "url/gurl.h" + +namespace { + +// Class that manages cross-origin whitelist registrations. +class CefOriginWhitelistManager { + public: + CefOriginWhitelistManager() {} + + // Retrieve the singleton instance. + static CefOriginWhitelistManager* GetInstance(); + + bool AddOriginEntry(const std::string& source_origin, + const std::string& target_protocol, + const std::string& target_domain, + bool allow_target_subdomains) { + Cef_CrossOriginWhiteListEntry_Params info; + info.source_origin = source_origin; + info.target_protocol = target_protocol; + info.target_domain = target_domain; + info.allow_target_subdomains = allow_target_subdomains; + + { + base::AutoLock lock_scope(lock_); + + // Verify that the origin entry doesn't already exist. + OriginList::const_iterator it = origin_list_.begin(); + for (; it != origin_list_.end(); ++it) { + if (IsEqual(*it, info)) + return false; + } + + origin_list_.push_back(info); + } + + SendModifyCrossOriginWhitelistEntry(true, info); + return true; + } + + bool RemoveOriginEntry(const std::string& source_origin, + const std::string& target_protocol, + const std::string& target_domain, + bool allow_target_subdomains) { + Cef_CrossOriginWhiteListEntry_Params info; + info.source_origin = source_origin; + info.target_protocol = target_protocol; + info.target_domain = target_domain; + info.allow_target_subdomains = allow_target_subdomains; + + bool found = false; + + { + base::AutoLock lock_scope(lock_); + + OriginList::iterator it = origin_list_.begin(); + for (; it != origin_list_.end(); ++it) { + if (IsEqual(*it, info)) { + origin_list_.erase(it); + found = true; + break; + } + } + } + + if (!found) + return false; + + SendModifyCrossOriginWhitelistEntry(false, info); + return true; + } + + void ClearOrigins() { + { + base::AutoLock lock_scope(lock_); + origin_list_.clear(); + } + + SendClearCrossOriginWhitelist(); + } + + void GetCrossOriginWhitelistEntries( + std::vector* entries) { + base::AutoLock lock_scope(lock_); + + if (origin_list_.empty()) + return; + entries->insert(entries->end(), origin_list_.begin(), origin_list_.end()); + } + + private: + // Send the modify cross-origin whitelist entry message to all currently + // existing hosts. + static void SendModifyCrossOriginWhitelistEntry( + bool add, + Cef_CrossOriginWhiteListEntry_Params& params) { + CEF_REQUIRE_UIT(); + + content::RenderProcessHost::iterator i( + content::RenderProcessHost::AllHostsIterator()); + for (; !i.IsAtEnd(); i.Advance()) { + i.GetCurrentValue()->Send( + new CefProcessMsg_ModifyCrossOriginWhitelistEntry(add, params)); + } + } + + // Send the clear cross-origin whitelists message to all currently existing + // hosts. + static void SendClearCrossOriginWhitelist() { + CEF_REQUIRE_UIT(); + + content::RenderProcessHost::iterator i( + content::RenderProcessHost::AllHostsIterator()); + for (; !i.IsAtEnd(); i.Advance()) { + i.GetCurrentValue()->Send(new CefProcessMsg_ClearCrossOriginWhitelist); + } + } + + static bool IsEqual(const Cef_CrossOriginWhiteListEntry_Params& param1, + const Cef_CrossOriginWhiteListEntry_Params& param2) { + return (param1.source_origin == param2.source_origin && + param1.target_protocol == param2.target_protocol && + param1.target_domain == param2.target_domain && + param1.allow_target_subdomains == param2.allow_target_subdomains); + } + + base::Lock lock_; + + // List of registered origins. Access must be protected by |lock_|. + typedef std::vector OriginList; + OriginList origin_list_; + + DISALLOW_EVIL_CONSTRUCTORS(CefOriginWhitelistManager); +}; + +base::LazyInstance g_manager = + LAZY_INSTANCE_INITIALIZER; + +CefOriginWhitelistManager* CefOriginWhitelistManager::GetInstance() { + return g_manager.Pointer(); +} + +bool IsMatch(const GURL& source_origin, + const GURL& target_origin, + const Cef_CrossOriginWhiteListEntry_Params& param) { + if (source_origin.GetOrigin() != GURL(param.source_origin)) { + // Source origin does not match. + return false; + } + + if (target_origin.scheme() != param.target_protocol) { + // Target scheme does not match. + return false; + } + + if (param.allow_target_subdomains) { + if (param.target_domain.empty()) { + // Any domain will match. + return true; + } else { + // Match sub-domains. + return target_origin.DomainIs(param.target_domain.c_str()); + } + } else { + // Match full domain. + return (target_origin.host() == param.target_domain); + } +} + +} // namespace + +bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin, + const CefString& target_protocol, + const CefString& target_domain, + bool allow_target_subdomains) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED(); + return false; + } + + std::string source_url = source_origin; + GURL gurl = GURL(source_url); + if (gurl.is_empty() || !gurl.is_valid()) { + NOTREACHED() << "Invalid source_origin URL: " << source_url; + return false; + } + + if (CEF_CURRENTLY_ON_UIT()) { + return CefOriginWhitelistManager::GetInstance()->AddOriginEntry( + source_origin, target_protocol, target_domain, allow_target_subdomains); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(&CefAddCrossOriginWhitelistEntry), + source_origin, target_protocol, target_domain, + allow_target_subdomains)); + } + + return true; +} + +bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin, + const CefString& target_protocol, + const CefString& target_domain, + bool allow_target_subdomains) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED(); + return false; + } + + std::string source_url = source_origin; + GURL gurl = GURL(source_url); + if (gurl.is_empty() || !gurl.is_valid()) { + NOTREACHED() << "Invalid source_origin URL: " << source_url; + return false; + } + + if (CEF_CURRENTLY_ON_UIT()) { + return CefOriginWhitelistManager::GetInstance()->RemoveOriginEntry( + source_origin, target_protocol, target_domain, allow_target_subdomains); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(&CefRemoveCrossOriginWhitelistEntry), + source_origin, target_protocol, target_domain, + allow_target_subdomains)); + } + + return true; +} + +bool CefClearCrossOriginWhitelist() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED(); + return false; + } + + if (CEF_CURRENTLY_ON_UIT()) { + CefOriginWhitelistManager::GetInstance()->ClearOrigins(); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(base::IgnoreResult(&CefClearCrossOriginWhitelist))); + } + + return true; +} + +void GetCrossOriginWhitelistEntries( + std::vector* entries) { + CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries( + entries); +} + +bool HasCrossOriginWhitelistEntry(const GURL& source, const GURL& target) { + std::vector params; + CefOriginWhitelistManager::GetInstance()->GetCrossOriginWhitelistEntries( + ¶ms); + + if (params.empty()) + return false; + + std::vector::const_iterator it = + params.begin(); + for (; it != params.end(); ++it) { + if (IsMatch(source, target, *it)) + return true; + } + + return false; +} diff --git a/libcef/browser/origin_whitelist_impl.h b/libcef/browser/origin_whitelist_impl.h new file mode 100644 index 000000000..bca948c2d --- /dev/null +++ b/libcef/browser/origin_whitelist_impl.h @@ -0,0 +1,28 @@ +// 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_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_ +#define CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_ + +#include +#include + +namespace content { +class RenderProcessHost; +} + +class GURL; + +struct Cef_CrossOriginWhiteListEntry_Params; + +// Called to retrieve the current list of cross-origin white list entries. This +// method is thread safe. +void GetCrossOriginWhitelistEntries( + std::vector* entries); + +// Returns true if |source| can access |target| based on the cross-origin white +// list settings. +bool HasCrossOriginWhitelistEntry(const GURL& source, const GURL& target); + +#endif // CEF_LIBCEF_BROWSER_ORIGIN_WHITELIST_IMPL_H_ diff --git a/libcef/browser/path_util_impl.cc b/libcef/browser/path_util_impl.cc new file mode 100644 index 000000000..9a73d800c --- /dev/null +++ b/libcef/browser/path_util_impl.cc @@ -0,0 +1,44 @@ +// 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 "include/cef_path_util.h" + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" + +bool CefGetPath(PathKey key, CefString& path) { + int pref_key = base::PATH_START; + switch(key) { + case PK_DIR_CURRENT: + pref_key = base::DIR_CURRENT; + break; + case PK_DIR_EXE: + pref_key = base::DIR_EXE; + break; + case PK_DIR_MODULE: + pref_key = base::DIR_MODULE; + break; + case PK_DIR_TEMP: + pref_key = base::DIR_TEMP; + break; + case PK_FILE_EXE: + pref_key = base::FILE_EXE; + break; + case PK_FILE_MODULE: + pref_key = base::FILE_MODULE; + break; + default: + NOTREACHED() << "invalid argument"; + return false; + } + + base::FilePath file_path; + if (PathService::Get(pref_key, &file_path)) { + path = file_path.value(); + return true; + } + + return false; +} diff --git a/libcef/browser/print_settings_impl.cc b/libcef/browser/print_settings_impl.cc new file mode 100644 index 000000000..fd38b4047 --- /dev/null +++ b/libcef/browser/print_settings_impl.cc @@ -0,0 +1,165 @@ +// 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 "libcef/browser/print_settings_impl.h" + +#include "base/logging.h" + +CefPrintSettingsImpl::CefPrintSettingsImpl(printing::PrintSettings* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +bool CefPrintSettingsImpl::IsValid() { + return !detached(); +} + +bool CefPrintSettingsImpl::IsReadOnly() { + return read_only(); +} + +CefRefPtr CefPrintSettingsImpl::Copy() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + printing::PrintSettings* new_settings = new printing::PrintSettings; + *new_settings = const_value(); + return new CefPrintSettingsImpl(new_settings, true, false); +} + +void CefPrintSettingsImpl::SetOrientation(bool landscape) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->SetOrientation(landscape); +} + +bool CefPrintSettingsImpl::IsLandscape() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().landscape(); +} + +void CefPrintSettingsImpl::SetPrinterPrintableArea( + const CefSize& physical_size_device_units, + const CefRect& printable_area_device_units, + bool landscape_needs_flip) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + gfx::Size size(physical_size_device_units.width, + physical_size_device_units.height); + gfx::Rect rect(printable_area_device_units.x, + printable_area_device_units.y, + printable_area_device_units.width, + printable_area_device_units.height); + mutable_value()->SetPrinterPrintableArea(size, rect, landscape_needs_flip); +} + +void CefPrintSettingsImpl::SetDeviceName(const CefString& name) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_device_name(name.ToString16()); +} + +CefString CefPrintSettingsImpl::GetDeviceName() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().device_name(); +} + +void CefPrintSettingsImpl::SetDPI(int dpi) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_dpi(dpi); +} + +int CefPrintSettingsImpl::GetDPI() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().dpi(); +} + +void CefPrintSettingsImpl::SetPageRanges(const PageRangeList& ranges) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + printing::PageRanges page_ranges; + PageRangeList::const_iterator it = ranges.begin(); + for(; it != ranges.end(); ++it) { + const CefPageRange& cef_range = *it; + printing::PageRange range; + range.from = cef_range.from; + range.to = cef_range.to; + page_ranges.push_back(range); + } + mutable_value()->set_ranges(page_ranges); +} + +size_t CefPrintSettingsImpl::GetPageRangesCount() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().ranges().size(); +} + +void CefPrintSettingsImpl::GetPageRanges(PageRangeList& ranges) { + CEF_VALUE_VERIFY_RETURN_VOID(false); + if (!ranges.empty()) + ranges.clear(); + const printing::PageRanges& page_ranges = const_value().ranges(); + printing::PageRanges::const_iterator it = page_ranges.begin(); + for (; it != page_ranges.end(); ++it) { + const printing::PageRange& range = *it; + ranges.push_back(CefPageRange(range.from, range.to)); + } +} + +void CefPrintSettingsImpl::SetSelectionOnly(bool selection_only) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_selection_only(selection_only); +} + +bool CefPrintSettingsImpl::IsSelectionOnly() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().selection_only(); +} + +void CefPrintSettingsImpl::SetCollate(bool collate) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_collate(collate); +} + +bool CefPrintSettingsImpl::WillCollate() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().collate(); +} + +void CefPrintSettingsImpl::SetColorModel(ColorModel model) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_color(static_cast(model)); +} + +CefPrintSettings::ColorModel CefPrintSettingsImpl::GetColorModel() { + CEF_VALUE_VERIFY_RETURN(false, COLOR_MODEL_UNKNOWN); + return static_cast(const_value().color()); +} + +void CefPrintSettingsImpl::SetCopies(int copies) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_copies(copies); +} + +int CefPrintSettingsImpl::GetCopies() { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().copies(); +} + +void CefPrintSettingsImpl::SetDuplexMode(DuplexMode mode) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->set_duplex_mode(static_cast(mode)); +} + +CefPrintSettings::DuplexMode CefPrintSettingsImpl::GetDuplexMode() { + CEF_VALUE_VERIFY_RETURN(false, DUPLEX_MODE_UNKNOWN); + return static_cast(const_value().duplex_mode()); +} + + +// CefPrintSettings implementation. + +// static +CefRefPtr CefPrintSettings::Create() { + return new CefPrintSettingsImpl( + new printing::PrintSettings(), true, false); +} + diff --git a/libcef/browser/print_settings_impl.h b/libcef/browser/print_settings_impl.h new file mode 100644 index 000000000..e802c56f3 --- /dev/null +++ b/libcef/browser/print_settings_impl.h @@ -0,0 +1,56 @@ +// 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_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_ +#define CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_ +#pragma once + +#include "include/cef_print_settings.h" +#include "libcef/common/value_base.h" + +#include "printing/print_settings.h" + +// CefPrintSettings implementation +class CefPrintSettingsImpl + : public CefValueBase { + public: + CefPrintSettingsImpl(printing::PrintSettings* value, + bool will_delete, + bool read_only); + + // CefPrintSettings methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual void SetOrientation(bool landscape) OVERRIDE; + virtual bool IsLandscape() OVERRIDE; + virtual void SetPrinterPrintableArea( + const CefSize& physical_size_device_units, + const CefRect& printable_area_device_units, + bool landscape_needs_flip) OVERRIDE; + virtual void SetDeviceName(const CefString& name) OVERRIDE; + virtual CefString GetDeviceName() OVERRIDE; + virtual void SetDPI(int dpi) OVERRIDE; + virtual int GetDPI() OVERRIDE; + virtual void SetPageRanges(const PageRangeList& ranges) OVERRIDE; + virtual size_t GetPageRangesCount() OVERRIDE; + virtual void GetPageRanges(PageRangeList& ranges) OVERRIDE; + virtual void SetSelectionOnly(bool selection_only) OVERRIDE; + virtual bool IsSelectionOnly() OVERRIDE; + virtual void SetCollate(bool collate) OVERRIDE; + virtual bool WillCollate() OVERRIDE; + virtual void SetColorModel(ColorModel model) OVERRIDE; + virtual ColorModel GetColorModel() OVERRIDE; + virtual void SetCopies(int copies) OVERRIDE; + virtual int GetCopies() OVERRIDE; + virtual void SetDuplexMode(DuplexMode mode) OVERRIDE; + virtual DuplexMode GetDuplexMode() OVERRIDE; + + // Must hold the controller lock while using this value. + const printing::PrintSettings& print_settings() { return const_value(); } + + DISALLOW_COPY_AND_ASSIGN(CefPrintSettingsImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_PRINT_SETTINGS_IMPL_H_ diff --git a/libcef/browser/printing/print_dialog_linux.cc b/libcef/browser/printing/print_dialog_linux.cc new file mode 100644 index 000000000..1f7f19311 --- /dev/null +++ b/libcef/browser/printing/print_dialog_linux.cc @@ -0,0 +1,275 @@ +// 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 "libcef/browser/printing/print_dialog_linux.h" + +#include +#include + +#include "libcef/browser/print_settings_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/content_client.h" + +#include "base/bind.h" +#include "base/file_util.h" +#include "base/files/file_util_proxy.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "printing/metafile.h" +#include "printing/print_job_constants.h" +#include "printing/print_settings.h" + +using content::BrowserThread; +using printing::PageRanges; +using printing::PrintSettings; + +class CefPrintDialogCallbackImpl : public CefPrintDialogCallback { + public: + explicit CefPrintDialogCallbackImpl(CefRefPtr dialog) + : dialog_(dialog) { + } + + virtual void Continue(CefRefPtr settings) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (dialog_) { + dialog_->OnPrintContinue(settings); + dialog_ = NULL; + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefPrintDialogCallbackImpl::Continue, this, settings)); + } + } + + virtual void Cancel() OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (dialog_) { + dialog_->OnPrintCancel(); + dialog_ = NULL; + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefPrintDialogCallbackImpl::Cancel, this)); + } + } + + void Disconnect() { + dialog_ = NULL; + } + + private: + CefRefPtr dialog_; + + IMPLEMENT_REFCOUNTING(CefPrintDialogCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefPrintDialogCallbackImpl); +}; + +class CefPrintJobCallbackImpl : public CefPrintJobCallback { + public: + explicit CefPrintJobCallbackImpl(CefRefPtr dialog) + : dialog_(dialog) { + } + + virtual void Continue() OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (dialog_) { + dialog_->OnJobCompleted(); + dialog_ = NULL; + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefPrintJobCallbackImpl::Continue, this)); + } + } + + void Disconnect() { + dialog_ = NULL; + } + + private: + CefRefPtr dialog_; + + IMPLEMENT_REFCOUNTING(CefPrintJobCallbackImpl); + DISALLOW_COPY_AND_ASSIGN(CefPrintJobCallbackImpl); +}; + + +// static +printing::PrintDialogGtkInterface* CefPrintDialogLinux::CreatePrintDialog( + PrintingContextLinux* context) { + CEF_REQUIRE_UIT(); + return new CefPrintDialogLinux(context); +} + +CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context) + : context_(context) { +} + +CefPrintDialogLinux::~CefPrintDialogLinux() { + CEF_REQUIRE_UIT(); + ReleaseHandler(); +} + +void CefPrintDialogLinux::UseDefaultSettings() { + PrintSettings settings; + UpdateSettings(&settings, true); +} + +bool CefPrintDialogLinux::UpdateSettings(printing::PrintSettings* settings) { + return UpdateSettings(settings, false); +} + +void CefPrintDialogLinux::ShowDialog( + gfx::NativeView parent_view, + bool has_selection, + const PrintingContextLinux::PrintSettingsCallback& callback) { + CEF_REQUIRE_UIT(); + + SetHandler(); + if (!handler_) { + callback.Run(PrintingContextLinux::CANCEL); + return; + } + + callback_ = callback; + + CefRefPtr callback_impl( + new CefPrintDialogCallbackImpl(this)); + + if (!handler_->OnPrintDialog(has_selection, callback_impl.get())) { + callback_impl->Disconnect(); + OnPrintCancel(); + } +} + +void CefPrintDialogLinux::PrintDocument(const printing::Metafile* metafile, + const base::string16& document_name) { + // This runs on the print worker thread, does not block the UI thread. + DCHECK(!CEF_CURRENTLY_ON_UIT()); + + // The document printing tasks can outlive the PrintingContext that created + // this dialog. + AddRef(); + + bool error = false; + if (!base::CreateTemporaryFile(&path_to_pdf_)) { + LOG(ERROR) << "Creating temporary file failed"; + error = true; + } + + if (!error && !metafile->SaveTo(path_to_pdf_)) { + LOG(ERROR) << "Saving metafile failed"; + base::DeleteFile(path_to_pdf_, false); + error = true; + } + + if (error) { + // Matches AddRef() above. + Release(); + } else { + // No errors, continue printing. + CEF_POST_TASK( + CEF_UIT, + base::Bind(&CefPrintDialogLinux::SendDocumentToPrinter, this, + document_name)); + } +} + +void CefPrintDialogLinux::AddRefToDialog() { + AddRef(); +} + +void CefPrintDialogLinux::ReleaseDialog() { + Release(); +} + +void CefPrintDialogLinux::SetHandler() { + if (handler_) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr browser_handler = + app->GetBrowserProcessHandler(); + if (browser_handler) + handler_ = browser_handler->GetPrintHandler(); + } +} + +void CefPrintDialogLinux::ReleaseHandler() { + if (handler_) { + handler_->OnPrintReset(); + handler_ = NULL; + } +} + +bool CefPrintDialogLinux::UpdateSettings(printing::PrintSettings* settings, + bool get_defaults) { + CEF_REQUIRE_UIT(); + + SetHandler(); + if (!handler_) + return false; + + CefRefPtr settings_impl( + new CefPrintSettingsImpl(settings, false, false)); + handler_->OnPrintSettings(settings_impl.get(), get_defaults); + settings_impl->Detach(NULL); + + context_->InitWithSettings(*settings); + return true; +} + +void CefPrintDialogLinux::SendDocumentToPrinter( + const base::string16& document_name) { + CEF_REQUIRE_UIT(); + + if (!handler_) { + OnJobCompleted(); + return; + } + + CefRefPtr callback_impl( + new CefPrintJobCallbackImpl(this)); + + if (!handler_->OnPrintJob(document_name, path_to_pdf_.value(), + callback_impl.get())) { + callback_impl->Disconnect(); + OnJobCompleted(); + } +} + +void CefPrintDialogLinux::OnPrintContinue( + CefRefPtr settings) { + { + CefPrintSettingsImpl* impl = + static_cast(settings.get()); + CefValueController::AutoLock lock_scope(impl->controller()); + context_->InitWithSettings(impl->print_settings()); + } + callback_.Run(PrintingContextLinux::OK); + callback_.Reset(); +} + +void CefPrintDialogLinux::OnPrintCancel() { + callback_.Run(PrintingContextLinux::CANCEL); + callback_.Reset(); +} + +void CefPrintDialogLinux::OnJobCompleted() { + base::FileUtilProxy::DeleteFile( + content::BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::FILE).get(), + path_to_pdf_, + false, + base::FileUtilProxy::StatusCallback()); + + // Printing finished. Matches AddRef() in PrintDocument(); + Release(); +} + diff --git a/libcef/browser/printing/print_dialog_linux.h b/libcef/browser/printing/print_dialog_linux.h new file mode 100644 index 000000000..2c5aa8bbf --- /dev/null +++ b/libcef/browser/printing/print_dialog_linux.h @@ -0,0 +1,85 @@ +// 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 LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_ +#define LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_ + +#include "include/cef_print_handler.h" + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner_helpers.h" +#include "content/public/browser/browser_thread.h" +#include "printing/print_dialog_gtk_interface.h" +#include "printing/printing_context_linux.h" + +namespace printing { +class Metafile; +class PrintSettings; +} + +using printing::PrintingContextLinux; + +// Needs to be freed on the UI thread to clean up its member variables. +class CefPrintDialogLinux + : public printing::PrintDialogGtkInterface, + public base::RefCountedThreadSafe< + CefPrintDialogLinux, content::BrowserThread::DeleteOnUIThread> { + public: + // Creates and returns a print dialog. + static printing::PrintDialogGtkInterface* CreatePrintDialog( + PrintingContextLinux* context); + + // printing::CefPrintDialogLinuxInterface implementation. + virtual void UseDefaultSettings() OVERRIDE; + virtual bool UpdateSettings(printing::PrintSettings* settings) OVERRIDE; + virtual void ShowDialog( + gfx::NativeView parent_view, + bool has_selection, + const PrintingContextLinux::PrintSettingsCallback& callback) OVERRIDE; + virtual void PrintDocument(const printing::Metafile* metafile, + const base::string16& document_name) OVERRIDE; + virtual void AddRefToDialog() OVERRIDE; + virtual void ReleaseDialog() OVERRIDE; + + private: + friend struct content::BrowserThread::DeleteOnThread< + content::BrowserThread::UI>; + friend class base::DeleteHelper; + friend class CefPrintDialogCallbackImpl; + friend class CefPrintJobCallbackImpl; + + explicit CefPrintDialogLinux(PrintingContextLinux* context); + virtual ~CefPrintDialogLinux(); + + void SetHandler(); + void ReleaseHandler(); + + bool UpdateSettings(printing::PrintSettings* settings, + bool get_defaults); + + // Prints document named |document_name|. + void SendDocumentToPrinter(const base::string16& document_name); + + // Handles print dialog response. + void OnPrintContinue(CefRefPtr settings); + void OnPrintCancel(); + + // Handles print job response. + void OnJobCompleted(); + + CefRefPtr handler_; + + // Printing dialog callback. + PrintingContextLinux::PrintSettingsCallback callback_; + PrintingContextLinux* context_; + + base::FilePath path_to_pdf_; + + DISALLOW_COPY_AND_ASSIGN(CefPrintDialogLinux); +}; + +#endif // LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_ diff --git a/libcef/browser/printing/print_view_manager.cc b/libcef/browser/printing/print_view_manager.cc new file mode 100644 index 000000000..c4cbc79d1 --- /dev/null +++ b/libcef/browser/printing/print_view_manager.cc @@ -0,0 +1,64 @@ +// 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 "libcef/browser/printing/print_view_manager.h" + +#include + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/metrics/histogram.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/printing/print_job_manager.h" +#include "chrome/browser/printing/print_preview_dialog_controller.h" +#include "chrome/common/print_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "printing/print_destination_interface.h" + +using content::BrowserThread; + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintViewManager); + +namespace printing { + +PrintViewManager::PrintViewManager(content::WebContents* web_contents) + : PrintViewManagerBase(web_contents) { +} + +PrintViewManager::~PrintViewManager() { +} + +bool PrintViewManager::PrintForSystemDialogNow() { + return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id())); +} + +bool PrintViewManager::PrintToDestination() { + // TODO(mad): Remove this once we can send user metrics from the metro driver. + // crbug.com/142330 + UMA_HISTOGRAM_ENUMERATION("Metro.Print", 0, 2); + // TODO(mad): Use a passed in destination interface instead. + g_browser_process->print_job_manager()->queue()->SetDestination( + printing::CreatePrintDestination()); + return PrintNowInternal(new PrintMsg_PrintPages(routing_id())); +} + +void PrintViewManager::RenderProcessGone(base::TerminationStatus status) { + PrintViewManagerBase::RenderProcessGone(status); +} + +void PrintViewManager::OnDidShowPrintDialog() { +} + +bool PrintViewManager::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManager, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidShowPrintDialog, OnDidShowPrintDialog) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled ? true : PrintViewManagerBase::OnMessageReceived(message); +} + +} // namespace printing diff --git a/libcef/browser/printing/print_view_manager.h b/libcef/browser/printing/print_view_manager.h new file mode 100644 index 000000000..2776e290b --- /dev/null +++ b/libcef/browser/printing/print_view_manager.h @@ -0,0 +1,51 @@ +// 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_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_ +#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_ + +#include "libcef/browser/printing/print_view_manager_base.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { +class RenderProcessHost; +} + +namespace printing { + +// Manages the print commands for a WebContents. +class PrintViewManager : public PrintViewManagerBase, + public content::WebContentsUserData { + public: + virtual ~PrintViewManager(); + + // Same as PrintNow(), but for the case where a user prints with the system + // dialog from print preview. + bool PrintForSystemDialogNow(); + + // Same as PrintNow(), but for the case where we want to send the result to + // another destination. + // TODO(mad) Add an argument so we can pass the destination interface. + bool PrintToDestination(); + + // content::WebContentsObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // content::WebContentsObserver implementation. + // Terminates or cancels the print job if one was pending. + virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; + + private: + explicit PrintViewManager(content::WebContents* web_contents); + friend class content::WebContentsUserData; + + // IPC Message handlers. + void OnDidShowPrintDialog(); + + DISALLOW_COPY_AND_ASSIGN(PrintViewManager); +}; + +} // namespace printing + +#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_H_ diff --git a/libcef/browser/printing/print_view_manager_base.cc b/libcef/browser/printing/print_view_manager_base.cc new file mode 100644 index 000000000..7cfc42fca --- /dev/null +++ b/libcef/browser/printing/print_view_manager_base.cc @@ -0,0 +1,578 @@ +// Copyright 2013 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 "libcef/browser/printing/print_view_manager_base.h" + +#include "libcef/browser/content_browser_client.h" + +#include "base/bind.h" +#include "base/memory/scoped_ptr.h" +#include "base/prefs/pref_service.h" +#include "base/strings/utf_string_conversions.h" +#include "base/timer/timer.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/printing/print_job.h" +#include "chrome/browser/printing/print_job_manager.h" +#include "chrome/browser/printing/printer_query.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/print_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "grit/generated_resources.h" +#include "printing/metafile_impl.h" +#include "printing/printed_document.h" +#include "ui/base/l10n/l10n_util.h" + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" +#include "chrome/browser/printing/pdf_to_emf_converter.h" +#include "printing/pdf_render_settings.h" +#endif + +using base::TimeDelta; +using content::BrowserThread; + +namespace printing { + +namespace { + +#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) +// Limits memory usage by raster to 64 MiB. +const int kMaxRasterSizeInPixels = 16*1024*1024; +#endif + +} // namespace + +PrintViewManagerBase::PrintViewManagerBase(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + number_pages_(0), + printing_succeeded_(false), + inside_inner_message_loop_(false), + cookie_(0), + queue_(g_browser_process->print_job_manager()->queue()) { + DCHECK(queue_); +#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ + defined(WIN_PDF_METAFILE_FOR_PRINTING) + expecting_first_page_ = true; +#endif + printing_enabled_.Init( + prefs::kPrintingEnabled, + CefContentBrowserClient::Get()->pref_service(), + base::Bind(&PrintViewManagerBase::UpdateScriptedPrintingBlocked, + base::Unretained(this))); +} + +PrintViewManagerBase::~PrintViewManagerBase() { + ReleasePrinterQuery(); + DisconnectFromCurrentPrintJob(); +} + +bool PrintViewManagerBase::PrintNow() { + return PrintNowInternal(new PrintMsg_PrintPages(routing_id())); +} + +void PrintViewManagerBase::UpdateScriptedPrintingBlocked() { + Send(new PrintMsg_SetScriptedPrintingBlocked( + routing_id(), + !printing_enabled_.GetValue())); +} + +void PrintViewManagerBase::NavigationStopped() { + // Cancel the current job, wait for the worker to finish. + TerminatePrintJob(true); +} + +void PrintViewManagerBase::RenderProcessGone(base::TerminationStatus status) { + ReleasePrinterQuery(); + + if (!print_job_.get()) + return; + + scoped_refptr document(print_job_->document()); + if (document.get()) { + // If IsComplete() returns false, the document isn't completely rendered. + // Since our renderer is gone, there's nothing to do, cancel it. Otherwise, + // the print job may finish without problem. + TerminatePrintJob(!document->IsComplete()); + } +} + +base::string16 PrintViewManagerBase::RenderSourceName() { + base::string16 name(web_contents()->GetTitle()); + if (name.empty()) + name = l10n_util::GetStringUTF16(IDS_DEFAULT_PRINT_DOCUMENT_TITLE); + return name; +} + +void PrintViewManagerBase::OnDidGetPrintedPagesCount(int cookie, + int number_pages) { + DCHECK_GT(cookie, 0); + DCHECK_GT(number_pages, 0); + number_pages_ = number_pages; + OpportunisticallyCreatePrintJob(cookie); +} + +void PrintViewManagerBase::OnDidGetDocumentCookie(int cookie) { + cookie_ = cookie; +} + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) +void PrintViewManagerBase::OnPdfToEmfConverted( + const PrintHostMsg_DidPrintPage_Params& params, + double scale_factor, + const std::vector& emf_files) { + PrintedDocument* document = print_job_->document(); + if (!document) + return; + + for (size_t i = 0; i < emf_files.size(); ++i) { + scoped_ptr metafile(new printing::Emf); + if (!metafile->InitFromFile(emf_files[i])) { + NOTREACHED() << "Invalid metafile"; + web_contents()->Stop(); + return; + } + // Update the rendered document. It will send notifications to the listener. + document->SetPage(i, + metafile.release(), + scale_factor, + params.page_size, + params.content_area); + } + + ShouldQuitFromInnerMessageLoop(); +} +#endif // WIN_PDF_METAFILE_FOR_PRINTING + +void PrintViewManagerBase::OnDidPrintPage( + const PrintHostMsg_DidPrintPage_Params& params) { + if (!OpportunisticallyCreatePrintJob(params.document_cookie)) + return; + + PrintedDocument* document = print_job_->document(); + if (!document || params.document_cookie != document->cookie()) { + // Out of sync. It may happen since we are completely asynchronous. Old + // spurious messages can be received if one of the processes is overloaded. + return; + } + +#if (defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING)) || \ + defined(OS_MACOSX) + const bool metafile_must_be_valid = true; +#elif defined(OS_POSIX) || defined(WIN_PDF_METAFILE_FOR_PRINTING) + const bool metafile_must_be_valid = expecting_first_page_; + expecting_first_page_ = false; +#endif + + base::SharedMemory shared_buf(params.metafile_data_handle, true); + if (metafile_must_be_valid) { + if (!shared_buf.Map(params.data_size)) { + NOTREACHED() << "couldn't map"; + web_contents()->Stop(); + return; + } + } + + scoped_ptr metafile(new NativeMetafile); + if (metafile_must_be_valid) { + if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) { + NOTREACHED() << "Invalid metafile header"; + web_contents()->Stop(); + return; + } + } + +#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) + bool big_emf = (params.data_size && params.data_size >= kMetafileMaxSize); + int raster_size = + std::min(params.page_size.GetArea(), kMaxRasterSizeInPixels); + if (big_emf) { + scoped_ptr raster_metafile( + metafile->RasterizeMetafile(raster_size)); + if (raster_metafile.get()) { + metafile.swap(raster_metafile); + } else if (big_emf) { + // Don't fall back to emf here. + NOTREACHED() << "size:" << params.data_size; + TerminatePrintJob(true); + web_contents()->Stop(); + return; + } + } +#endif // OS_WIN && !WIN_PDF_METAFILE_FOR_PRINTING + +#if !defined(WIN_PDF_METAFILE_FOR_PRINTING) + // Update the rendered document. It will send notifications to the listener. + document->SetPage(params.page_number, + metafile.release(), +#if defined(OS_WIN) + params.actual_shrink, +#endif // OS_WIN + params.page_size, + params.content_area); + + ShouldQuitFromInnerMessageLoop(); +#else + if (metafile_must_be_valid) { + scoped_refptr bytes = new base::RefCountedBytes( + reinterpret_cast(shared_buf.memory()), + params.data_size); + + document->DebugDumpData(bytes, FILE_PATH_LITERAL(".pdf")); + + if (!pdf_to_emf_converter_) + pdf_to_emf_converter_ = PdfToEmfConverter::CreateDefault(); + + const int kPrinterDpi = print_job_->settings().dpi(); + pdf_to_emf_converter_->Start( + bytes, + printing::PdfRenderSettings(params.content_area, kPrinterDpi, true), + base::Bind(&PrintViewManagerBase::OnPdfToEmfConverted, + base::Unretained(this), + params)); + } +#endif // !WIN_PDF_METAFILE_FOR_PRINTING +} + +void PrintViewManagerBase::OnPrintingFailed(int cookie) { + if (cookie != cookie_) { + NOTREACHED(); + return; + } + + ReleasePrinterQuery(); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source(web_contents()), + content::NotificationService::NoDetails()); +} + +void PrintViewManagerBase::DidStartLoading( + content::RenderViewHost* render_view_host) { + UpdateScriptedPrintingBlocked(); +} + +bool PrintViewManagerBase::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintViewManagerBase, message) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount, + OnDidGetPrintedPagesCount) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie, + OnDidGetDocumentCookie) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintPage, OnDidPrintPage) + IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PrintViewManagerBase::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case chrome::NOTIFICATION_PRINT_JOB_EVENT: { + OnNotifyPrintJobEvent(*content::Details(details).ptr()); + break; + } + default: { + NOTREACHED(); + break; + } + } +} + +void PrintViewManagerBase::OnNotifyPrintJobEvent( + const JobEventDetails& event_details) { + switch (event_details.type()) { + case JobEventDetails::FAILED: { + TerminatePrintJob(true); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source(web_contents()), + content::NotificationService::NoDetails()); + break; + } + case JobEventDetails::USER_INIT_DONE: + case JobEventDetails::DEFAULT_INIT_DONE: + case JobEventDetails::USER_INIT_CANCELED: { + NOTREACHED(); + break; + } + case JobEventDetails::ALL_PAGES_REQUESTED: { + ShouldQuitFromInnerMessageLoop(); + break; + } + case JobEventDetails::NEW_DOC: + case JobEventDetails::NEW_PAGE: + case JobEventDetails::PAGE_DONE: + case JobEventDetails::DOC_DONE: { + // Don't care about the actual printing process. + break; + } + case JobEventDetails::JOB_DONE: { + // Printing is done, we don't need it anymore. + // print_job_->is_job_pending() may still be true, depending on the order + // of object registration. + printing_succeeded_ = true; + ReleasePrintJob(); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PRINT_JOB_RELEASED, + content::Source(web_contents()), + content::NotificationService::NoDetails()); + break; + } + default: { + NOTREACHED(); + break; + } + } +} + +bool PrintViewManagerBase::RenderAllMissingPagesNow() { + if (!print_job_.get() || !print_job_->is_job_pending()) + return false; + + // We can't print if there is no renderer. + if (!web_contents() || + !web_contents()->GetRenderViewHost() || + !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { + return false; + } + + // Is the document already complete? + if (print_job_->document() && print_job_->document()->IsComplete()) { + printing_succeeded_ = true; + return true; + } + + // WebContents is either dying or a second consecutive request to print + // happened before the first had time to finish. We need to render all the + // pages in an hurry if a print_job_ is still pending. No need to wait for it + // to actually spool the pages, only to have the renderer generate them. Run + // a message loop until we get our signal that the print job is satisfied. + // PrintJob will send a ALL_PAGES_REQUESTED after having received all the + // pages it needs. MessageLoop::current()->Quit() will be called as soon as + // print_job_->document()->IsComplete() is true on either ALL_PAGES_REQUESTED + // or in DidPrintPage(). The check is done in + // ShouldQuitFromInnerMessageLoop(). + // BLOCKS until all the pages are received. (Need to enable recursive task) + if (!RunInnerMessageLoop()) { + // This function is always called from DisconnectFromCurrentPrintJob() so we + // know that the job will be stopped/canceled in any case. + return false; + } + return true; +} + +void PrintViewManagerBase::ShouldQuitFromInnerMessageLoop() { + // Look at the reason. + DCHECK(print_job_->document()); + if (print_job_->document() && + print_job_->document()->IsComplete() && + inside_inner_message_loop_) { + // We are in a message loop created by RenderAllMissingPagesNow. Quit from + // it. + base::MessageLoop::current()->Quit(); + inside_inner_message_loop_ = false; + } +} + +bool PrintViewManagerBase::CreateNewPrintJob(PrintJobWorkerOwner* job) { + DCHECK(!inside_inner_message_loop_); + + // Disconnect the current print_job_. + DisconnectFromCurrentPrintJob(); + + // We can't print if there is no renderer. + if (!web_contents()->GetRenderViewHost() || + !web_contents()->GetRenderViewHost()->IsRenderViewLive()) { + return false; + } + + // Ask the renderer to generate the print preview, create the print preview + // view and switch to it, initialize the printer and show the print dialog. + DCHECK(!print_job_.get()); + DCHECK(job); + if (!job) + return false; + + print_job_ = new PrintJob(); + print_job_->Initialize(job, this, number_pages_); + registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, + content::Source(print_job_.get())); + printing_succeeded_ = false; + return true; +} + +void PrintViewManagerBase::DisconnectFromCurrentPrintJob() { + // Make sure all the necessary rendered page are done. Don't bother with the + // return value. + bool result = RenderAllMissingPagesNow(); + + // Verify that assertion. + if (print_job_.get() && + print_job_->document() && + !print_job_->document()->IsComplete()) { + DCHECK(!result); + // That failed. + TerminatePrintJob(true); + } else { + // DO NOT wait for the job to finish. + ReleasePrintJob(); + } +#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ + defined(WIN_PDF_METAFILE_FOR_PRINTING) + expecting_first_page_ = true; +#endif +} + +void PrintViewManagerBase::PrintingDone(bool success) { + if (!print_job_.get()) + return; + Send(new PrintMsg_PrintingDone(routing_id(), success)); +} + +void PrintViewManagerBase::TerminatePrintJob(bool cancel) { + if (!print_job_.get()) + return; + + if (cancel) { + // We don't need the metafile data anymore because the printing is canceled. + print_job_->Cancel(); + inside_inner_message_loop_ = false; + } else { + DCHECK(!inside_inner_message_loop_); + DCHECK(!print_job_->document() || print_job_->document()->IsComplete()); + + // WebContents is either dying or navigating elsewhere. We need to render + // all the pages in an hurry if a print job is still pending. This does the + // trick since it runs a blocking message loop: + print_job_->Stop(); + } + ReleasePrintJob(); +} + +void PrintViewManagerBase::ReleasePrintJob() { + if (!print_job_.get()) + return; + + PrintingDone(printing_succeeded_); + + registrar_.Remove(this, chrome::NOTIFICATION_PRINT_JOB_EVENT, + content::Source(print_job_.get())); + print_job_->DisconnectSource(); + // Don't close the worker thread. + print_job_ = NULL; +} + +bool PrintViewManagerBase::RunInnerMessageLoop() { + // This value may actually be too low: + // + // - If we're looping because of printer settings initialization, the premise + // here is that some poor users have their print server away on a VPN over a + // slow connection. In this situation, the simple fact of opening the printer + // can be dead slow. On the other side, we don't want to die infinitely for a + // real network error. Give the printer 60 seconds to comply. + // + // - If we're looping because of renderer page generation, the renderer could + // be CPU bound, the page overly complex/large or the system just + // memory-bound. + static const int kPrinterSettingsTimeout = 60000; + base::OneShotTimer quit_timer; + quit_timer.Start(FROM_HERE, + TimeDelta::FromMilliseconds(kPrinterSettingsTimeout), + base::MessageLoop::current(), &base::MessageLoop::Quit); + + inside_inner_message_loop_ = true; + + // Need to enable recursive task. + { + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + base::MessageLoop::current()->Run(); + } + + bool success = true; + if (inside_inner_message_loop_) { + // Ok we timed out. That's sad. + inside_inner_message_loop_ = false; + success = false; + } + + return success; +} + +bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) { + if (print_job_.get()) + return true; + + if (!cookie) { + // Out of sync. It may happens since we are completely asynchronous. Old + // spurious message can happen if one of the processes is overloaded. + return false; + } + + // The job was initiated by a script. Time to get the corresponding worker + // thread. + scoped_refptr queued_query = queue_->PopPrinterQuery(cookie); + if (!queued_query) { + NOTREACHED(); + return false; + } + + if (!CreateNewPrintJob(queued_query)) { + // Don't kill anything. + return false; + } + + // Settings are already loaded. Go ahead. This will set + // print_job_->is_job_pending() to true. + print_job_->StartPrinting(); + return true; +} + +bool PrintViewManagerBase::PrintNowInternal(IPC::Message* message) { + // Don't print / print preview interstitials. + if (web_contents()->ShowingInterstitialPage()) { + delete message; + return false; + } + return Send(message); +} + +void PrintViewManagerBase::ReleasePrinterQuery() { + if (!cookie_) + return; + + int cookie = cookie_; + cookie_ = 0; + queue_->SetDestination(NULL); + + + printing::PrintJobManager* print_job_manager = + g_browser_process->print_job_manager(); + // May be NULL in tests. + if (!print_job_manager) + return; + + scoped_refptr printer_query; + printer_query = queue_->PopPrinterQuery(cookie); + if (!printer_query) + return; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&PrinterQuery::StopWorker, printer_query.get())); +} + +} // namespace printing diff --git a/libcef/browser/printing/print_view_manager_base.h b/libcef/browser/printing/print_view_manager_base.h new file mode 100644 index 000000000..a0a42fbe7 --- /dev/null +++ b/libcef/browser/printing/print_view_manager_base.h @@ -0,0 +1,179 @@ +// Copyright 2013 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_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_ +#define CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_ + +#include "base/memory/ref_counted.h" +#include "base/prefs/pref_member.h" +#include "base/strings/string16.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "printing/printed_pages_source.h" + +struct PrintHostMsg_DidPrintPage_Params; + +namespace content { +class RenderViewHost; +} + +namespace printing { + +class JobEventDetails; +class PdfToEmfConverter; +class PrintJob; +class PrintJobWorkerOwner; +class PrintQueriesQueue; + +// Base class for managing the print commands for a WebContents. +class PrintViewManagerBase : public content::NotificationObserver, + public PrintedPagesSource, + public content::WebContentsObserver { + public: + virtual ~PrintViewManagerBase(); + + // Prints the current document immediately. Since the rendering is + // asynchronous, the actual printing will not be completed on the return of + // this function. Returns false if printing is impossible at the moment. + virtual bool PrintNow(); + + // Whether to block scripted printing for our tab or not. + void UpdateScriptedPrintingBlocked(); + + // PrintedPagesSource implementation. + virtual base::string16 RenderSourceName() OVERRIDE; + + protected: + explicit PrintViewManagerBase(content::WebContents* web_contents); + + // Helper method for Print*Now(). + bool PrintNowInternal(IPC::Message* message); + + // Terminates or cancels the print job if one was pending. + virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; + + // content::WebContentsObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // IPC Message handlers. + virtual void OnPrintingFailed(int cookie); + + private: + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // content::WebContentsObserver implementation. + virtual void DidStartLoading( + content::RenderViewHost* render_view_host) OVERRIDE; + + // Cancels the print job. + virtual void NavigationStopped() OVERRIDE; + + // IPC Message handlers. + void OnDidGetPrintedPagesCount(int cookie, int number_pages); + void OnDidGetDocumentCookie(int cookie); + void OnDidPrintPage(const PrintHostMsg_DidPrintPage_Params& params); + + // Processes a NOTIFY_PRINT_JOB_EVENT notification. + void OnNotifyPrintJobEvent(const JobEventDetails& event_details); + + // Requests the RenderView to render all the missing pages for the print job. + // No-op if no print job is pending. Returns true if at least one page has + // been requested to the renderer. + bool RenderAllMissingPagesNow(); + + // Quits the current message loop if these conditions hold true: a document is + // loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This + // function is called in DidPrintPage() or on ALL_PAGES_REQUESTED + // notification. The inner message loop is created was created by + // RenderAllMissingPagesNow(). + void ShouldQuitFromInnerMessageLoop(); + + // Creates a new empty print job. It has no settings loaded. If there is + // currently a print job, safely disconnect from it. Returns false if it is + // impossible to safely disconnect from the current print job or it is + // impossible to create a new print job. + bool CreateNewPrintJob(PrintJobWorkerOwner* job); + + // Makes sure the current print_job_ has all its data before continuing, and + // disconnect from it. + void DisconnectFromCurrentPrintJob(); + + // Notify that the printing is done. + void PrintingDone(bool success); + + // Terminates the print job. No-op if no print job has been created. If + // |cancel| is true, cancel it instead of waiting for the job to finish. Will + // call ReleasePrintJob(). + void TerminatePrintJob(bool cancel); + + // Releases print_job_. Correctly deregisters from notifications. No-op if + // no print job has been created. + void ReleasePrintJob(); + + // Runs an inner message loop. It will set inside_inner_message_loop_ to true + // while the blocking inner message loop is running. This is useful in cases + // where the RenderView is about to be destroyed while a printing job isn't + // finished. + bool RunInnerMessageLoop(); + + // In the case of Scripted Printing, where the renderer is controlling the + // control flow, print_job_ is initialized whenever possible. No-op is + // print_job_ is initialized. + bool OpportunisticallyCreatePrintJob(int cookie); + + // Release the PrinterQuery associated with our |cookie_|. + void ReleasePrinterQuery(); + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) + // Called on completion of converting the pdf to emf. + void OnPdfToEmfConverted(const PrintHostMsg_DidPrintPage_Params& params, + double scale_factor, + const std::vector& emf_file); +#endif + + content::NotificationRegistrar registrar_; + + // Manages the low-level talk to the printer. + scoped_refptr print_job_; + + // Number of pages to print in the print job. + int number_pages_; + + // Indication of success of the print job. + bool printing_succeeded_; + + // Running an inner message loop inside RenderAllMissingPagesNow(). This means + // we are _blocking_ until all the necessary pages have been rendered or the + // print settings are being loaded. + bool inside_inner_message_loop_; + +#if (defined(OS_POSIX) && !defined(OS_MACOSX)) || \ + defined(WIN_PDF_METAFILE_FOR_PRINTING) + // Set to true when OnDidPrintPage() should be expecting the first page. + bool expecting_first_page_; +#endif + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) + scoped_ptr pdf_to_emf_converter_; +#endif + + // The document cookie of the current PrinterQuery. + int cookie_; + + // Whether printing is enabled. + BooleanPrefMember printing_enabled_; + + scoped_refptr queue_; + + DISALLOW_COPY_AND_ASSIGN(PrintViewManagerBase); +}; + +} // namespace printing + +#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINT_VIEW_MANAGER_BASE_H_ diff --git a/libcef/browser/printing/printing_message_filter.cc b/libcef/browser/printing/printing_message_filter.cc new file mode 100644 index 000000000..1563ecb9d --- /dev/null +++ b/libcef/browser/printing/printing_message_filter.cc @@ -0,0 +1,446 @@ +// 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 "libcef/browser/printing/printing_message_filter.h" + +#include + +#include "base/bind.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/printing/printer_query.h" +#include "chrome/browser/printing/printing_ui_web_contents_observer.h" +#include "chrome/browser/printing/print_job_manager.h" +#include "chrome/common/print_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" + +#if defined(OS_CHROMEOS) +#include + +#include + +#include "base/file_util.h" +#include "base/lazy_instance.h" +#include "chrome/browser/printing/print_dialog_cloud.h" +#endif + +#if defined(OS_ANDROID) +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/printing/print_view_manager_basic.h" +#include "printing/printing_context_android.h" +#endif + +using content::BrowserThread; + +namespace { + +#if defined(OS_CHROMEOS) +typedef std::map SequenceToPathMap; + +struct PrintingSequencePathMap { + SequenceToPathMap map; + int sequence; +}; + +// No locking, only access on the FILE thread. +static base::LazyInstance + g_printing_file_descriptor_map = LAZY_INSTANCE_INITIALIZER; +#endif + +void RenderParamsFromPrintSettings(const printing::PrintSettings& settings, + PrintMsg_Print_Params* params) { + params->page_size = settings.page_setup_device_units().physical_size(); + params->content_size.SetSize( + settings.page_setup_device_units().content_area().width(), + settings.page_setup_device_units().content_area().height()); + params->printable_area.SetRect( + settings.page_setup_device_units().printable_area().x(), + settings.page_setup_device_units().printable_area().y(), + settings.page_setup_device_units().printable_area().width(), + settings.page_setup_device_units().printable_area().height()); + params->margin_top = settings.page_setup_device_units().content_area().y(); + params->margin_left = settings.page_setup_device_units().content_area().x(); + params->dpi = settings.dpi(); + // Currently hardcoded at 1.25. See PrintSettings' constructor. + params->min_shrink = settings.min_shrink(); + // Currently hardcoded at 2.0. See PrintSettings' constructor. + params->max_shrink = settings.max_shrink(); + // Currently hardcoded at 72dpi. See PrintSettings' constructor. + params->desired_dpi = settings.desired_dpi(); + // Always use an invalid cookie. + params->document_cookie = 0; + params->selection_only = settings.selection_only(); + params->supports_alpha_blend = settings.supports_alpha_blend(); + params->should_print_backgrounds = settings.should_print_backgrounds(); + params->display_header_footer = settings.display_header_footer(); + params->title = settings.title(); + params->url = settings.url(); +} + +} // namespace + +PrintingMessageFilter::PrintingMessageFilter(int render_process_id) + : content::BrowserMessageFilter(PrintMsgStart), + render_process_id_(render_process_id), + queue_(g_browser_process->print_job_manager()->queue()) { + DCHECK(queue_); +} + +PrintingMessageFilter::~PrintingMessageFilter() { +} + +void PrintingMessageFilter::OverrideThreadForMessage( + const IPC::Message& message, BrowserThread::ID* thread) { +#if defined(OS_CHROMEOS) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::FILE; + } +#elif defined(OS_ANDROID) + if (message.type() == PrintHostMsg_AllocateTempFileForPrinting::ID || + message.type() == PrintHostMsg_TempFileForPrintingWritten::ID) { + *thread = BrowserThread::UI; + } +#endif +} + +bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilter, message) +#if defined(OS_WIN) + IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection) +#endif +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + IPC_MESSAGE_HANDLER(PrintHostMsg_AllocateTempFileForPrinting, + OnAllocateTempFileForPrinting) + IPC_MESSAGE_HANDLER(PrintHostMsg_TempFileForPrintingWritten, + OnTempFileForPrintingWritten) +#endif + IPC_MESSAGE_HANDLER(PrintHostMsg_IsPrintingEnabled, OnIsPrintingEnabled) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings, + OnGetDefaultPrintSettings) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint) + IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings, + OnUpdatePrintSettings) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +#if defined(OS_WIN) +void PrintingMessageFilter::OnDuplicateSection( + base::SharedMemoryHandle renderer_handle, + base::SharedMemoryHandle* browser_handle) { + // Duplicate the handle in this process right now so the memory is kept alive + // (even if it is not mapped) + base::SharedMemory shared_buf(renderer_handle, true, PeerHandle()); + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle); +} +#endif + +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +void PrintingMessageFilter::OnAllocateTempFileForPrinting( + int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number) { +#if defined(OS_CHROMEOS) + // TODO(thestig): Use |render_view_id| for Chrome OS. + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + temp_file_fd->fd = *sequence_number = -1; + temp_file_fd->auto_close = false; + + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + *sequence_number = g_printing_file_descriptor_map.Get().sequence++; + + base::FilePath path; + if (base::CreateTemporaryFile(&path)) { + int fd = open(path.value().c_str(), O_WRONLY); + if (fd >= 0) { + SequenceToPathMap::iterator it = map->find(*sequence_number); + if (it != map->end()) { + NOTREACHED() << "Sequence number already in use. seq=" << + *sequence_number; + } else { + (*map)[*sequence_number] = path; + temp_file_fd->fd = fd; + temp_file_fd->auto_close = true; + } + } + } +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + printing::PrintViewManagerBasic* print_view_manager = + printing::PrintViewManagerBasic::FromWebContents(wc); + // The file descriptor is originally created in & passed from the Android + // side, and it will handle the closing. + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + temp_file_fd->fd = file_descriptor.fd; + temp_file_fd->auto_close = false; +#endif +} + +void PrintingMessageFilter::OnTempFileForPrintingWritten(int render_view_id, + int sequence_number) { +#if defined(OS_CHROMEOS) + DCHECK_CURRENTLY_ON(BrowserThread::FILE); + SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; + SequenceToPathMap::iterator it = map->find(sequence_number); + if (it == map->end()) { + NOTREACHED() << "Got a sequence that we didn't pass to the " + "renderer: " << sequence_number; + return; + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::CreatePrintDialogForFile, + this, render_view_id, it->second)); + + // Erase the entry in the map. + map->erase(it); +#elif defined(OS_ANDROID) + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + printing::PrintViewManagerBasic* print_view_manager = + printing::PrintViewManagerBasic::FromWebContents(wc); + const base::FileDescriptor& file_descriptor = + print_view_manager->file_descriptor(); + printing::PrintingContextAndroid::PdfWritingDone(file_descriptor.fd, true); + // Invalidate the file descriptor so it doesn't accidentally get reused. + print_view_manager->set_file_descriptor(base::FileDescriptor(-1, false)); +#endif +} +#endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) + +#if defined(OS_CHROMEOS) +void PrintingMessageFilter::CreatePrintDialogForFile( + int render_view_id, + const base::FilePath& path) { + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + print_dialog_cloud::CreatePrintDialogForFile( + wc->GetBrowserContext(), + wc->GetTopLevelNativeWindow(), + path, + wc->GetTitle(), + base::string16(), + std::string("application/pdf")); +} +#endif // defined(OS_CHROMEOS) + +content::WebContents* PrintingMessageFilter::GetWebContentsForRenderView( + int render_view_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::RenderViewHost* view = content::RenderViewHost::FromID( + render_process_id_, render_view_id); + return view ? content::WebContents::FromRenderViewHost(view) : NULL; +} + +struct PrintingMessageFilter::GetPrintSettingsForRenderViewParams { + printing::PrinterQuery::GetSettingsAskParam ask_user_for_settings; + int expected_page_count; + bool has_selection; + printing::MarginType margin_type; +}; + +void PrintingMessageFilter::GetPrintSettingsForRenderView( + int render_view_id, + GetPrintSettingsForRenderViewParams params, + const base::Closure& callback, + scoped_refptr printer_query) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (wc) { + scoped_ptr wc_observer( + new PrintingUIWebContentsObserver(wc)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&printing::PrinterQuery::GetSettings, printer_query, + params.ask_user_for_settings, base::Passed(&wc_observer), + params.expected_page_count, params.has_selection, + params.margin_type, callback)); + } else { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&PrintingMessageFilter::OnGetPrintSettingsFailed, this, + callback, printer_query)); + } +} + +void PrintingMessageFilter::OnGetPrintSettingsFailed( + const base::Closure& callback, + scoped_refptr printer_query) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + printer_query->GetSettingsDone(printing::PrintSettings(), + printing::PrintingContext::FAILED); + callback.Run(); +} + +void PrintingMessageFilter::OnIsPrintingEnabled(bool* is_enabled) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + *is_enabled = true; +} + +void PrintingMessageFilter::OnGetDefaultPrintSettings(IPC::Message* reply_msg) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + scoped_refptr printer_query; + printer_query = queue_->PopPrinterQuery(0); + if (!printer_query) + printer_query = queue_->CreatePrinterQuery(); + + // Loads default settings. This is asynchronous, only the IPC message sender + // will hang until the settings are retrieved. + GetPrintSettingsForRenderViewParams params; + params.ask_user_for_settings = printing::PrinterQuery::DEFAULTS; + params.expected_page_count = 0; + params.has_selection = false; + params.margin_type = printing::DEFAULT_MARGINS; + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, + reply_msg->routing_id(), params, + base::Bind(&PrintingMessageFilter::OnGetDefaultPrintSettingsReply, + this, printer_query, reply_msg), + printer_query)); +} + +void PrintingMessageFilter::OnGetDefaultPrintSettingsReply( + scoped_refptr printer_query, + IPC::Message* reply_msg) { + PrintMsg_Print_Params params; + if (!printer_query.get() || + printer_query->last_status() != printing::PrintingContext::OK) { + params.Reset(); + } else { + RenderParamsFromPrintSettings(printer_query->settings(), ¶ms); + params.document_cookie = printer_query->cookie(); + } + PrintHostMsg_GetDefaultPrintSettings::WriteReplyParams(reply_msg, params); + Send(reply_msg); + // If printing was enabled. + if (printer_query.get()) { + // If user hasn't cancelled. + if (printer_query->cookie() && printer_query->settings().dpi()) { + queue_->QueuePrinterQuery(printer_query.get()); + } else { + printer_query->StopWorker(); + } + } +} + +void PrintingMessageFilter::OnScriptedPrint( + const PrintHostMsg_ScriptedPrint_Params& params, + IPC::Message* reply_msg) { + scoped_refptr printer_query = + queue_->PopPrinterQuery(params.cookie); + if (!printer_query) + printer_query = queue_->CreatePrinterQuery(); + GetPrintSettingsForRenderViewParams settings_params; + settings_params.ask_user_for_settings = printing::PrinterQuery::ASK_USER; + settings_params.expected_page_count = params.expected_pages_count; + settings_params.has_selection = params.has_selection; + settings_params.margin_type = params.margin_type; + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::GetPrintSettingsForRenderView, this, + reply_msg->routing_id(), settings_params, + base::Bind(&PrintingMessageFilter::OnScriptedPrintReply, this, + printer_query, reply_msg), + printer_query)); +} + +void PrintingMessageFilter::OnScriptedPrintReply( + scoped_refptr printer_query, + IPC::Message* reply_msg) { + PrintMsg_PrintPages_Params params; +#if defined(OS_ANDROID) + // We need to save the routing ID here because Send method below deletes the + // |reply_msg| before we can get the routing ID for the Android code. + int routing_id = reply_msg->routing_id(); +#endif + if (printer_query->last_status() != printing::PrintingContext::OK || + !printer_query->settings().dpi()) { + params.Reset(); + } else { + RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); + params.params.document_cookie = printer_query->cookie(); + params.pages = + printing::PageRange::GetPages(printer_query->settings().ranges()); + } + PrintHostMsg_ScriptedPrint::WriteReplyParams(reply_msg, params); + Send(reply_msg); + if (params.params.dpi && params.params.document_cookie) { +#if defined(OS_ANDROID) + int file_descriptor; + const base::string16& device_name = printer_query->settings().device_name(); + if (base::StringToInt(device_name, &file_descriptor)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&PrintingMessageFilter::UpdateFileDescriptor, this, + routing_id, file_descriptor)); + } +#endif + queue_->QueuePrinterQuery(printer_query.get()); + } else { + printer_query->StopWorker(); + } +} + +#if defined(OS_ANDROID) +void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + content::WebContents* wc = GetWebContentsForRenderView(render_view_id); + if (!wc) + return; + printing::PrintViewManagerBasic* print_view_manager = + printing::PrintViewManagerBasic::FromWebContents(wc); + print_view_manager->set_file_descriptor(base::FileDescriptor(fd, false)); +} +#endif + +void PrintingMessageFilter::OnUpdatePrintSettings( + int document_cookie, const base::DictionaryValue& job_settings, + IPC::Message* reply_msg) { + scoped_refptr printer_query; + printer_query = queue_->PopPrinterQuery(document_cookie); + if (!printer_query) + printer_query = queue_->CreatePrinterQuery(); + printer_query->SetSettings( + job_settings, + base::Bind(&PrintingMessageFilter::OnUpdatePrintSettingsReply, this, + printer_query, reply_msg)); +} + +void PrintingMessageFilter::OnUpdatePrintSettingsReply( + scoped_refptr printer_query, + IPC::Message* reply_msg) { + PrintMsg_PrintPages_Params params; + if (!printer_query.get() || + printer_query->last_status() != printing::PrintingContext::OK) { + params.Reset(); + } else { + RenderParamsFromPrintSettings(printer_query->settings(), ¶ms.params); + params.params.document_cookie = printer_query->cookie(); + params.pages = + printing::PageRange::GetPages(printer_query->settings().ranges()); + } + PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params); + Send(reply_msg); + // If user hasn't cancelled. + if (printer_query.get()) { + if (printer_query->cookie() && printer_query->settings().dpi()) { + queue_->QueuePrinterQuery(printer_query.get()); + } else { + printer_query->StopWorker(); + } + } +} diff --git a/libcef/browser/printing/printing_message_filter.h b/libcef/browser/printing/printing_message_filter.h new file mode 100644 index 000000000..da1e058a1 --- /dev/null +++ b/libcef/browser/printing/printing_message_filter.h @@ -0,0 +1,131 @@ +// 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_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_ +#define CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_ + +#include + +#include "base/compiler_specific.h" +#include "content/public/browser/browser_message_filter.h" + +#if defined(OS_WIN) +#include "base/memory/shared_memory.h" +#endif + +struct PrintHostMsg_ScriptedPrint_Params; + +namespace base { +class DictionaryValue; +class FilePath; +} + +namespace content { +class WebContents; +} + +namespace printing { +class PrinterQuery; +class PrintJobManager; +class PrintQueriesQueue; +} + +// This class filters out incoming printing related IPC messages for the +// renderer process on the IPC thread. +class PrintingMessageFilter : public content::BrowserMessageFilter { + public: + explicit PrintingMessageFilter(int render_process_id); + + // content::BrowserMessageFilter methods. + virtual void OverrideThreadForMessage( + const IPC::Message& message, + content::BrowserThread::ID* thread) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + private: + virtual ~PrintingMessageFilter(); + +#if defined(OS_WIN) + // Used to pass resulting EMF from renderer to browser in printing. + void OnDuplicateSection(base::SharedMemoryHandle renderer_handle, + base::SharedMemoryHandle* browser_handle); +#endif + +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) + // Used to ask the browser allocate a temporary file for the renderer + // to fill in resulting PDF in renderer. + void OnAllocateTempFileForPrinting(int render_view_id, + base::FileDescriptor* temp_file_fd, + int* sequence_number); + void OnTempFileForPrintingWritten(int render_view_id, int sequence_number); +#endif + +#if defined(OS_CHROMEOS) + void CreatePrintDialogForFile(int render_view_id, const base::FilePath& path); +#endif + +#if defined(OS_ANDROID) + // Updates the file descriptor for the PrintViewManagerBasic of a given + // render_view_id. + void UpdateFileDescriptor(int render_view_id, int fd); +#endif + + // Given a render_view_id get the corresponding WebContents. + // Must be called on the UI thread. + content::WebContents* GetWebContentsForRenderView(int render_view_id); + + // GetPrintSettingsForRenderView must be called via PostTask and + // base::Bind. Collapse the settings-specific params into a + // struct to avoid running into issues with too many params + // to base::Bind. + struct GetPrintSettingsForRenderViewParams; + + // Retrieve print settings. Uses |render_view_id| to get a parent + // for any UI created if needed. + void GetPrintSettingsForRenderView( + int render_view_id, + GetPrintSettingsForRenderViewParams params, + const base::Closure& callback, + scoped_refptr printer_query); + + void OnGetPrintSettingsFailed( + const base::Closure& callback, + scoped_refptr printer_query); + + // Checks if printing is enabled. + void OnIsPrintingEnabled(bool* is_enabled); + + // Get the default print setting. + void OnGetDefaultPrintSettings(IPC::Message* reply_msg); + void OnGetDefaultPrintSettingsReply( + scoped_refptr printer_query, + IPC::Message* reply_msg); + + // The renderer host have to show to the user the print dialog and returns + // the selected print settings. The task is handled by the print worker + // thread and the UI thread. The reply occurs on the IO thread. + void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& params, + IPC::Message* reply_msg); + void OnScriptedPrintReply( + scoped_refptr printer_query, + IPC::Message* reply_msg); + + // Modify the current print settings based on |job_settings|. The task is + // handled by the print worker thread and the UI thread. The reply occurs on + // the IO thread. + void OnUpdatePrintSettings(int document_cookie, + const base::DictionaryValue& job_settings, + IPC::Message* reply_msg); + void OnUpdatePrintSettingsReply( + scoped_refptr printer_query, + IPC::Message* reply_msg); + + const int render_process_id_; + + scoped_refptr queue_; + + DISALLOW_COPY_AND_ASSIGN(PrintingMessageFilter); +}; + +#endif // CEF_LIBCEF_BROWSER_PRINTING_PRINTING_MESSAGE_FILTER_H_ diff --git a/libcef/browser/process_util_impl.cc b/libcef/browser/process_util_impl.cc new file mode 100644 index 000000000..c73dea79d --- /dev/null +++ b/libcef/browser/process_util_impl.cc @@ -0,0 +1,31 @@ +// 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 "include/cef_process_util.h" +#include "libcef/common/command_line_impl.h" + +#include "base/logging.h" +#include "base/process/launch.h" +#include "content/public/browser/browser_thread.h" + +bool CefLaunchProcess(CefRefPtr command_line) { + if (!command_line.get()) { + NOTREACHED() << "invalid parameter"; + return false; + } + + if (!content::BrowserThread::CurrentlyOn( + content::BrowserThread::PROCESS_LAUNCHER)) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + CefCommandLineImpl* impl = + static_cast(command_line.get()); + + CefValueController::AutoLock lock_scope(impl->controller()); + + base::LaunchOptions options; + return base::LaunchProcess(impl->command_line(), options, NULL); +} diff --git a/libcef/browser/proxy_stubs.cc b/libcef/browser/proxy_stubs.cc new file mode 100644 index 000000000..98ba2d75a --- /dev/null +++ b/libcef/browser/proxy_stubs.cc @@ -0,0 +1,18 @@ +// 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 "base/logging.h" +#include "components/pref_registry/pref_registry_syncable.h" + +namespace user_prefs { + +// Required by PrefProxyConfigTrackerImpl::RegisterUserPrefs. +void PrefRegistrySyncable::RegisterDictionaryPref( + const char* path, + base::DictionaryValue* default_value, + PrefSyncStatus sync_status) { + NOTREACHED(); +} + +} // namespace user_prefs diff --git a/libcef/browser/render_widget_host_view_osr.cc b/libcef/browser/render_widget_host_view_osr.cc new file mode 100644 index 000000000..788042162 --- /dev/null +++ b/libcef/browser/render_widget_host_view_osr.cc @@ -0,0 +1,1081 @@ +// 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 "libcef/browser/render_widget_host_view_osr.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/thread_util.h" + +#include "base/callback_helpers.h" +#include "cc/output/copy_output_request.h" +#include "content/browser/compositor/image_transport_factory.h" +#include "content/browser/compositor/resize_lock.h" +#include "content/browser/renderer_host/dip_util.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/common/gpu/client/gl_helper.h" +#include "content/public/browser/context_factory.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view_frame_subscriber.h" +#include "third_party/WebKit/public/platform/WebScreenInfo.h" +#include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/image/image_skia_operations.h" + +namespace { + +const float kDefaultScaleFactor = 1.0; + +// The rate at which new calls to OnPaint will be generated. +const int kDefaultFrameRate = 30; +const int kMaximumFrameRate = 60; + +// The maximum number of retry counts if frame capture fails. +const int kFrameRetryLimit = 2; + +// When accelerated compositing is enabled and a widget resize is pending, +// we delay further resizes of the UI. The following constant is the maximum +// length of time that we should delay further UI resizes while waiting for a +// resized frame from a renderer. +const int kResizeLockTimeoutMs = 67; + +static blink::WebScreenInfo webScreenInfoFrom(const CefScreenInfo& src) { + blink::WebScreenInfo webScreenInfo; + webScreenInfo.deviceScaleFactor = src.device_scale_factor; + webScreenInfo.depth = src.depth; + webScreenInfo.depthPerComponent = src.depth_per_component; + webScreenInfo.isMonochrome = src.is_monochrome ? true : false; + webScreenInfo.rect = blink::WebRect(src.rect.x, src.rect.y, + src.rect.width, src.rect.height); + webScreenInfo.availableRect = blink::WebRect(src.available_rect.x, + src.available_rect.y, + src.available_rect.width, + src.available_rect.height); + + return webScreenInfo; +} + +// Root layer passed to the ui::Compositor. +class CefRootLayer : public ui::Layer, public ui::LayerDelegate { + public: + CefRootLayer() + : Layer(ui::LAYER_TEXTURED) { + set_delegate(this); + } + + virtual ~CefRootLayer() { } + + // Overridden from LayerDelegate: + virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { + } + + virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { + } + + virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { + return base::Closure(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(CefRootLayer); +}; + +// Used to prevent further resizes while a resize is pending. +class CefResizeLock : public content::ResizeLock { + public: + CefResizeLock(CefRenderWidgetHostViewOSR* host, + const gfx::Size new_size, + bool defer_compositor_lock, + double timeout) + : ResizeLock(new_size, defer_compositor_lock), + host_(host), + cancelled_(false), + weak_ptr_factory_(this) { + DCHECK(host_); + host_->HoldResize(); + + CEF_POST_DELAYED_TASK( + CEF_UIT, + base::Bind(&CefResizeLock::CancelLock, + weak_ptr_factory_.GetWeakPtr()), + timeout); + } + + virtual ~CefResizeLock() { + CancelLock(); + } + + virtual bool GrabDeferredLock() OVERRIDE { + return ResizeLock::GrabDeferredLock(); + } + + virtual void UnlockCompositor() OVERRIDE { + ResizeLock::UnlockCompositor(); + compositor_lock_ = NULL; + } + + protected: + virtual void LockCompositor() OVERRIDE { + ResizeLock::LockCompositor(); + compositor_lock_ = host_->compositor()->GetCompositorLock(); + } + + void CancelLock() { + if (cancelled_) + return; + cancelled_ = true; + UnlockCompositor(); + host_->ReleaseResize(); + } + + private: + CefRenderWidgetHostViewOSR* host_; + scoped_refptr compositor_lock_; + bool cancelled_; + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CefResizeLock); +}; + +} // namespace + +CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( + content::RenderWidgetHost* widget) + : delegated_frame_host_(new content::DelegatedFrameHost(this)), + compositor_widget_(gfx::kNullAcceleratedWidget), + frame_rate_threshold_ms_(1000 / kDefaultFrameRate), + frame_pending_(false), + frame_in_progress_(false), + frame_retry_count_(0), + hold_resize_(false), + pending_resize_(false), + render_widget_host_(content::RenderWidgetHostImpl::From(widget)), + parent_host_view_(NULL), + popup_host_view_(NULL), + is_showing_(false), + is_destroyed_(false), +#if defined(OS_MACOSX) + text_input_context_osr_mac_(NULL), +#endif + weak_ptr_factory_(this) { + DCHECK(render_widget_host_); + render_widget_host_->SetView(this); + + // CefBrowserHostImpl might not be created at this time for popups. + if (render_widget_host_->IsRenderView()) { + browser_impl_ = CefBrowserHostImpl::GetBrowserForHost( + content::RenderViewHost::From(render_widget_host_)); + } + + root_layer_.reset(new CefRootLayer); + + PlatformCreateCompositorWidget(); +#if !defined(OS_MACOSX) + // On OS X the ui::Compositor is created/owned by the platform view. + compositor_.reset( + new ui::Compositor(compositor_widget_, content::GetContextFactory())); +#endif + compositor_->SetRootLayer(root_layer_.get()); + + if (browser_impl_) { + SetFrameRate(); + ResizeRootLayer(); + compositor_->SetScaleAndSize(CurrentDeviceScaleFactor(), + root_layer_->bounds().size()); + } +} + +CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { + delegated_frame_host_.reset(NULL); + compositor_.reset(NULL); + PlatformDestroyCompositorWidget(); + root_layer_.reset(NULL); +} + +void CefRenderWidgetHostViewOSR::InitAsChild(gfx::NativeView parent_view) { +} + +content::RenderWidgetHost* + CefRenderWidgetHostViewOSR::GetRenderWidgetHost() const { + return render_widget_host_; +} + +void CefRenderWidgetHostViewOSR::SetSize(const gfx::Size& size) { +} + +void CefRenderWidgetHostViewOSR::SetBounds(const gfx::Rect& rect) { +} + +gfx::NativeView CefRenderWidgetHostViewOSR::GetNativeView() const { + return gfx::NativeView(); +} + +gfx::NativeViewId CefRenderWidgetHostViewOSR::GetNativeViewId() const { + return gfx::NativeViewId(); +} + +gfx::NativeViewAccessible + CefRenderWidgetHostViewOSR::GetNativeViewAccessible() { + return gfx::NativeViewAccessible(); +} + +ui::TextInputClient* CefRenderWidgetHostViewOSR::GetTextInputClient() { + return NULL; +} + +void CefRenderWidgetHostViewOSR::Focus() { +} + +bool CefRenderWidgetHostViewOSR::HasFocus() const { + return false; +} + +bool CefRenderWidgetHostViewOSR::IsSurfaceAvailableForCopy() const { + return delegated_frame_host_->CanCopyToBitmap(); +} + +void CefRenderWidgetHostViewOSR::Show() { + WasShown(); +} + +void CefRenderWidgetHostViewOSR::Hide() { + WasHidden(); +} + +bool CefRenderWidgetHostViewOSR::IsShowing() { + return is_showing_; +} + +gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() const { + if (IsPopupWidget()) + return popup_position_; + + if (!browser_impl_) + return gfx::Rect(); + + CefRect rc; + browser_impl_->GetClient()->GetRenderHandler()->GetViewRect( + browser_impl_.get(), rc); + return gfx::Rect(rc.x, rc.y, rc.width, rc.height); +} + +void CefRenderWidgetHostViewOSR::SetBackgroundOpaque(bool opaque) { + content::RenderWidgetHostViewBase::SetBackgroundOpaque(opaque); + if (render_widget_host_) + render_widget_host_->SetBackgroundOpaque(opaque); +} + +bool CefRenderWidgetHostViewOSR::LockMouse() { + return false; +} + +void CefRenderWidgetHostViewOSR::UnlockMouse() { +} + +void CefRenderWidgetHostViewOSR::OnSwapCompositorFrame( + uint32 output_surface_id, + scoped_ptr frame) { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::OnSwapCompositorFrame"); + if (frame->delegated_frame_data) { + delegated_frame_host_->SwapDelegatedFrame( + output_surface_id, + frame->delegated_frame_data.Pass(), + frame->metadata.device_scale_factor, + frame->metadata.latency_info); + + GenerateFrame(true); + return; + } + + if (frame->software_frame_data) { + DLOG(ERROR) << "Unable to use software frame in CEF windowless rendering"; + if (render_widget_host_) + render_widget_host_->GetProcess()->ReceivedBadMessage(); + return; + } +} + +void CefRenderWidgetHostViewOSR::InitAsPopup( + content::RenderWidgetHostView* parent_host_view, + const gfx::Rect& pos) { + parent_host_view_ = static_cast( + parent_host_view); + browser_impl_ = parent_host_view_->browser_impl(); + if (!browser_impl_) + return; + + if (parent_host_view_->popup_host_view_) { + // Cancel the previous popup widget. + parent_host_view_->popup_host_view_->CancelPopupWidget(); + } + + parent_host_view_->set_popup_host_view(this); + browser_impl_->GetClient()->GetRenderHandler()->OnPopupShow( + browser_impl_.get(), true); + + popup_position_ = pos; + + const float scale_factor = CurrentDeviceScaleFactor(); + const gfx::Rect scaled_size = + gfx::ToNearestRect(gfx::ScaleRect(pos, scale_factor)); + + CefRect widget_pos(scaled_size.x(), scaled_size.y(), + scaled_size.width(), scaled_size.height()); + browser_impl_->GetClient()->GetRenderHandler()->OnPopupSize( + browser_impl_.get(), widget_pos); + + SetFrameRate(); + ResizeRootLayer(); + compositor_->SetScaleAndSize(scale_factor, root_layer_->bounds().size()); + + WasShown(); +} + +void CefRenderWidgetHostViewOSR::InitAsFullscreen( + content::RenderWidgetHostView* reference_host_view) { + NOTREACHED() << "Fullscreen widgets are not supported in OSR"; +} + +void CefRenderWidgetHostViewOSR::WasShown() { + if (is_showing_) + return; + + is_showing_ = true; + if (render_widget_host_) + render_widget_host_->WasShown(); + delegated_frame_host_->AddedToWindow(); + delegated_frame_host_->WasShown(); +} + +void CefRenderWidgetHostViewOSR::WasHidden() { + if (!is_showing_) + return; + + if (browser_impl_) + browser_impl_->CancelContextMenu(); + + if (render_widget_host_) + render_widget_host_->WasHidden(); + delegated_frame_host_->WasHidden(); + delegated_frame_host_->RemovingFromWindow(); + is_showing_ = false; +} + +void CefRenderWidgetHostViewOSR::MovePluginWindows( + const std::vector& moves) { +} + +void CefRenderWidgetHostViewOSR::Blur() { +} + +void CefRenderWidgetHostViewOSR::UpdateCursor( + const content::WebCursor& cursor) { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::UpdateCursor"); + if (!browser_impl_) + return; + +#if defined(USE_AURA) + content::WebCursor web_cursor = cursor; + + ui::PlatformCursor platform_cursor; + if (web_cursor.IsCustom()) { + // |web_cursor| owns the resulting |platform_cursor|. + platform_cursor = web_cursor.GetPlatformCursor(); + } else { + content::WebCursor::CursorInfo cursor_info; + cursor.GetCursorInfo(&cursor_info); + platform_cursor = browser_impl_->GetPlatformCursor(cursor_info.type); + } + + browser_impl_->GetClient()->GetRenderHandler()->OnCursorChange( + browser_impl_.get(), platform_cursor); +#elif defined(OS_MACOSX) + // |web_cursor| owns the resulting |native_cursor|. + content::WebCursor web_cursor = cursor; + CefCursorHandle native_cursor = web_cursor.GetNativeCursor(); + browser_impl_->GetClient()->GetRenderHandler()->OnCursorChange( + browser_impl_.get(), native_cursor); +#else + // TODO(port): Implement this method to work on other platforms as part of + // off-screen rendering support. + NOTREACHED(); +#endif +} + +void CefRenderWidgetHostViewOSR::SetIsLoading(bool is_loading) { +} + +#if !defined(OS_MACOSX) +void CefRenderWidgetHostViewOSR::TextInputStateChanged( + const ViewHostMsg_TextInputState_Params& params) { +} + +void CefRenderWidgetHostViewOSR::ImeCancelComposition() { +} +#endif // !defined(OS_MACOSX) + +void CefRenderWidgetHostViewOSR::RenderProcessGone( + base::TerminationStatus status, + int error_code) { + // TODO(OSR): Need to also clear WebContentsViewOSR::view_? + render_widget_host_ = NULL; + parent_host_view_ = NULL; + popup_host_view_ = NULL; +} + +void CefRenderWidgetHostViewOSR::Destroy() { + if (!is_destroyed_) { + is_destroyed_ = true; + + if (IsPopupWidget()) { + CancelPopupWidget(); + } else { + if (popup_host_view_) + popup_host_view_->CancelPopupWidget(); + WasHidden(); + } + } + + delete this; +} + +void CefRenderWidgetHostViewOSR::SetTooltipText( + const base::string16& tooltip_text) { + if (!browser_impl_) + return; + + CefString tooltip(tooltip_text); + CefRefPtr handler = + browser_impl_->GetClient()->GetDisplayHandler(); + if (handler.get()) { + handler->OnTooltip(browser_impl_.get(), tooltip); + } +} + +void CefRenderWidgetHostViewOSR::SelectionChanged( + const base::string16& text, + size_t offset, + const gfx::Range& range) { +} + +gfx::Size CefRenderWidgetHostViewOSR::GetRequestedRendererSize() const { + return delegated_frame_host_->GetRequestedRendererSize(); +} + +gfx::Size CefRenderWidgetHostViewOSR::GetPhysicalBackingSize() const { + float scale_factor = const_cast(this)-> + CurrentDeviceScaleFactor(); + return gfx::ToCeiledSize(gfx::ScaleSize(GetRequestedRendererSize(), + scale_factor)); +} + +void CefRenderWidgetHostViewOSR::SelectionBoundsChanged( + const ViewHostMsg_SelectionBounds_Params& params) { +} + +void CefRenderWidgetHostViewOSR::ScrollOffsetChanged() { + if (!browser_impl_) + return; + + browser_impl_->GetClient()->GetRenderHandler()-> + OnScrollOffsetChanged(browser_impl_.get()); +} + +void CefRenderWidgetHostViewOSR::CopyFromCompositingSurface( + const gfx::Rect& src_subrect, + const gfx::Size& dst_size, + const base::Callback& callback, + const SkBitmap::Config config) { + delegated_frame_host_->CopyFromCompositingSurface( + src_subrect, dst_size, callback, config); +} + +void CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceToVideoFrame( + const gfx::Rect& src_subrect, + const scoped_refptr& target, + const base::Callback& callback) { + delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame( + src_subrect, target, callback); +} + +bool CefRenderWidgetHostViewOSR::CanCopyToVideoFrame() const { + return delegated_frame_host_->CanCopyToVideoFrame(); +} + +bool CefRenderWidgetHostViewOSR::CanSubscribeFrame() const { + return delegated_frame_host_->CanSubscribeFrame(); +} + +void CefRenderWidgetHostViewOSR::BeginFrameSubscription( + scoped_ptr subscriber) { + delegated_frame_host_->BeginFrameSubscription(subscriber.Pass()); +} + +void CefRenderWidgetHostViewOSR::EndFrameSubscription() { + delegated_frame_host_->EndFrameSubscription(); +} + +void CefRenderWidgetHostViewOSR::AcceleratedSurfaceInitialized( + int host_id, + int route_id) { +} + +void CefRenderWidgetHostViewOSR::AcceleratedSurfaceBuffersSwapped( + const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, + int gpu_host_id) { + // Oldschool composited mode is no longer supported. +} + +void CefRenderWidgetHostViewOSR::AcceleratedSurfacePostSubBuffer( + const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, + int gpu_host_id) { + // Oldschool composited mode is no longer supported. +} + +void CefRenderWidgetHostViewOSR::AcceleratedSurfaceSuspend() { +} + +void CefRenderWidgetHostViewOSR::AcceleratedSurfaceRelease() { +} + +bool CefRenderWidgetHostViewOSR::HasAcceleratedSurface( + const gfx::Size& desired_size) { + // CEF doesn't use GetBackingStore for accelerated pages, so it doesn't + // matter what is returned here as GetBackingStore is the only caller of this + // method. + NOTREACHED(); + return false; +} + +void CefRenderWidgetHostViewOSR::GetScreenInfo(blink::WebScreenInfo* results) { + if (!browser_impl_) + return; + + CefScreenInfo screen_info( + kDefaultScaleFactor, 0, 0, false, CefRect(), CefRect()); + + CefRefPtr handler = + browser_impl_->client()->GetRenderHandler(); + if (!handler->GetScreenInfo(browser_impl_.get(), screen_info) || + screen_info.rect.width == 0 || + screen_info.rect.height == 0 || + screen_info.available_rect.width == 0 || + screen_info.available_rect.height == 0) { + // If a screen rectangle was not provided, try using the view rectangle + // instead. Otherwise, popup views may be drawn incorrectly, or not at all. + CefRect screenRect; + if (!handler->GetViewRect(browser_impl_.get(), screenRect)) { + NOTREACHED(); + screenRect = CefRect(); + } + + if (screen_info.rect.width == 0 && screen_info.rect.height == 0) + screen_info.rect = screenRect; + + if (screen_info.available_rect.width == 0 && + screen_info.available_rect.height == 0) + screen_info.available_rect = screenRect; + } + + *results = webScreenInfoFrom(screen_info); +} + +gfx::Rect CefRenderWidgetHostViewOSR::GetBoundsInRootWindow() { + if (!browser_impl_) + return gfx::Rect(); + + CefRect rc; + if (browser_impl_->GetClient()->GetRenderHandler()->GetRootScreenRect( + browser_impl_.get(), rc)) { + return gfx::Rect(rc.x, rc.y, rc.width, rc.height); + } + return gfx::Rect(); +} + +gfx::GLSurfaceHandle CefRenderWidgetHostViewOSR::GetCompositingSurface() { + return content::ImageTransportFactory::GetInstance()-> + GetSharedSurfaceHandle(); +} + +#if !defined(OS_MACOSX) && defined(USE_AURA) +void CefRenderWidgetHostViewOSR::ImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector& character_bounds) { +} +#endif + +ui::Compositor* CefRenderWidgetHostViewOSR::GetCompositor() const { + return compositor_.get(); +} + +ui::Layer* CefRenderWidgetHostViewOSR::GetLayer() { + return root_layer_.get(); +} + +content::RenderWidgetHostImpl* CefRenderWidgetHostViewOSR::GetHost() { + return render_widget_host_; +} + +void CefRenderWidgetHostViewOSR::SchedulePaintInRect( + const gfx::Rect& damage_rect_in_dip) { + root_layer_->SchedulePaint(damage_rect_in_dip); +} + +bool CefRenderWidgetHostViewOSR::IsVisible() { + return IsShowing(); +} + +scoped_ptr CefRenderWidgetHostViewOSR::CreateResizeLock( + bool defer_compositor_lock) { + const gfx::Size& desired_size = root_layer_->bounds().size(); + return scoped_ptr(new CefResizeLock( + this, + desired_size, + defer_compositor_lock, + kResizeLockTimeoutMs)); +} + +gfx::Size CefRenderWidgetHostViewOSR::DesiredFrameSize() { + return root_layer_->bounds().size(); +} + +float CefRenderWidgetHostViewOSR::CurrentDeviceScaleFactor() { + if (!browser_impl_) + return kDefaultScaleFactor; + + CefScreenInfo screen_info( + kDefaultScaleFactor, 0, 0, false, CefRect(), CefRect()); + if (!browser_impl_->GetClient()->GetRenderHandler()->GetScreenInfo( + browser_impl_.get(), screen_info)) { + // Use the default + return kDefaultScaleFactor; + } + + return screen_info.device_scale_factor; +} + +gfx::Size CefRenderWidgetHostViewOSR::ConvertViewSizeToPixel( + const gfx::Size& size) { + return content::ConvertViewSizeToPixel(this, size); +} + +content::DelegatedFrameHost* + CefRenderWidgetHostViewOSR::GetDelegatedFrameHost() const { + return delegated_frame_host_.get(); +} + +bool CefRenderWidgetHostViewOSR::InstallTransparency() { + if (browser_impl_ && browser_impl_->IsTransparent()) { + SetBackgroundOpaque(false); + return true; + } + return false; +} + +void CefRenderWidgetHostViewOSR::WasResized() { + if (hold_resize_) { + if (!pending_resize_) + pending_resize_ = true; + return; + } + + ResizeRootLayer(); + if (render_widget_host_) + render_widget_host_->WasResized(); + delegated_frame_host_->WasResized(); +} + +void CefRenderWidgetHostViewOSR::OnScreenInfoChanged() { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::OnScreenInfoChanged"); + if (!render_widget_host_) + return; + + // TODO(OSR): Update the backing store. + + render_widget_host_->NotifyScreenInfoChanged(); + // We might want to change the cursor scale factor here as well - see the + // cache for the current_cursor_, as passed by UpdateCursor from the renderer + // in the rwhv_aura (current_cursor_.SetScaleFactor) +} + +void CefRenderWidgetHostViewOSR::Invalidate( + CefBrowserHost::PaintElementType type) { + TRACE_EVENT1("libcef", "CefRenderWidgetHostViewOSR::Invalidate", "type", + type); + if (!IsPopupWidget() && type == PET_POPUP) { + if (popup_host_view_) + popup_host_view_->Invalidate(type); + return; + } + + GenerateFrame(true); +} + +void CefRenderWidgetHostViewOSR::SendKeyEvent( + const content::NativeWebKeyboardEvent& event) { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::SendKeyEvent"); + if (!render_widget_host_) + return; + render_widget_host_->ForwardKeyboardEvent(event); +} + +void CefRenderWidgetHostViewOSR::SendMouseEvent( + const blink::WebMouseEvent& event) { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::SendMouseEvent"); + if (!IsPopupWidget()) { + if (browser_impl_ && event.type == blink::WebMouseEvent::MouseDown) + browser_impl_->CancelContextMenu(); + + if (popup_host_view_ && + popup_host_view_->popup_position_.Contains(event.x, event.y)) { + blink::WebMouseEvent popup_event(event); + popup_event.x -= popup_host_view_->popup_position_.x(); + popup_event.y -= popup_host_view_->popup_position_.y(); + popup_event.windowX = popup_event.x; + popup_event.windowY = popup_event.y; + + popup_host_view_->SendMouseEvent(popup_event); + return; + } + } + if (!render_widget_host_) + return; + render_widget_host_->ForwardMouseEvent(event); +} + +void CefRenderWidgetHostViewOSR::SendMouseWheelEvent( + const blink::WebMouseWheelEvent& event) { + TRACE_EVENT0("libcef", "CefRenderWidgetHostViewOSR::SendMouseWheelEvent"); + if (!IsPopupWidget()) { + if (browser_impl_) + browser_impl_->CancelContextMenu(); + + if (popup_host_view_) { + if (popup_host_view_->popup_position_.Contains(event.x, event.y)) { + blink::WebMouseWheelEvent popup_event(event); + popup_event.x -= popup_host_view_->popup_position_.x(); + popup_event.y -= popup_host_view_->popup_position_.y(); + popup_event.windowX = popup_event.x; + popup_event.windowY = popup_event.y; + popup_host_view_->SendMouseWheelEvent(popup_event); + return; + } else { + // Scrolling outside of the popup widget so destroy it. + // Execute asynchronously to avoid deleting the widget from inside some + // other callback. + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefRenderWidgetHostViewOSR::CancelPopupWidget, + popup_host_view_->weak_ptr_factory_.GetWeakPtr())); + } + } + } + if (!render_widget_host_) + return; + render_widget_host_->ForwardWheelEvent(event); +} + +void CefRenderWidgetHostViewOSR::SendFocusEvent(bool focus) { + if (!render_widget_host_) + return; + + content::RenderWidgetHostImpl* widget = + content::RenderWidgetHostImpl::From(render_widget_host_); + if (focus) { + widget->GotFocus(); + widget->SetActive(true); + } else { + if (browser_impl_) + browser_impl_->CancelContextMenu(); + + widget->SetActive(false); + widget->Blur(); + } +} + +void CefRenderWidgetHostViewOSR::HoldResize() { + if (!hold_resize_) + hold_resize_ = true; +} + +void CefRenderWidgetHostViewOSR::ReleaseResize() { + if (!hold_resize_) + return; + + hold_resize_ = false; + if (pending_resize_) { + pending_resize_ = false; + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefRenderWidgetHostViewOSR::WasResized, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void CefRenderWidgetHostViewOSR::SetFrameRate() { + if (!browser_impl_) + return; + int frame_rate = browser_impl_->settings().windowless_frame_rate; + if (frame_rate < 1) + frame_rate = kDefaultFrameRate; + else if (frame_rate > kMaximumFrameRate) + frame_rate = kMaximumFrameRate; + frame_rate_threshold_ms_ = 1000 / frame_rate; +} + +void CefRenderWidgetHostViewOSR::ResizeRootLayer() { + gfx::Size size; + if (!IsPopupWidget()) + size = GetViewBounds().size(); + else + size = popup_position_.size(); + root_layer_->SetBounds(gfx::Rect(0, 0, size.width(), size.height())); +} + +void CefRenderWidgetHostViewOSR::GenerateFrame(bool force_frame) { + if (force_frame && !frame_pending_) + frame_pending_ = true; + + // No frame needs to be generated at this time. + if (!frame_pending_) + return; + + // Don't attempt to generate a frame while one is currently in-progress. + if (frame_in_progress_) + return; + frame_in_progress_ = true; + + // Don't exceed the frame rate threshold. + const int64 frame_rate_delta = + (base::TimeTicks::Now() - frame_start_time_).InMilliseconds(); + if (frame_rate_delta < frame_rate_threshold_ms_) { + // Generate the frame after the necessary time has passed. + CEF_POST_DELAYED_TASK(CEF_UIT, + base::Bind(&CefRenderWidgetHostViewOSR::InternalGenerateFrame, + weak_ptr_factory_.GetWeakPtr()), + frame_rate_threshold_ms_ - frame_rate_delta); + return; + } + + InternalGenerateFrame(); +} + +void CefRenderWidgetHostViewOSR::InternalGenerateFrame() { + frame_pending_ = false; + frame_start_time_ = base::TimeTicks::Now(); + + // The below code is similar in functionality to + // DelegatedFrameHost::CopyFromCompositingSurface but we reuse the same + // SkBitmap in the GPU codepath and avoid scaling where possible. + scoped_ptr request = + cc::CopyOutputRequest::CreateRequest(base::Bind( + &CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceHasResult, + weak_ptr_factory_.GetWeakPtr())); + + const gfx::Rect& src_subrect_in_pixel = + content::ConvertRectToPixel(CurrentDeviceScaleFactor(), + root_layer_->bounds()); + request->set_area(src_subrect_in_pixel); + RequestCopyOfOutput(request.Pass()); +} + +void CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceHasResult( + scoped_ptr result) { + if (result->IsEmpty() || result->size().IsEmpty()) { + OnFrameCaptureFailure(); + return; + } + + if (result->HasTexture()) { + PrepareTextureCopyOutputResult(result.Pass()); + return; + } + + DCHECK(result->HasBitmap()); + PrepareBitmapCopyOutputResult(result.Pass()); +} + +void CefRenderWidgetHostViewOSR::PrepareTextureCopyOutputResult( + scoped_ptr result) { + DCHECK(result->HasTexture()); + base::ScopedClosureRunner scoped_callback_runner( + base::Bind(&CefRenderWidgetHostViewOSR::OnFrameCaptureFailure, + weak_ptr_factory_.GetWeakPtr())); + + const gfx::Size& result_size = result->size(); + SkIRect bitmap_size; + if (bitmap_) + bitmap_->getBounds(&bitmap_size); + + if (!bitmap_ || + bitmap_size.width() != result_size.width() || + bitmap_size.height() != result_size.height()) { + // Create a new bitmap if the size has changed. + bitmap_.reset(new SkBitmap); + bitmap_->setConfig(SkBitmap::kARGB_8888_Config, + result_size.width(), + result_size.height(), + 0, + kOpaque_SkAlphaType); + if (!bitmap_->allocPixels()) + return; + } + + content::ImageTransportFactory* factory = + content::ImageTransportFactory::GetInstance(); + content::GLHelper* gl_helper = factory->GetGLHelper(); + if (!gl_helper) + return; + + scoped_ptr bitmap_pixels_lock( + new SkAutoLockPixels(*bitmap_)); + uint8* pixels = static_cast(bitmap_->getPixels()); + + cc::TextureMailbox texture_mailbox; + scoped_ptr release_callback; + result->TakeTexture(&texture_mailbox, &release_callback); + DCHECK(texture_mailbox.IsTexture()); + if (!texture_mailbox.IsTexture()) + return; + + ignore_result(scoped_callback_runner.Release()); + + gl_helper->CropScaleReadbackAndCleanMailbox( + texture_mailbox.mailbox(), + texture_mailbox.sync_point(), + result_size, + gfx::Rect(result_size), + result_size, + pixels, + SkBitmap::kARGB_8888_Config, + base::Bind( + &CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceFinishedProxy, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(&release_callback), + base::Passed(&bitmap_), + base::Passed(&bitmap_pixels_lock)), + content::GLHelper::SCALER_QUALITY_FAST); +} + +// static +void CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceFinishedProxy( + base::WeakPtr view, + scoped_ptr release_callback, + scoped_ptr bitmap, + scoped_ptr bitmap_pixels_lock, + bool result) { + // This method may be called after the view has been deleted. + uint32 sync_point = 0; + if (result) { + content::GLHelper* gl_helper = + content::ImageTransportFactory::GetInstance()->GetGLHelper(); + sync_point = gl_helper->InsertSyncPoint(); + } + bool lost_resource = sync_point == 0; + release_callback->Run(sync_point, lost_resource); + + if (view) { + view->CopyFromCompositingSurfaceFinished( + bitmap.Pass(), bitmap_pixels_lock.Pass(), result); + } else { + bitmap_pixels_lock.reset(); + bitmap.reset(); + } +} + +void CefRenderWidgetHostViewOSR::CopyFromCompositingSurfaceFinished( + scoped_ptr bitmap, + scoped_ptr bitmap_pixels_lock, + bool result) { + // Restore ownership of the bitmap to the view. + DCHECK(!bitmap_); + bitmap_ = bitmap.Pass(); + + if (result) { + OnFrameCaptureSuccess(*bitmap_, bitmap_pixels_lock.Pass()); + } else { + bitmap_pixels_lock.reset(); + OnFrameCaptureFailure(); + } +} + +void CefRenderWidgetHostViewOSR::PrepareBitmapCopyOutputResult( + scoped_ptr result) { + DCHECK(result->HasBitmap()); + scoped_ptr source = result->TakeBitmap(); + DCHECK(source); + if (source) { + scoped_ptr bitmap_pixels_lock( + new SkAutoLockPixels(*source)); + OnFrameCaptureSuccess(*source, bitmap_pixels_lock.Pass()); + } else { + OnFrameCaptureFailure(); + } +} + +void CefRenderWidgetHostViewOSR::OnFrameCaptureFailure() { + const bool force_frame = (++frame_retry_count_ <= kFrameRetryLimit); + OnFrameCaptureCompletion(force_frame); +} + +void CefRenderWidgetHostViewOSR::OnFrameCaptureSuccess( + const SkBitmap& bitmap, + scoped_ptr bitmap_pixels_lock) { + SkRect bounds; + bitmap.getBounds(&bounds); + + CefRenderHandler::RectList rcList; + rcList.push_back(CefRect(0, 0, bounds.width(), bounds.height())); + + browser_impl_->GetClient()->GetRenderHandler()->OnPaint( + browser_impl_.get(), + IsPopupWidget() ? PET_POPUP : PET_VIEW, + rcList, + bitmap.getPixels(), + bounds.width(), + bounds.height()); + + bitmap_pixels_lock.reset(); + + // Reset the frame retry count on successful frame generation. + if (frame_retry_count_ > 0) + frame_retry_count_ = 0; + + OnFrameCaptureCompletion(false); +} + +void CefRenderWidgetHostViewOSR::OnFrameCaptureCompletion(bool force_frame) { + frame_in_progress_ = false; + + if (frame_pending_) { + // Another frame was requested while the current frame was in-progress. + // Generate the pending frame now. + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefRenderWidgetHostViewOSR::GenerateFrame, + weak_ptr_factory_.GetWeakPtr(), force_frame)); + } +} + +void CefRenderWidgetHostViewOSR::CancelPopupWidget() { + DCHECK(IsPopupWidget()); + + if (render_widget_host_) + render_widget_host_->LostCapture(); + + WasHidden(); + + if (browser_impl_) { + browser_impl_->GetClient()->GetRenderHandler()->OnPopupShow( + browser_impl_.get(), false); + browser_impl_ = NULL; + } + + if (parent_host_view_) { + parent_host_view_->set_popup_host_view(NULL); + parent_host_view_ = NULL; + } + + if (render_widget_host_ && !is_destroyed_) { + is_destroyed_ = true; + // Results in a call to Destroy(). + render_widget_host_->Shutdown(); + } +} + diff --git a/libcef/browser/render_widget_host_view_osr.h b/libcef/browser/render_widget_host_view_osr.h new file mode 100644 index 000000000..ffd61425d --- /dev/null +++ b/libcef/browser/render_widget_host_view_osr.h @@ -0,0 +1,335 @@ +// 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_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_ +#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_ +#pragma once + +#include + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +#include "base/memory/weak_ptr.h" +#include "content/browser/compositor/delegated_frame_host.h" +#include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "ui/compositor/compositor.h" + +#if defined(OS_WIN) +#include "ui/gfx/win/window_impl.h" +#endif + +namespace content { +class RenderWidgetHost; +class RenderWidgetHostImpl; +class BackingStore; +} + +class CefBrowserHostImpl; +class CefWebContentsViewOSR; + +#if defined(OS_MACOSX) +#ifdef __OBJC__ +@class NSWindow; +#else +class NSWindow; +#endif +#endif + +#if defined(USE_X11) +class CefWindowX11; +#endif + +/////////////////////////////////////////////////////////////////////////////// +// CefRenderWidgetHostViewOSR +// +// An object representing the "View" of a rendered web page. This object is +// responsible for sending paint events to the the CefRenderHandler +// when window rendering is disabled. It is the implementation of the +// RenderWidgetHostView that the cross-platform RenderWidgetHost object uses +// to display the data. +// +// Comment excerpted from render_widget_host.h: +// +// "The lifetime of the RenderWidgetHostView is tied to the render process. +// If the render process dies, the RenderWidgetHostView goes away and all +// references to it must become NULL." +// +// RenderWidgetHostView class hierarchy described in render_widget_host_view.h. +/////////////////////////////////////////////////////////////////////////////// + +class CefRenderWidgetHostViewOSR + : public content::RenderWidgetHostViewBase, + public content::DelegatedFrameHostClient { + public: + explicit CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget); + virtual ~CefRenderWidgetHostViewOSR(); + + // RenderWidgetHostView implementation. + virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE; + virtual content::RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE; + virtual void SetSize(const gfx::Size& size) OVERRIDE; + virtual void SetBounds(const gfx::Rect& rect) OVERRIDE; + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE; + virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; + virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; + virtual void Focus() OVERRIDE; + virtual bool HasFocus() const OVERRIDE; + virtual bool IsSurfaceAvailableForCopy() const OVERRIDE; + virtual void Show() OVERRIDE; + virtual void Hide() OVERRIDE; + virtual bool IsShowing() OVERRIDE; + virtual gfx::Rect GetViewBounds() const OVERRIDE; + virtual void SetBackgroundOpaque(bool opaque) OVERRIDE; + virtual bool LockMouse() OVERRIDE; + virtual void UnlockMouse() OVERRIDE; + +#if defined(OS_MACOSX) + virtual void SetActive(bool active) OVERRIDE; + virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE; + virtual void SetWindowVisibility(bool visible) OVERRIDE; + virtual void WindowFrameChanged() OVERRIDE; + virtual void ShowDefinitionForSelection() OVERRIDE; + virtual bool SupportsSpeech() const OVERRIDE; + virtual void SpeakSelection() OVERRIDE; + virtual bool IsSpeaking() const OVERRIDE; + virtual void StopSpeaking() OVERRIDE; +#endif // defined(OS_MACOSX) + + // RenderWidgetHostViewBase implementation. + virtual void OnSwapCompositorFrame( + uint32 output_surface_id, + scoped_ptr frame) OVERRIDE; + virtual void InitAsPopup(content::RenderWidgetHostView* parent_host_view, + const gfx::Rect& pos) OVERRIDE; + virtual void InitAsFullscreen( + content::RenderWidgetHostView* reference_host_view) OVERRIDE; + virtual void WasShown() OVERRIDE; + virtual void WasHidden() OVERRIDE; + virtual void MovePluginWindows( + const std::vector& moves) OVERRIDE; + virtual void Blur() OVERRIDE; + virtual void UpdateCursor(const content::WebCursor& cursor) OVERRIDE; + virtual void SetIsLoading(bool is_loading) OVERRIDE; + virtual void TextInputStateChanged( + const ViewHostMsg_TextInputState_Params& params) OVERRIDE; + virtual void ImeCancelComposition() OVERRIDE; + virtual void RenderProcessGone(base::TerminationStatus status, + int error_code) OVERRIDE; + virtual void Destroy() OVERRIDE; + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, + size_t offset, + const gfx::Range& range) OVERRIDE; + virtual gfx::Size GetRequestedRendererSize() const OVERRIDE; + virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE; + virtual void SelectionBoundsChanged( + const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE; + virtual void ScrollOffsetChanged() OVERRIDE; + virtual void CopyFromCompositingSurface( + const gfx::Rect& src_subrect, + const gfx::Size& dst_size, + const base::Callback& callback, + const SkBitmap::Config config) OVERRIDE; + virtual void CopyFromCompositingSurfaceToVideoFrame( + const gfx::Rect& src_subrect, + const scoped_refptr& target, + const base::Callback& callback) OVERRIDE; + virtual bool CanCopyToVideoFrame() const OVERRIDE; + virtual bool CanSubscribeFrame() const OVERRIDE; + virtual void BeginFrameSubscription( + scoped_ptr subscriber) + OVERRIDE; + virtual void EndFrameSubscription() OVERRIDE; + virtual void AcceleratedSurfaceInitialized(int host_id, + int route_id) OVERRIDE; + virtual void AcceleratedSurfaceBuffersSwapped( + const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, + int gpu_host_id) OVERRIDE; + virtual void AcceleratedSurfacePostSubBuffer( + const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, + int gpu_host_id) OVERRIDE; + virtual void AcceleratedSurfaceSuspend() OVERRIDE; + virtual void AcceleratedSurfaceRelease() OVERRIDE; + virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; + virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE; + virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE; + virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE; + +#if defined(OS_MACOSX) + virtual bool PostProcessEventForPluginIme( + const content::NativeWebKeyboardEvent& event) OVERRIDE; +#endif + +#if defined(OS_MACOSX) || defined(USE_AURA) + virtual void ImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector& character_bounds) OVERRIDE; +#endif + +#if defined(OS_WIN) + virtual void SetParentNativeViewAccessible( + gfx::NativeViewAccessible accessible_parent) OVERRIDE; + virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE; +#endif + + // DelegatedFrameHost implementation. + virtual ui::Compositor* GetCompositor() const OVERRIDE; + virtual ui::Layer* GetLayer() OVERRIDE; + virtual content::RenderWidgetHostImpl* GetHost() OVERRIDE; + virtual void SchedulePaintInRect( + const gfx::Rect& damage_rect_in_dip) OVERRIDE; + virtual bool IsVisible() OVERRIDE; + virtual scoped_ptr CreateResizeLock( + bool defer_compositor_lock) OVERRIDE; + virtual gfx::Size DesiredFrameSize() OVERRIDE; + virtual float CurrentDeviceScaleFactor() OVERRIDE; + virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) OVERRIDE; + virtual content::DelegatedFrameHost* GetDelegatedFrameHost() const OVERRIDE; + + bool InstallTransparency(); + + void WasResized(); + void OnScreenInfoChanged(); + void Invalidate(CefBrowserHost::PaintElementType type); + void SendKeyEvent(const content::NativeWebKeyboardEvent& event); + void SendMouseEvent(const blink::WebMouseEvent& event); + void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event); + void SendFocusEvent(bool focus); + + void HoldResize(); + void ReleaseResize(); + + bool IsPopupWidget() const { + return popup_type_ != blink::WebPopupTypeNone; + } + +#if defined(OS_MACOSX) + NSTextInputContext* GetNSTextInputContext(); + void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent); + void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent); + + bool GetCachedFirstRectForCharacterRange(gfx::Range range, gfx::Rect* rect, + gfx::Range* actual_range) const; +#endif // defined(OS_MACOSX) + + CefRefPtr browser_impl() const { return browser_impl_; } + void set_browser_impl(CefRefPtr browser) { + browser_impl_ = browser; + } + + void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view) { + popup_host_view_ = popup_view; + } + + ui::Compositor* compositor() const { return compositor_.get(); } + content::RenderWidgetHostImpl* render_widget_host() const + { return render_widget_host_; } + + private: + void SetFrameRate(); + void ResizeRootLayer(); + + // Implementation based on RendererOverridesHandler::InnerSwapCompositorFrame + // and DelegatedFrameHost::CopyFromCompositingSurface. + void GenerateFrame(bool force_frame); + void InternalGenerateFrame(); + void CopyFromCompositingSurfaceHasResult( + scoped_ptr result); + void PrepareTextureCopyOutputResult( + scoped_ptr result); + static void CopyFromCompositingSurfaceFinishedProxy( + base::WeakPtr view, + scoped_ptr release_callback, + scoped_ptr bitmap, + scoped_ptr bitmap_pixels_lock, + bool result); + void CopyFromCompositingSurfaceFinished( + scoped_ptr bitmap, + scoped_ptr bitmap_pixels_lock, + bool result); + void PrepareBitmapCopyOutputResult( + scoped_ptr result); + void OnFrameCaptureFailure(); + void OnFrameCaptureSuccess( + const SkBitmap& bitmap, + scoped_ptr bitmap_pixels_lock); + void OnFrameCaptureCompletion(bool force_frame); + + void CancelPopupWidget(); + +#if defined(OS_MACOSX) + // Returns composition character boundary rectangle. The |range| is + // composition based range. Also stores |actual_range| which is corresponding + // to actually used range for returned rectangle. + gfx::Rect GetFirstRectForCompositionRange(const gfx::Range& range, + gfx::Range* actual_range) const; + + // Converts from given whole character range to composition oriented range. If + // the conversion failed, return gfx::Range::InvalidRange. + gfx::Range ConvertCharacterRangeToCompositionRange( + const gfx::Range& request_range) const; + + // Returns true if there is line break in |range| and stores line breaking + // point to |line_breaking_point|. The |line_break_point| is valid only if + // this function returns true. + static bool GetLineBreakIndex(const std::vector& bounds, + const gfx::Range& range, + size_t* line_break_point); + + void DestroyNSTextInputOSR(); +#endif // defined(OS_MACOSX) + + void PlatformCreateCompositorWidget(); + void PlatformDestroyCompositorWidget(); + + scoped_ptr delegated_frame_host_; + scoped_ptr compositor_; + gfx::AcceleratedWidget compositor_widget_; + scoped_ptr root_layer_; + +#if defined(OS_WIN) + scoped_ptr window_; +#elif defined(OS_MACOSX) + NSWindow* window_; +#elif defined(USE_X11) + CefWindowX11* window_; +#endif + + int frame_rate_threshold_ms_; + base::TimeTicks frame_start_time_; + bool frame_pending_; + bool frame_in_progress_; + int frame_retry_count_; + scoped_ptr bitmap_; + + bool hold_resize_; + bool pending_resize_; + + // The associated Model. While |this| is being Destroyed, + // |render_widget_host_| is NULL and the message loop is run one last time + // Message handlers must check for a NULL |render_widget_host_|. + content::RenderWidgetHostImpl* render_widget_host_; + CefRenderWidgetHostViewOSR* parent_host_view_; + CefRenderWidgetHostViewOSR* popup_host_view_; + + CefRefPtr browser_impl_; + + bool is_showing_; + bool is_destroyed_; + gfx::Rect popup_position_; + +#if defined(OS_MACOSX) + NSTextInputContext* text_input_context_osr_mac_; +#endif + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR); +}; + +#endif // CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_ + diff --git a/libcef/browser/render_widget_host_view_osr_linux.cc b/libcef/browser/render_widget_host_view_osr_linux.cc new file mode 100644 index 000000000..26cc247ab --- /dev/null +++ b/libcef/browser/render_widget_host_view_osr_linux.cc @@ -0,0 +1,25 @@ +// 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 "libcef/browser/render_widget_host_view_osr.h" + +#include + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/window_x11.h" + +#include "ui/gfx/x/x11_types.h" + +void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() { + // Create a hidden 1x1 window. It will delete itself on close. + window_ = new CefWindowX11(NULL, None, gfx::Rect(0, 0, 1, 1)); + compositor_widget_ = window_->xwindow(); +} + +void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { + DCHECK(window_); + window_->Close(); + compositor_widget_ = gfx::kNullAcceleratedWidget; +} diff --git a/libcef/browser/render_widget_host_view_osr_mac.mm b/libcef/browser/render_widget_host_view_osr_mac.mm new file mode 100644 index 000000000..697eaa4f0 --- /dev/null +++ b/libcef/browser/render_widget_host_view_osr_mac.mm @@ -0,0 +1,281 @@ +// 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 "libcef/browser/render_widget_host_view_osr.h" + +#import + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/text_input_client_osr_mac.h" + +#include "content/browser/compositor/browser_compositor_view_mac.h" + +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + +namespace { + +CefTextInputClientOSRMac* GetInputClientFromContext( + const NSTextInputContext* context) { + if (!context) + return NULL; + return reinterpret_cast([context client]); +} + +} // namespace + +void CefRenderWidgetHostViewOSR::SetActive(bool active) { +} + +void CefRenderWidgetHostViewOSR::SetTakesFocusOnlyOnMouseDown(bool flag) { +} + +void CefRenderWidgetHostViewOSR::SetWindowVisibility(bool visible) { +} + +void CefRenderWidgetHostViewOSR::WindowFrameChanged() { +} + +void CefRenderWidgetHostViewOSR::ShowDefinitionForSelection() { +} + +bool CefRenderWidgetHostViewOSR::SupportsSpeech() const { + return false; +} + +void CefRenderWidgetHostViewOSR::SpeakSelection() { +} + +bool CefRenderWidgetHostViewOSR::IsSpeaking() const { + return false; +} + +void CefRenderWidgetHostViewOSR::StopSpeaking() { +} + +void CefRenderWidgetHostViewOSR::TextInputStateChanged( + const ViewHostMsg_TextInputState_Params& params) { + [NSApp updateWindows]; +} + +void CefRenderWidgetHostViewOSR::ImeCancelComposition() { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + if (client) + [client cancelComposition]; +} + +bool CefRenderWidgetHostViewOSR::PostProcessEventForPluginIme( + const content::NativeWebKeyboardEvent& event) { + return false; +} + +void CefRenderWidgetHostViewOSR::ImeCompositionRangeChanged( + const gfx::Range& range, + const std::vector& character_bounds) { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + if (!client) + return; + + client->markedRange_ = range.ToNSRange(); + client->composition_range_ = range; + client->composition_bounds_ = character_bounds; +} + +CefTextInputContext CefRenderWidgetHostViewOSR::GetNSTextInputContext() { + if (!text_input_context_osr_mac_) { + CefTextInputClientOSRMac* text_input_client_osr_mac = + [[CefTextInputClientOSRMac alloc] initWithRenderWidgetHostViewOSR: + this]; + + text_input_context_osr_mac_ = [[NSTextInputContext alloc] initWithClient: + text_input_client_osr_mac]; + } + + return text_input_context_osr_mac_; +} + +void CefRenderWidgetHostViewOSR::HandleKeyEventBeforeTextInputClient( + CefEventHandle keyEvent) { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + if (client) + [client HandleKeyEventBeforeTextInputClient: keyEvent]; +} + +void CefRenderWidgetHostViewOSR::HandleKeyEventAfterTextInputClient( + CefEventHandle keyEvent) { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + if (client) + [client HandleKeyEventAfterTextInputClient: keyEvent]; +} + +bool CefRenderWidgetHostViewOSR::GetCachedFirstRectForCharacterRange( + gfx::Range range, gfx::Rect* rect, gfx::Range* actual_range) const { + DCHECK(rect); + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + + // If requested range is same as caret location, we can just return it. + if (selection_range_.is_empty() && gfx::Range(range) == selection_range_) { + if (actual_range) + *actual_range = range; + *rect = client->caret_rect_; + return true; + } + + const gfx::Range request_range_in_composition = + ConvertCharacterRangeToCompositionRange(gfx::Range(range)); + if (request_range_in_composition == gfx::Range::InvalidRange()) + return false; + + // If firstRectForCharacterRange in WebFrame is failed in renderer, + // ImeCompositionRangeChanged will be sent with empty vector. + if (client->composition_bounds_.empty()) + return false; + + DCHECK_EQ(client->composition_bounds_.size(), + client->composition_range_.length()); + + gfx::Range ui_actual_range; + *rect = GetFirstRectForCompositionRange(request_range_in_composition, + &ui_actual_range); + if (actual_range) { + *actual_range = gfx::Range( + client->composition_range_.start() + ui_actual_range.start(), + client->composition_range_.start() + ui_actual_range.end()).ToNSRange(); + } + return true; +} + +gfx::Rect CefRenderWidgetHostViewOSR::GetFirstRectForCompositionRange( + const gfx::Range& range, gfx::Range* actual_range) const { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + + DCHECK(client); + DCHECK(actual_range); + DCHECK(!client->composition_bounds_.empty()); + DCHECK_LE(range.start(), client->composition_bounds_.size()); + DCHECK_LE(range.end(), client->composition_bounds_.size()); + + if (range.is_empty()) { + *actual_range = range; + if (range.start() == client->composition_bounds_.size()) { + return gfx::Rect(client->composition_bounds_[range.start() - 1].right(), + client->composition_bounds_[range.start() - 1].y(), + 0, + client->composition_bounds_[range.start() - 1].height()); + } else { + return gfx::Rect(client->composition_bounds_[range.start()].x(), + client->composition_bounds_[range.start()].y(), + 0, + client->composition_bounds_[range.start()].height()); + } + } + + size_t end_idx; + if (!GetLineBreakIndex(client->composition_bounds_, + range, &end_idx)) { + end_idx = range.end(); + } + *actual_range = gfx::Range(range.start(), end_idx); + gfx::Rect rect = client->composition_bounds_[range.start()]; + for (size_t i = range.start() + 1; i < end_idx; ++i) { + rect.Union(client->composition_bounds_[i]); + } + return rect; +} + +gfx::Range CefRenderWidgetHostViewOSR::ConvertCharacterRangeToCompositionRange( + const gfx::Range& request_range) const { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + DCHECK(client); + + if (client->composition_range_.is_empty()) + return gfx::Range::InvalidRange(); + + if (request_range.is_reversed()) + return gfx::Range::InvalidRange(); + + if (request_range.start() < client->composition_range_.start() + || request_range.start() > client->composition_range_.end() + || request_range.end() > client->composition_range_.end()) + return gfx::Range::InvalidRange(); + + return gfx::Range(request_range.start() - client->composition_range_.start(), + request_range.end() - client->composition_range_.start()); +} + +bool CefRenderWidgetHostViewOSR::GetLineBreakIndex( + const std::vector& bounds, + const gfx::Range& range, + size_t* line_break_point) { + DCHECK(line_break_point); + if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty()) + return false; + + // We can't check line breaking completely from only rectangle array. Thus we + // assume the line breaking as the next character's y offset is larger than + // a threshold. Currently the threshold is determined as minimum y offset plus + // 75% of maximum height. + const size_t loop_end_idx = std::min(bounds.size(), range.end()); + int max_height = 0; + int min_y_offset = kint32max; + for (size_t idx = range.start(); idx < loop_end_idx; ++idx) { + max_height = std::max(max_height, bounds[idx].height()); + min_y_offset = std::min(min_y_offset, bounds[idx].y()); + } + int line_break_threshold = min_y_offset + (max_height * 3 / 4); + for (size_t idx = range.start(); idx < loop_end_idx; ++idx) { + if (bounds[idx].y() > line_break_threshold) { + *line_break_point = idx; + return true; + } + } + return false; +} + +void CefRenderWidgetHostViewOSR::DestroyNSTextInputOSR() { + CefTextInputClientOSRMac* client = GetInputClientFromContext( + text_input_context_osr_mac_); + if (client) { + [client release]; + client = NULL; + } + + [text_input_context_osr_mac_ release]; + text_input_context_osr_mac_ = NULL; +} + +void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() { + // Create a borderless non-visible 1x1 window. + window_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + BrowserCompositorViewMac* view = + [[BrowserCompositorViewMac alloc] + initWithSuperview:[window_ contentView]]; + compositor_.reset([view compositor]); + DCHECK(compositor_); + compositor_widget_ = view; +} + +void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { + DCHECK(window_); + + // Compositor is owned by and will be freed by BrowserCompositorViewMac. + ui::Compositor* compositor = compositor_.release(); + UNUSED(compositor); + + [window_ close]; + window_ = nil; + compositor_widget_ = gfx::kNullAcceleratedWidget; +} diff --git a/libcef/browser/render_widget_host_view_osr_win.cc b/libcef/browser/render_widget_host_view_osr_win.cc new file mode 100644 index 000000000..9d1643b3d --- /dev/null +++ b/libcef/browser/render_widget_host_view_osr_win.cc @@ -0,0 +1,59 @@ +// 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 "libcef/browser/render_widget_host_view_osr.h" +#include "libcef/browser/browser_host_impl.h" + +namespace { + +class CefCompositorHostWin : public gfx::WindowImpl { + public: + CefCompositorHostWin() { + // Create a hidden 1x1 borderless window. + set_window_style(WS_POPUP | WS_SYSMENU); + Init(NULL, gfx::Rect(0, 0, 1, 1)); + } + + virtual ~CefCompositorHostWin() { + DestroyWindow(hwnd()); + } + + private: + CR_BEGIN_MSG_MAP_EX(CompositorHostWin) + CR_MSG_WM_PAINT(OnPaint) + CR_END_MSG_MAP() + + void OnPaint(HDC dc) { + ValidateRect(hwnd(), NULL); + } + + DISALLOW_COPY_AND_ASSIGN(CefCompositorHostWin); +}; + +} // namespace + +void CefRenderWidgetHostViewOSR::SetParentNativeViewAccessible( + gfx::NativeViewAccessible accessible_parent) { +} + +gfx::NativeViewId + CefRenderWidgetHostViewOSR::GetParentForWindowlessPlugin() const { + if (browser_impl_.get()) { + return reinterpret_cast( + browser_impl_->GetWindowHandle()); + } + return NULL; +} + +void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() { + DCHECK(!window_); + window_.reset(new CefCompositorHostWin()); + compositor_widget_ = window_->hwnd(); +} + +void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() { + window_.reset(NULL); + compositor_widget_ = gfx::kNullAcceleratedWidget; +} diff --git a/libcef/browser/request_context_impl.cc b/libcef/browser/request_context_impl.cc new file mode 100644 index 000000000..b2557c5c6 --- /dev/null +++ b/libcef/browser/request_context_impl.cc @@ -0,0 +1,112 @@ +// 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 "libcef/browser/request_context_impl.h" +#include "libcef/browser/browser_context_proxy.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "base/atomic_sequence_num.h" +#include "base/logging.h" + +namespace { + +void RemoveContextRef(CefBrowserContext* browser_context) { + CefContentBrowserClient::Get()->RemoveBrowserContextReference( + browser_context); +} + +base::StaticAtomicSequenceNumber g_next_id; + +} // namespace + +// Static functions + +CefRefPtr CefRequestContext::GetGlobalContext() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + return new CefRequestContextImpl( + CefContentBrowserClient::Get()->browser_context()); +} + +CefRefPtr CefRequestContext::CreateContext( + CefRefPtr handler) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + return new CefRequestContextImpl(handler); +} + +// CefBrowserContextImpl + +CefRequestContextImpl::CefRequestContextImpl( + CefBrowserContext* browser_context) + : browser_context_(browser_context), + unique_id_(0) { + DCHECK(browser_context); + if (!IsGlobal()) { + CEF_REQUIRE_UIT(); + CefBrowserContextProxy* proxy = + static_cast(browser_context); + handler_ = proxy->handler(); + CefContentBrowserClient::Get()->AddBrowserContextReference(browser_context); + } +} + +CefRequestContextImpl::CefRequestContextImpl( + CefRefPtr handler) + : browser_context_(NULL), + handler_(handler), + unique_id_(g_next_id.GetNext()) { +} + +CefRequestContextImpl::~CefRequestContextImpl() { + if (browser_context_) { + if (CEF_CURRENTLY_ON_UIT()) + RemoveContextRef(browser_context_); + else + CEF_POST_TASK(CEF_UIT, base::Bind(RemoveContextRef, browser_context_)); + } +} + +CefBrowserContext* CefRequestContextImpl::GetOrCreateBrowserContext() { + CEF_REQUIRE_UIT(); + if (!browser_context_) { + browser_context_ = + CefContentBrowserClient::Get()->CreateBrowserContextProxy(handler_); + } + return browser_context_; +} + +bool CefRequestContextImpl::IsSame(CefRefPtr other) { + CefRequestContextImpl* impl = + static_cast(other.get()); + if (!impl) + return false; + + // Compare CefBrowserContext points if one has been associated. + if (browser_context_ && impl->browser_context_) + return (browser_context_ == impl->browser_context_); + else if (browser_context_ || impl->browser_context_) + return false; + + // Otherwise compare unique IDs. + return (unique_id_ == impl->unique_id_); +} + +bool CefRequestContextImpl::IsGlobal() { + return (browser_context_ == + CefContentBrowserClient::Get()->browser_context()); +} + +CefRefPtr CefRequestContextImpl::GetHandler() { + return handler_; +} diff --git a/libcef/browser/request_context_impl.h b/libcef/browser/request_context_impl.h new file mode 100644 index 000000000..97266a2ec --- /dev/null +++ b/libcef/browser/request_context_impl.h @@ -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_LIBCEF_REQUEST_CONTEXT_IMPL_H_ +#define CEF_LIBCEF_REQUEST_CONTEXT_IMPL_H_ +#pragma once + +#include "include/cef_request_context.h" + +class CefBrowserContext; + +class CefRequestContextImpl : public CefRequestContext { + public: + explicit CefRequestContextImpl(CefBrowserContext* browser_context); + explicit CefRequestContextImpl(CefRefPtr handler); + virtual ~CefRequestContextImpl(); + + CefBrowserContext* GetOrCreateBrowserContext(); + + virtual bool IsSame(CefRefPtr other) OVERRIDE; + virtual bool IsGlobal() OVERRIDE; + virtual CefRefPtr GetHandler() OVERRIDE; + + protected: + CefBrowserContext* browser_context_; + CefRefPtr handler_; + + // Used to uniquely identify CefRequestContext objects before an associated + // CefBrowserContext has been created. + int unique_id_; + + IMPLEMENT_REFCOUNTING(CefRequestContextImpl); + DISALLOW_COPY_AND_ASSIGN(CefRequestContextImpl); +}; + +#endif // CEF_LIBCEF_REQUEST_CONTEXT_IMPL_H_ diff --git a/libcef/browser/resource_dispatcher_host_delegate.cc b/libcef/browser/resource_dispatcher_host_delegate.cc new file mode 100644 index 000000000..4976ee5f4 --- /dev/null +++ b/libcef/browser/resource_dispatcher_host_delegate.cc @@ -0,0 +1,122 @@ +// 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 "libcef/browser/resource_dispatcher_host_delegate.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/origin_whitelist_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/request_impl.h" + +#include "base/memory/scoped_vector.h" +#include "components/navigation_interception/intercept_navigation_resource_throttle.h" +#include "components/navigation_interception/navigation_params.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/common/resource_response.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/url_request.h" + +namespace { + +bool NavigationOnUIThread( + int64 frame_id, + CefRefPtr request, + content::WebContents* source, + const navigation_interception::NavigationParams& params) { + CEF_REQUIRE_UIT(); + + bool ignore_navigation = false; + + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForContents(source); + DCHECK(browser.get()); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr frame; + if (frame_id >= 0) + frame = browser->GetFrame(frame_id); + DCHECK(frame.get()); + if (frame.get()) { + ignore_navigation = handler->OnBeforeBrowse( + browser.get(), frame, request.get(), params.is_redirect()); + } + } + } + } + + return ignore_navigation; +} + +} // namespace + +CefResourceDispatcherHostDelegate::CefResourceDispatcherHostDelegate() { +} + +CefResourceDispatcherHostDelegate::~CefResourceDispatcherHostDelegate() { +} + +void CefResourceDispatcherHostDelegate::RequestBeginning( + net::URLRequest* request, + content::ResourceContext* resource_context, + appcache::AppCacheService* appcache_service, + ResourceType::Type resource_type, + int child_id, + int route_id, + ScopedVector* throttles) { + if (resource_type == ResourceType::MAIN_FRAME || + resource_type == ResourceType::SUB_FRAME) { + int64 frame_id = -1; + + // ResourceRequestInfo will not exist for requests originating from + // WebURLLoader in the render process. + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + if (info) + frame_id = info->GetRenderFrameID(); + + if (frame_id >= 0) { + CefRefPtr cef_request(new CefRequestImpl); + cef_request->Set(request); + cef_request->SetReadOnly(true); + + content::ResourceThrottle* throttle = + new navigation_interception::InterceptNavigationResourceThrottle( + request, + base::Bind(&NavigationOnUIThread, frame_id, cef_request)); + throttles->push_back(throttle); + } + } +} + +bool CefResourceDispatcherHostDelegate::HandleExternalProtocol( + const GURL& url, + int child_id, + int route_id) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForView(child_id, route_id); + if (browser.get()) + browser->HandleExternalProtocol(url); + return false; +} + +void CefResourceDispatcherHostDelegate::OnRequestRedirected( + const GURL& redirect_url, + net::URLRequest* request, + content::ResourceContext* resource_context, + content::ResourceResponse* response) { + const GURL& active_url = request->url(); + if (active_url.is_valid() && redirect_url.is_valid() && + active_url.GetOrigin() != redirect_url.GetOrigin() && + HasCrossOriginWhitelistEntry(active_url, redirect_url)) { + if (!response->head.headers) + response->head.headers = new net::HttpResponseHeaders(std::string()); + + // Add CORS headers to support XMLHttpRequest redirects. + response->head.headers->AddHeader("Access-Control-Allow-Origin: " + + active_url.scheme() + "://" + active_url.host()); + response->head.headers->AddHeader("Access-Control-Allow-Credentials: true"); + } +} diff --git a/libcef/browser/resource_dispatcher_host_delegate.h b/libcef/browser/resource_dispatcher_host_delegate.h new file mode 100644 index 000000000..b6ccc86ab --- /dev/null +++ b/libcef/browser/resource_dispatcher_host_delegate.h @@ -0,0 +1,41 @@ +// 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_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "content/public/browser/resource_dispatcher_host_delegate.h" + +// Implements ResourceDispatcherHostDelegate. +class CefResourceDispatcherHostDelegate + : public content::ResourceDispatcherHostDelegate { + public: + CefResourceDispatcherHostDelegate(); + virtual ~CefResourceDispatcherHostDelegate(); + + // ResourceDispatcherHostDelegate methods. + virtual void RequestBeginning( + net::URLRequest* request, + content::ResourceContext* resource_context, + appcache::AppCacheService* appcache_service, + ResourceType::Type resource_type, + int child_id, + int route_id, + ScopedVector* throttles) OVERRIDE; + virtual bool HandleExternalProtocol(const GURL& url, + int child_id, + int route_id) OVERRIDE; + virtual void OnRequestRedirected( + const GURL& redirect_url, + net::URLRequest* request, + content::ResourceContext* resource_context, + content::ResourceResponse* response) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(CefResourceDispatcherHostDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_RESOURCE_DISPATCHER_HOST_DELEGATE_H_ diff --git a/libcef/browser/resource_request_job.cc b/libcef/browser/resource_request_job.cc new file mode 100644 index 000000000..bd6f418eb --- /dev/null +++ b/libcef/browser/resource_request_job.cc @@ -0,0 +1,559 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2006-2009 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 "libcef/browser/resource_request_job.h" + +#include +#include + +#include "include/cef_callback.h" +#include "libcef/browser/cookie_manager_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/response_impl.h" + +#include "base/logging.h" +#include "net/base/io_buffer.h" +#include "net/base/load_flags.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/http_user_agent_settings.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" + +using net::URLRequestStatus; + +namespace { + +bool SetHeaderIfMissing(CefRequest::HeaderMap& headerMap, + const std::string& name, + const std::string& value) { + if (value.empty()) + return false; + + CefRequest::HeaderMap::const_iterator it = headerMap.find(name); + if (it == headerMap.end()) { + headerMap.insert(std::make_pair(name, value)); + return true; + } + + return false; +} + +} // namespace + +// Client callback for asynchronous response continuation. +class CefResourceRequestJobCallback : public CefCallback { + public: + enum Type { + HEADERS_AVAILABLE, + BYTES_AVAILABLE, + }; + + explicit CefResourceRequestJobCallback(CefResourceRequestJob* job, Type type) + : job_(job), + type_(type), + dest_(NULL), + dest_size_(0) {} + + virtual void Continue() OVERRIDE { + // Continue asynchronously. + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefResourceRequestJobCallback::ContinueOnIOThread, this)); + } + + virtual void Cancel() OVERRIDE { + // Cancel asynchronously. + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefResourceRequestJobCallback::CancelOnIOThread, this)); + } + + void Detach() { + CEF_REQUIRE_IOT(); + job_ = NULL; + } + + void SetDestination(net::IOBuffer* dest, int dest_size) { + CEF_REQUIRE_IOT(); + // Should not be called multiple times while IO is pending. + DCHECK(!dest_); + + dest_ = dest; + dest_size_ = dest_size; + } + + private: + void ContinueOnIOThread() { + CEF_REQUIRE_IOT(); + + // Return early if the callback has already been detached. + if (!job_) + return; + + if (type_ == HEADERS_AVAILABLE) { + // Callback for headers available. + if (!job_->has_response_started()) { + // Send header information. + job_->SendHeaders(); + } + + // This type of callback only ever needs to be called once. + Detach(); + } else if (type_ == BYTES_AVAILABLE) { + // Callback for bytes available. + if (job_->has_response_started() && + job_->GetStatus().is_io_pending()) { + // Read the bytes. They should be available but, if not, wait again. + int bytes_read = 0; + if (job_->ReadRawData(dest_, dest_size_, &bytes_read)) { + // Must clear the members here because they may be reset as a result + // of calling NotifyReadComplete. + dest_size_ = 0; + dest_ = NULL; + + // Clear the IO_PENDING status. + job_->SetStatus(URLRequestStatus()); + + // Notify about the available bytes. If bytes_read > 0 then + // ReadRawData may be called from URLRequest::Read. If bytes_read == 0 + // then Kill will be called from the URLRequest destructor. + job_->NotifyReadComplete(bytes_read); + } else if (!job_->GetStatus().is_io_pending()) { + // Failed due to an error. + NOTREACHED() << + "ReadRawData returned false without setting IO as pending"; + job_->NotifyDone(URLRequestStatus()); + Detach(); + } + } + } + } + + void CancelOnIOThread() { + CEF_REQUIRE_IOT(); + + if (job_) + job_->Kill(); + } + + CefResourceRequestJob* job_; + Type type_; + + net::IOBuffer* dest_; + int dest_size_; + + IMPLEMENT_REFCOUNTING(CefResourceRequestJobCallback); +}; + +CefResourceRequestJob::CefResourceRequestJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + CefRefPtr handler) + : net::URLRequestJob(request, network_delegate), + handler_(handler), + done_(false), + remaining_bytes_(0), + response_cookies_save_index_(0), + weak_factory_(this) { +} + +CefResourceRequestJob::~CefResourceRequestJob() { +} + +void CefResourceRequestJob::Start() { + CEF_REQUIRE_IOT(); + + request_start_time_ = base::Time::Now(); + cef_request_ = CefRequest::Create(); + + // Populate the request data. + static_cast(cef_request_.get())->Set(request_); + + // Add default headers if not already specified. + const net::URLRequestContext* context = request_->context(); + if (context) { + CefRequest::HeaderMap headerMap; + cef_request_->GetHeaderMap(headerMap); + bool changed = false; + + const net::HttpUserAgentSettings* ua_settings = + context->http_user_agent_settings(); + if (ua_settings) { + if (SetHeaderIfMissing(headerMap, + net::HttpRequestHeaders::kAcceptLanguage, + ua_settings->GetAcceptLanguage())) { + changed = true; + } + + if (SetHeaderIfMissing(headerMap, + net::HttpRequestHeaders::kUserAgent, + ua_settings->GetUserAgent())) { + changed = true; + } + } + + if (changed) + cef_request_->SetHeaderMap(headerMap); + } + + AddCookieHeaderAndStart(); +} + +void CefResourceRequestJob::Kill() { + CEF_REQUIRE_IOT(); + + if (!done_) { + // Notify the handler that the request has been canceled. + handler_->Cancel(); + } + + if (callback_) { + callback_->Detach(); + callback_ = NULL; + } + + net::URLRequestJob::Kill(); +} + +// This method will be called by URLRequestJob::Read and our callback. +// It can indicate the following states: +// 1. If the request is complete set |bytes_read| == 0 and return true. The +// caller is then responsible for calling NotifyReadComplete. ReadRawData +// should not be called again. +// 2. If data is available synchronously set |bytes_read| > 0 and return true. +// The caller is then responsible for calling NotifyReadComplete. ReadRawData +// may be called again by URLRequestJob::Read. +// 3. If data is not available now but may be available asynchronously set +// status to IO_PENDING and return false. When executed asynchronously the +// callback will again call ReadRawData. If data is returned at that time the +// callback will clear the status and call NotifyReadComplete. +bool CefResourceRequestJob::ReadRawData(net::IOBuffer* dest, int dest_size, + int* bytes_read) { + CEF_REQUIRE_IOT(); + + DCHECK_NE(dest_size, 0); + DCHECK(bytes_read); + + if (remaining_bytes_ == 0) { + // No more data to read. + *bytes_read = 0; + done_ = true; + return true; + } else if (remaining_bytes_ > 0 && remaining_bytes_ < dest_size) { + // The handler knows the content size beforehand. + dest_size = static_cast(remaining_bytes_); + } + + if (!callback_.get()) { + // Create the bytes available callback that will be used until the request + // is completed. + callback_ = new CefResourceRequestJobCallback(this, + CefResourceRequestJobCallback::BYTES_AVAILABLE); + } + + // Read response data from the handler. + bool rv = handler_->ReadResponse(dest->data(), dest_size, *bytes_read, + callback_.get()); + if (!rv) { + // The handler has indicated completion of the request. + *bytes_read = 0; + done_ = true; + return true; + } else if (*bytes_read == 0) { + // Continue reading asynchronously. May happen multiple times in a row so + // only set IO pending the first time. + if (!GetStatus().is_io_pending()) { + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + callback_->SetDestination(dest, dest_size); + } + return false; + } else if (*bytes_read > dest_size) { + // Normalize the return value. + *bytes_read = dest_size; + } + + if (remaining_bytes_ > 0) + remaining_bytes_ -= *bytes_read; + + // Continue calling this method. + return true; +} + +void CefResourceRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { + CEF_REQUIRE_IOT(); + + info->headers = GetResponseHeaders(); +} + +void CefResourceRequestJob::GetLoadTimingInfo( + net::LoadTimingInfo* load_timing_info) const { + // If haven't made it far enough to receive any headers, don't return + // anything. This makes for more consistent behavior in the case of errors. + if (!response_ || receive_headers_end_.is_null()) + return; + load_timing_info->request_start_time = request_start_time_; + load_timing_info->receive_headers_end = receive_headers_end_; +} + +bool CefResourceRequestJob::GetResponseCookies( + std::vector* cookies) { + CEF_REQUIRE_IOT(); + + cookies->clear(); + FetchResponseCookies(cookies); + return true; +} + +bool CefResourceRequestJob::IsRedirectResponse(GURL* location, + int* http_status_code) { + CEF_REQUIRE_IOT(); + + if (redirect_url_.is_valid()) { + // Redirect to the new URL. + *http_status_code = 303; + location->Swap(&redirect_url_); + return true; + } + + if (response_.get()) { + // Check for HTTP 302 or HTTP 303 redirect. + int status = response_->GetStatus(); + if (status == 302 || status == 303) { + CefResponse::HeaderMap headerMap; + response_->GetHeaderMap(headerMap); + CefRequest::HeaderMap::iterator iter = headerMap.find("Location"); + if (iter != headerMap.end()) { + GURL new_url = GURL(std::string(iter->second)); + *http_status_code = status; + location->Swap(&new_url); + return true; + } + } + } + + return false; +} + +bool CefResourceRequestJob::GetMimeType(std::string* mime_type) const { + CEF_REQUIRE_IOT(); + + if (response_.get()) + *mime_type = response_->GetMimeType(); + return true; +} + +void CefResourceRequestJob::SendHeaders() { + CEF_REQUIRE_IOT(); + + // Clear the headers available callback. + callback_ = NULL; + + // We may have been orphaned... + if (!request()) + return; + + response_ = new CefResponseImpl(); + remaining_bytes_ = 0; + + CefString redirectUrl; + + // Get header information from the handler. + handler_->GetResponseHeaders(response_, remaining_bytes_, redirectUrl); + receive_headers_end_ = base::TimeTicks::Now(); + if (!redirectUrl.empty()) { + std::string redirectUrlStr = redirectUrl; + redirect_url_ = GURL(redirectUrlStr); + } + + if (remaining_bytes_ > 0) + set_expected_content_size(remaining_bytes_); + + // Continue processing the request. + SaveCookiesAndNotifyHeadersComplete(); +} + +void CefResourceRequestJob::AddCookieHeaderAndStart() { + // No matter what, we want to report our status as IO pending since we will + // be notifying our consumer asynchronously via OnStartCompleted. + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + + // If the request was destroyed, then there is no more work to do. + if (!request_) + return; + + net::CookieStore* cookie_store = + request_->context()->cookie_store(); + if (cookie_store && + !(request_->load_flags() & net::LOAD_DO_NOT_SEND_COOKIES)) { + net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster(); + if (cookie_monster) { + cookie_monster->GetAllCookiesForURLAsync( + request_->url(), + base::Bind(&CefResourceRequestJob::CheckCookiePolicyAndLoad, + weak_factory_.GetWeakPtr())); + } else { + DoLoadCookies(); + } + } else { + DoStartTransaction(); + } +} + +void CefResourceRequestJob::DoLoadCookies() { + net::CookieOptions options; + options.set_include_httponly(); + request_->context()->cookie_store()->GetCookiesWithOptionsAsync( + request_->url(), options, + base::Bind(&CefResourceRequestJob::OnCookiesLoaded, + weak_factory_.GetWeakPtr())); +} + +void CefResourceRequestJob::CheckCookiePolicyAndLoad( + const net::CookieList& cookie_list) { + bool can_get_cookies = CanGetCookies(cookie_list); + if (can_get_cookies) { + net::CookieList::const_iterator it = cookie_list.begin(); + for (; it != cookie_list.end(); ++it) { + CefCookie cookie; + if (!CefCookieManagerImpl::GetCefCookie(*it, cookie) || + !handler_->CanGetCookie(cookie)) { + can_get_cookies = false; + break; + } + } + } + + if (can_get_cookies) + DoLoadCookies(); + else + DoStartTransaction(); +} + +void CefResourceRequestJob::OnCookiesLoaded(const std::string& cookie_line) { + if (!cookie_line.empty()) { + CefRequest::HeaderMap headerMap; + cef_request_->GetHeaderMap(headerMap); + headerMap.insert( + std::make_pair(net::HttpRequestHeaders::kCookie, cookie_line)); + cef_request_->SetHeaderMap(headerMap); + } + DoStartTransaction(); +} + +void CefResourceRequestJob::DoStartTransaction() { + // We may have been canceled while retrieving cookies. + if (GetStatus().is_success()) { + StartTransaction(); + } else { + NotifyCanceled(); + } +} + +void CefResourceRequestJob::StartTransaction() { + // Create the callback that will be used to notify when header information is + // available. + callback_ = new CefResourceRequestJobCallback(this, + CefResourceRequestJobCallback::HEADERS_AVAILABLE); + + // Protect against deletion of this object. + base::WeakPtr weak_ptr(weak_factory_.GetWeakPtr()); + + // Handler can decide whether to process the request. + bool rv = handler_->ProcessRequest(cef_request_, callback_.get()); + if (weak_ptr.get() && !rv) { + // Cancel the request. + NotifyCanceled(); + } +} + +net::HttpResponseHeaders* CefResourceRequestJob::GetResponseHeaders() { + DCHECK(response_); + if (!response_headers_.get()) { + CefResponseImpl* responseImpl = + static_cast(response_.get()); + response_headers_ = responseImpl->GetResponseHeaders(); + } + return response_headers_; +} + +void CefResourceRequestJob::SaveCookiesAndNotifyHeadersComplete() { + if (request_->load_flags() & net::LOAD_DO_NOT_SAVE_COOKIES) { + SetStatus(URLRequestStatus()); // Clear the IO_PENDING status + NotifyHeadersComplete(); + return; + } + + response_cookies_.clear(); + response_cookies_save_index_ = 0; + + FetchResponseCookies(&response_cookies_); + + // Now, loop over the response cookies, and attempt to persist each. + SaveNextCookie(); +} + +void CefResourceRequestJob::SaveNextCookie() { + if (response_cookies_save_index_ == response_cookies_.size()) { + response_cookies_.clear(); + response_cookies_save_index_ = 0; + SetStatus(URLRequestStatus()); // Clear the IO_PENDING status + NotifyHeadersComplete(); + return; + } + + // No matter what, we want to report our status as IO pending since we will + // be notifying our consumer asynchronously via OnStartCompleted. + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + + net::CookieOptions options; + options.set_include_httponly(); + bool can_set_cookie = CanSetCookie( + response_cookies_[response_cookies_save_index_], &options); + if (can_set_cookie) { + CefCookie cookie; + if (CefCookieManagerImpl::GetCefCookie(request_->url(), + response_cookies_[response_cookies_save_index_], cookie)) { + can_set_cookie = handler_->CanSetCookie(cookie); + } else { + can_set_cookie = false; + } + } + + if (can_set_cookie) { + request_->context()->cookie_store()->SetCookieWithOptionsAsync( + request_->url(), response_cookies_[response_cookies_save_index_], + options, base::Bind(&CefResourceRequestJob::OnCookieSaved, + weak_factory_.GetWeakPtr())); + return; + } + + CookieHandled(); +} + +void CefResourceRequestJob::OnCookieSaved(bool cookie_status) { + CookieHandled(); +} + +void CefResourceRequestJob::CookieHandled() { + response_cookies_save_index_++; + // We may have been canceled within OnSetCookie. + if (GetStatus().is_success()) { + SaveNextCookie(); + } else { + NotifyCanceled(); + } +} + +void CefResourceRequestJob::FetchResponseCookies( + std::vector* cookies) { + const std::string name = "Set-Cookie"; + std::string value; + + void* iter = NULL; + net::HttpResponseHeaders* headers = GetResponseHeaders(); + while (headers->EnumerateHeader(&iter, name, &value)) { + if (!value.empty()) + cookies->push_back(value); + } +} diff --git a/libcef/browser/resource_request_job.h b/libcef/browser/resource_request_job.h new file mode 100644 index 000000000..0bfd4f6e0 --- /dev/null +++ b/libcef/browser/resource_request_job.h @@ -0,0 +1,85 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2006-2009 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_LIBCEF_BROWSER_RESOURCE_REQUEST_JOB_H_ +#define CEF_LIBCEF_BROWSER_RESOURCE_REQUEST_JOB_H_ + +#include + +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/cef_request_handler.h" + +#include "net/cookies/cookie_monster.h" +#include "net/url_request/url_request_job.h" + +namespace net { +class HttpResponseHeaders; +class URLRequest; +} + +class CefResourceRequestJobCallback; + +class CefResourceRequestJob : public net::URLRequestJob { + public: + CefResourceRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + CefRefPtr handler); + virtual ~CefResourceRequestJob(); + + private: + // net::URLRequestJob methods. + virtual void Start() OVERRIDE; + virtual void Kill() OVERRIDE; + virtual bool ReadRawData(net::IOBuffer* dest, int dest_size, int* bytes_read) + OVERRIDE; + virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; + virtual void GetLoadTimingInfo( + net::LoadTimingInfo* load_timing_info) const OVERRIDE; + virtual bool GetResponseCookies(std::vector* cookies) OVERRIDE; + virtual bool IsRedirectResponse(GURL* location, int* http_status_code) + OVERRIDE; + virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; + + void SendHeaders(); + + // Used for sending cookies with the request. + void AddCookieHeaderAndStart(); + void DoLoadCookies(); + void CheckCookiePolicyAndLoad(const net::CookieList& cookie_list); + void OnCookiesLoaded(const std::string& cookie_line); + void DoStartTransaction(); + void StartTransaction(); + + // Used for saving cookies returned as part of the response. + net::HttpResponseHeaders* GetResponseHeaders(); + void SaveCookiesAndNotifyHeadersComplete(); + void SaveNextCookie(); + void OnCookieSaved(bool cookie_status); + void CookieHandled(); + void FetchResponseCookies(std::vector* cookies); + + CefRefPtr handler_; + bool done_; + CefRefPtr response_; + GURL redirect_url_; + int64 remaining_bytes_; + CefRefPtr cef_request_; + CefRefPtr callback_; + scoped_refptr response_headers_; + std::vector response_cookies_; + size_t response_cookies_save_index_; + base::Time request_start_time_; + base::TimeTicks receive_headers_end_; + + // Must be the last member. + base::WeakPtrFactory weak_factory_; + + friend class CefResourceRequestJobCallback; + + DISALLOW_COPY_AND_ASSIGN(CefResourceRequestJob); +}; + +#endif // CEF_LIBCEF_BROWSER_RESOURCE_REQUEST_JOB_H_ diff --git a/libcef/browser/scheme_handler.cc b/libcef/browser/scheme_handler.cc new file mode 100644 index 000000000..342d12517 --- /dev/null +++ b/libcef/browser/scheme_handler.cc @@ -0,0 +1,86 @@ +// 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 "libcef/browser/scheme_handler.h" + +#include + +#include "libcef/browser/chrome_scheme_handler.h" +#include "libcef/browser/devtools_scheme_handler.h" +#include "libcef/common/scheme_registration.h" + +#include "base/threading/sequenced_worker_pool.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/url_constants.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/ftp_protocol_handler.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "url/url_constants.h" + +namespace scheme { + +void InstallInternalProtectedHandlers( + net::URLRequestJobFactoryImpl* job_factory, + content::ProtocolHandlerMap* protocol_handlers, + net::FtpTransactionFactory* ftp_transaction_factory) { + protocol_handlers->insert( + std::make_pair(url::kDataScheme, + linked_ptr( + new net::DataProtocolHandler))); + protocol_handlers->insert( + std::make_pair(url::kFileScheme, + linked_ptr( + new net::FileProtocolHandler( + content::BrowserThread::GetBlockingPool()-> + GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))))); +#if !defined(DISABLE_FTP_SUPPORT) + protocol_handlers->insert( + std::make_pair(url::kFtpScheme, + linked_ptr( + new net::FtpProtocolHandler(ftp_transaction_factory)))); +#endif + + for (content::ProtocolHandlerMap::iterator it = + protocol_handlers->begin(); + it != protocol_handlers->end(); + ++it) { + const std::string& scheme = it->first; + scoped_ptr protocol_handler; + + if (scheme == content::kChromeDevToolsScheme) { + // Don't use the default "chrome-devtools" handler. + continue; + } else if (scheme == content::kChromeUIScheme) { + // Filter the URLs that are passed to the default "chrome" handler so as + // not to interfere with CEF's "chrome" handler. + protocol_handler.reset( + scheme::WrapChromeProtocolHandler( + make_scoped_ptr(it->second.release())).release()); + } else { + protocol_handler.reset(it->second.release()); + } + + // Make sure IsInternalProtectedScheme() stays synchronized with what + // Chromium is actually giving us. + DCHECK(IsInternalProtectedScheme(scheme)); + + bool set_protocol = job_factory->SetProtocolHandler( + scheme, protocol_handler.release()); + DCHECK(set_protocol); + } +} + +void RegisterInternalHandlers() { + scheme::RegisterChromeHandler(); + scheme::RegisterChromeDevToolsHandler(); +} + +void DidFinishLoad(CefRefPtr frame, const GURL& validated_url) { + if (validated_url.scheme() == content::kChromeUIScheme) + scheme::DidFinishChromeLoad(frame, validated_url); +} + +} // namespace scheme diff --git a/libcef/browser/scheme_handler.h b/libcef/browser/scheme_handler.h new file mode 100644 index 000000000..062c5a24f --- /dev/null +++ b/libcef/browser/scheme_handler.h @@ -0,0 +1,36 @@ +// 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_LIBCEF_BROWSER_SCHEME_HANDLER_H_ +#define CEF_LIBCEF_BROWSER_SCHEME_HANDLER_H_ +#pragma once + +#include "include/cef_frame.h" + +#include "content/public/browser/content_browser_client.h" +#include "url/gurl.h" + +namespace net { +class FtpTransactionFactory; +class URLRequestJobFactoryImpl; +} + +namespace scheme { + +// Install the internal scheme handlers provided by Chromium that cannot be +// overridden. +void InstallInternalProtectedHandlers( + net::URLRequestJobFactoryImpl* job_factory, + content::ProtocolHandlerMap* protocol_handlers, + net::FtpTransactionFactory* ftp_transaction_factory); + +// Register the internal scheme handlers that can be overridden. +void RegisterInternalHandlers(); + +// Used to fire any asynchronous content updates. +void DidFinishLoad(CefRefPtr frame, const GURL& validated_url); + +} // namespace scheme + +#endif // CEF_LIBCEF_BROWSER_SCHEME_HANDLER_H_ diff --git a/libcef/browser/scheme_impl.cc b/libcef/browser/scheme_impl.cc new file mode 100644 index 000000000..6f814c3f6 --- /dev/null +++ b/libcef/browser/scheme_impl.cc @@ -0,0 +1,362 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "include/cef_browser.h" +#include "include/cef_scheme.h" +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/resource_request_job.h" +#include "libcef/browser/scheme_handler.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_context_getter.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/response_impl.h" +#include "libcef/common/scheme_registration.h" +#include "libcef/common/upload_data.h" + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_util.h" +#include "base/synchronization/lock.h" +#include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_util.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_filter.h" +#include "net/url_request/url_request_http_job.h" +#include "net/url_request/url_request_job.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "url/third_party/mozilla/url_parse.h" +#include "url/url_util.h" + +using net::URLRequestStatus; + +namespace { + +bool IsStandardScheme(const std::string& scheme) { + url::Component scheme_comp(0, scheme.length()); + return url::IsStandard(scheme.c_str(), scheme_comp); +} + +// Copied from net/url_request/url_request_job_manager.cc. +struct SchemeToFactory { + const char* scheme; + net::URLRequest::ProtocolFactory* factory; +}; +static const SchemeToFactory kBuiltinFactories[] = { + { "http", net::URLRequestHttpJob::Factory }, + { "https", net::URLRequestHttpJob::Factory }, +}; + +bool IsBuiltinScheme(const std::string& scheme) { + for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) + if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme)) + return true; + return false; +} + +net::URLRequestJob* GetBuiltinSchemeRequestJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& scheme) { + // See if the request should be handled by a built-in protocol factory. + for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) { + if (scheme == kBuiltinFactories[i].scheme) { + net::URLRequestJob* job = + (kBuiltinFactories[i].factory)(request, network_delegate, scheme); + DCHECK(job); // The built-in factories are not expected to fail! + return job; + } + } + + return NULL; +} + +std::string ToLower(const std::string& str) { + std::string str_lower = str; + std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(), + towlower); + return str; +} + +// Class that manages the CefSchemeHandlerFactory instances. +class CefUrlRequestManager { + protected: + // Class used for creating URLRequestJob instances. The lifespan of this + // object is managed by URLRequestJobFactory. + class ProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { + public: + explicit ProtocolHandler(const std::string& scheme) + : scheme_(scheme) {} + + // From net::URLRequestJobFactory::ProtocolHandler + virtual net::URLRequestJob* MaybeCreateJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const OVERRIDE { + CEF_REQUIRE_IOT(); + return CefUrlRequestManager::GetInstance()->GetRequestJob( + request, network_delegate, scheme_); + } + + private: + std::string scheme_; + }; + + public: + CefUrlRequestManager() {} + + // Retrieve the singleton instance. + static CefUrlRequestManager* GetInstance(); + + bool AddFactory(const std::string& scheme, + const std::string& domain, + CefRefPtr factory) { + if (!factory.get()) { + RemoveFactory(scheme, domain); + return true; + } + + CEF_REQUIRE_IOT(); + + std::string scheme_lower = ToLower(scheme); + std::string domain_lower = ToLower(domain); + + // Hostname is only supported for standard schemes. + if (!IsStandardScheme(scheme_lower)) + domain_lower.clear(); + + SetProtocolHandlerIfNecessary(scheme_lower, true); + + handler_map_[make_pair(scheme_lower, domain_lower)] = factory; + + return true; + } + + void RemoveFactory(const std::string& scheme, + const std::string& domain) { + CEF_REQUIRE_IOT(); + + std::string scheme_lower = ToLower(scheme); + std::string domain_lower = ToLower(domain); + + // Hostname is only supported for standard schemes. + if (!IsStandardScheme(scheme_lower)) + domain_lower.clear(); + + HandlerMap::iterator iter = + handler_map_.find(make_pair(scheme_lower, domain_lower)); + if (iter != handler_map_.end()) { + handler_map_.erase(iter); + + SetProtocolHandlerIfNecessary(scheme_lower, false); + } + } + + // Clear all the existing URL handlers and unregister the ProtocolFactory. + void ClearFactories() { + CEF_REQUIRE_IOT(); + + net::URLRequestJobFactoryImpl* job_factory = GetJobFactoryImpl(); + + // Create a unique set of scheme names. + std::set schemes; + for (HandlerMap::const_iterator i = handler_map_.begin(); + i != handler_map_.end(); ++i) { + schemes.insert(i->first.first); + } + + for (std::set::const_iterator scheme = schemes.begin(); + scheme != schemes.end(); ++scheme) { + const std::string& scheme_name = *scheme; + if (!scheme::IsInternalProtectedScheme(scheme_name)) { + bool set_protocol = job_factory->SetProtocolHandler(scheme_name, NULL); + DCHECK(set_protocol); + } + } + + handler_map_.clear(); + } + + // Helper for chaining ProtocolHandler implementations. + net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate) { + CEF_REQUIRE_IOT(); + return GetRequestJob(request, network_delegate, request->url().scheme()); + } + + private: + net::URLRequestJobFactoryImpl* GetJobFactoryImpl() { + return static_cast( + CefContentBrowserClient::Get()->request_context().get())-> + job_factory_impl(); + } + + // Add or remove the protocol handler if necessary. |scheme| will already be + // in lower case. + void SetProtocolHandlerIfNecessary(const std::string& scheme, bool add) { + // Don't modify a protocol handler for internal protected schemes or if the + // protocol handler is still needed by other registered factories. + if (scheme::IsInternalProtectedScheme(scheme) || HasFactory(scheme)) + return; + + net::URLRequestJobFactoryImpl* job_factory = GetJobFactoryImpl(); + bool set_protocol = job_factory->SetProtocolHandler( + scheme, + (add ? new ProtocolHandler(scheme) : NULL)); + DCHECK(set_protocol); + } + + // Returns true if any factory currently exists for |scheme|. |scheme| will + // already be in lower case. + bool HasFactory(const std::string& scheme) { + if (handler_map_.empty()) + return false; + + for (HandlerMap::const_iterator i = handler_map_.begin(); + i != handler_map_.end(); ++i) { + if (scheme == i->first.first) + return true; + } + + return false; + } + + // Retrieve the matching handler factory, if any. |scheme| will already be in + // lower case. + CefRefPtr GetHandlerFactory( + net::URLRequest* request, const std::string& scheme) { + CefRefPtr factory; + + if (request->url().is_valid() && IsStandardScheme(scheme)) { + // Check for a match with a domain first. + const std::string& domain = request->url().host(); + + HandlerMap::iterator i = handler_map_.find(make_pair(scheme, domain)); + if (i != handler_map_.end()) + factory = i->second; + } + + if (!factory.get()) { + // Check for a match with no specified domain. + HandlerMap::iterator i = + handler_map_.find(make_pair(scheme, std::string())); + if (i != handler_map_.end()) + factory = i->second; + } + + return factory; + } + + // Create the job that will handle the request. |scheme| will already be in + // lower case. + net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& scheme) { + net::URLRequestJob* job = NULL; + CefRefPtr factory = + GetHandlerFactory(request, scheme); + if (factory) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + CefRefPtr frame; + if (browser.get()) + frame = browser->GetFrameForRequest(request); + + // Populate the request data. + CefRefPtr requestPtr(new CefRequestImpl()); + requestPtr->Set(request); + + // Call the handler factory to create the handler for the request. + CefRefPtr handler = + factory->Create(browser.get(), frame, scheme, requestPtr.get()); + if (handler.get()) + job = new CefResourceRequestJob(request, network_delegate, handler); + } + + if (!job && IsBuiltinScheme(scheme)) { + // Give the built-in scheme handler a chance to handle the request. + job = GetBuiltinSchemeRequestJob(request, network_delegate, scheme); + } + +#ifndef NDEBUG + if (job) + DLOG(INFO) << "CefUrlRequestManager hit for " << request->url().spec(); +#endif + + return job; + } + + // Map (scheme, domain) to factories. Will only be accessed on the IO thread. + typedef std::map, + CefRefPtr > HandlerMap; + HandlerMap handler_map_; + + DISALLOW_EVIL_CONSTRUCTORS(CefUrlRequestManager); +}; + +base::LazyInstance g_manager = LAZY_INSTANCE_INITIALIZER; + +CefUrlRequestManager* CefUrlRequestManager::GetInstance() { + return g_manager.Pointer(); +} + +} // namespace + + +bool CefRegisterSchemeHandlerFactory( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) + return false; + + if (CEF_CURRENTLY_ON(CEF_IOT)) { + return CefUrlRequestManager::GetInstance()->AddFactory(scheme_name, + domain_name, + factory); + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefRegisterSchemeHandlerFactory), + scheme_name, domain_name, factory)); + return true; + } +} + +bool CefClearSchemeHandlerFactories() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) + return false; + + if (CEF_CURRENTLY_ON(CEF_IOT)) { + CefUrlRequestManager::GetInstance()->ClearFactories(); + + // Register internal scheme handlers. + scheme::RegisterInternalHandlers(); + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(base::IgnoreResult(&CefClearSchemeHandlerFactories))); + } + + return true; +} + +namespace scheme { + +net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate) { + return CefUrlRequestManager::GetInstance()->GetRequestJob( + request, network_delegate); +} + +} // namespace scheme diff --git a/libcef/browser/scheme_impl.h b/libcef/browser/scheme_impl.h new file mode 100644 index 000000000..5b66ef9a1 --- /dev/null +++ b/libcef/browser/scheme_impl.h @@ -0,0 +1,24 @@ +// 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_LIBCEF_BROWSER_SCHEME_IMPL_H_ +#define CEF_LIBCEF_BROWSER_SCHEME_IMPL_H_ +#pragma once + +namespace net { +class NetworkDelegate; +class URLRequest; +class URLRequestJob; +} + +namespace scheme { + +// Helper for chaining net::URLRequestJobFactory::ProtocolHandler +// implementations. +net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate); + +} // namespace scheme + +#endif // CEF_LIBCEF_BROWSER_SCHEME_IMPL_H_ diff --git a/libcef/browser/speech_recognition_manager_delegate.cc b/libcef/browser/speech_recognition_manager_delegate.cc new file mode 100644 index 000000000..147ead94d --- /dev/null +++ b/libcef/browser/speech_recognition_manager_delegate.cc @@ -0,0 +1,228 @@ +// 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 "libcef/browser/speech_recognition_manager_delegate.h" + +#include +#include + +#include "libcef/common/cef_switches.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/notification_source.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/speech_recognition_manager.h" +#include "content/public/browser/speech_recognition_session_context.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/speech_recognition_error.h" +#include "content/public/common/speech_recognition_result.h" + +using content::BrowserThread; +using content::SpeechRecognitionManager; +using content::WebContents; + +// Simple utility to get notified when a WebContents is closed or crashes. +// Both the callback site and the callback thread are passed by the caller in +// the constructor. There is no restriction on the constructor, however this +// class must be destroyed on the UI thread, due to the NotificationRegistrar +// dependency. +class CefSpeechRecognitionManagerDelegate::WebContentsWatcher + : public base::RefCountedThreadSafe, + public content::NotificationObserver { + public: + typedef base::Callback + WebContentsClosedCallback; + + WebContentsWatcher(WebContentsClosedCallback web_contents_closed_callback, + BrowserThread::ID callback_thread) + : web_contents_closed_callback_(web_contents_closed_callback), + callback_thread_(callback_thread) { + } + + // Starts monitoring the WebContents corresponding to the given + // |render_process_id|, |render_view_id| pair, invoking + // |web_contents_closed_callback_| if closed/unloaded. + void Watch(int render_process_id, int render_view_id) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( + &WebContentsWatcher::Watch, this, render_process_id, render_view_id)); + return; + } + + WebContents* web_contents = NULL; + content::RenderViewHost* render_view_host = + content::RenderViewHost::FromID(render_process_id, render_view_id); + if (render_view_host) + web_contents = WebContents::FromRenderViewHost(render_view_host); + DCHECK(web_contents); + + // Avoid multiple registrations on |registrar_| for the same |web_contents|. + if (registered_web_contents_.find(web_contents) != + registered_web_contents_.end()) { + return; + } + registered_web_contents_.insert(web_contents); + + // Lazy initialize the registrar. + if (!registrar_.get()) + registrar_.reset(new content::NotificationRegistrar()); + + registrar_->Add(this, + content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, + content::Source(web_contents)); + } + + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_EQ(content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, type); + + WebContents* web_contents = content::Source(source).ptr(); + int render_process_id = web_contents->GetRenderProcessHost()->GetID(); + int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); + + registrar_->Remove(this, + content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, + content::Source(web_contents)); + registered_web_contents_.erase(web_contents); + + BrowserThread::PostTask(callback_thread_, FROM_HERE, base::Bind( + web_contents_closed_callback_, render_process_id, render_view_id)); + } + + private: + friend class base::RefCountedThreadSafe; + + virtual ~WebContentsWatcher() { + // Must be destroyed on the UI thread due to |registrar_| non thread-safety. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + } + + // Lazy-initialized and used on the UI thread to handle web contents + // notifications (tab closing). + scoped_ptr registrar_; + + // Keeps track of which WebContent(s) have been registered, in order to avoid + // double registrations on |registrar_| + std::set registered_web_contents_; + + // Callback used to notify, on the thread specified by |callback_thread_| the + // closure of a registered tab. + WebContentsClosedCallback web_contents_closed_callback_; + content::BrowserThread::ID callback_thread_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsWatcher); +}; + +CefSpeechRecognitionManagerDelegate +::CefSpeechRecognitionManagerDelegate() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + filter_profanities_ = + command_line.HasSwitch(switches::kEnableProfanityFilter); +} + +CefSpeechRecognitionManagerDelegate +::~CefSpeechRecognitionManagerDelegate() { +} + +void CefSpeechRecognitionManagerDelegate::WebContentsClosedCallback( + int render_process_id, int render_view_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + SpeechRecognitionManager* manager = SpeechRecognitionManager::GetInstance(); + // |manager| becomes NULL if a browser shutdown happens between the post of + // this task (from the UI thread) and this call (on the IO thread). In this + // case we just return. + if (!manager) + return; + + manager->AbortAllSessionsForRenderView(render_process_id, render_view_id); +} + +void CefSpeechRecognitionManagerDelegate::OnRecognitionStart( + int session_id) { + const content::SpeechRecognitionSessionContext& context = + SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); + + // Register callback to auto abort session on tab closure. + // |web_contents_watcher_| is lazyly istantiated on the first call. + if (!web_contents_watcher_.get()) { + web_contents_watcher_ = new WebContentsWatcher( + base::Bind( + &CefSpeechRecognitionManagerDelegate::WebContentsClosedCallback, + base::Unretained(this)), + BrowserThread::IO); + } + web_contents_watcher_->Watch(context.render_process_id, + context.render_view_id); +} + +void CefSpeechRecognitionManagerDelegate::OnAudioStart(int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::OnEnvironmentEstimationComplete( + int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::OnSoundStart(int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::OnSoundEnd(int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::OnAudioEnd(int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::OnRecognitionResults( + int session_id, const content::SpeechRecognitionResults& result) { +} + +void CefSpeechRecognitionManagerDelegate::OnRecognitionError( + int session_id, const content::SpeechRecognitionError& error) { +} + +void CefSpeechRecognitionManagerDelegate::OnAudioLevelsChange( + int session_id, float volume, float noise_volume) { +} + +void CefSpeechRecognitionManagerDelegate::OnRecognitionEnd(int session_id) { +} + +void CefSpeechRecognitionManagerDelegate::GetDiagnosticInformation( + bool* can_report_metrics, + std::string* hardware_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); +} + +void CefSpeechRecognitionManagerDelegate::CheckRecognitionIsAllowed( + int session_id, + base::Callback callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + const content::SpeechRecognitionSessionContext& context = + SpeechRecognitionManager::GetInstance()->GetSessionContext(session_id); + + // Make sure that initiators properly set the |render_process_id| field. + DCHECK_NE(context.render_process_id, 0); + + callback.Run(false, true); +} + +content::SpeechRecognitionEventListener* +CefSpeechRecognitionManagerDelegate::GetEventListener() { + return this; +} + +bool CefSpeechRecognitionManagerDelegate::FilterProfanities( + int render_process_id) { + return filter_profanities_; +} diff --git a/libcef/browser/speech_recognition_manager_delegate.h b/libcef/browser/speech_recognition_manager_delegate.h new file mode 100644 index 000000000..5553079ef --- /dev/null +++ b/libcef/browser/speech_recognition_manager_delegate.h @@ -0,0 +1,63 @@ +// 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_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/speech_recognition_event_listener.h" +#include "content/public/browser/speech_recognition_manager_delegate.h" + + +// This is CEF's implementation of the SpeechRecognitionManagerDelegate +// interface. Based on chrome/browser/speech/ +// chrome_speech_recognition_manager_delegate.[cc|h] +class CefSpeechRecognitionManagerDelegate + : NON_EXPORTED_BASE(public content::SpeechRecognitionManagerDelegate), + public content::SpeechRecognitionEventListener { + public: + CefSpeechRecognitionManagerDelegate(); + virtual ~CefSpeechRecognitionManagerDelegate(); + + protected: + // SpeechRecognitionEventListener methods. + virtual void OnRecognitionStart(int session_id) OVERRIDE; + virtual void OnAudioStart(int session_id) OVERRIDE; + virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE; + virtual void OnSoundStart(int session_id) OVERRIDE; + virtual void OnSoundEnd(int session_id) OVERRIDE; + virtual void OnAudioEnd(int session_id) OVERRIDE; + virtual void OnRecognitionEnd(int session_id) OVERRIDE; + virtual void OnRecognitionResults( + int session_id, const content::SpeechRecognitionResults& result) OVERRIDE; + virtual void OnRecognitionError( + int session_id, const content::SpeechRecognitionError& error) OVERRIDE; + virtual void OnAudioLevelsChange(int session_id, float volume, + float noise_volume) OVERRIDE; + + // SpeechRecognitionManagerDelegate methods. + virtual void GetDiagnosticInformation(bool* can_report_metrics, + std::string* hardware_info) OVERRIDE; + virtual void CheckRecognitionIsAllowed( + int session_id, + base::Callback callback) OVERRIDE; + virtual content::SpeechRecognitionEventListener* GetEventListener() OVERRIDE; + virtual bool FilterProfanities(int render_process_id) OVERRIDE; + + private: + class WebContentsWatcher; + + // Callback called by |web_contents_watcher_| on the IO thread to signal + // web contents closure. + void WebContentsClosedCallback(int render_process_id, int render_view_id); + + scoped_refptr web_contents_watcher_; + bool filter_profanities_; + + DISALLOW_COPY_AND_ASSIGN(CefSpeechRecognitionManagerDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_SPEECH_RECOGNITION_MANAGER_DELEGATE_H_ diff --git a/libcef/browser/stream_impl.cc b/libcef/browser/stream_impl.cc new file mode 100644 index 000000000..472b442a9 --- /dev/null +++ b/libcef/browser/stream_impl.cc @@ -0,0 +1,318 @@ +// Copyright (c) 2008 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 "libcef/browser/stream_impl.h" +#include +#include "base/file_util.h" +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" + +// Static functions + +CefRefPtr CefStreamReader::CreateForFile( + const CefString& fileName) { + DCHECK(!fileName.empty()); + + // TODO(cef): Do not allow file IO on all threads (issue #1187). + base::ThreadRestrictions::ScopedAllowIO allow_io; + + CefRefPtr reader; + FILE* file = base::OpenFile(base::FilePath(fileName), "rb"); + if (file) + reader = new CefFileReader(file, true); + return reader; +} + +CefRefPtr CefStreamReader::CreateForData(void* data, + size_t size) { + DCHECK(data != NULL); + DCHECK(size > 0); // NOLINT(readability/check) + CefRefPtr reader; + if (data && size > 0) + reader = new CefBytesReader(data, size, true); + return reader; +} + +CefRefPtr CefStreamReader::CreateForHandler( + CefRefPtr handler) { + DCHECK(handler.get()); + CefRefPtr reader; + if (handler.get()) + reader = new CefHandlerReader(handler); + return reader; +} + +CefRefPtr CefStreamWriter::CreateForFile( + const CefString& fileName) { + DCHECK(!fileName.empty()); + + // TODO(cef): Do not allow file IO on all threads (issue #1187). + base::ThreadRestrictions::ScopedAllowIO allow_io; + + CefRefPtr writer; + FILE* file = base::OpenFile(base::FilePath(fileName), "wb"); + if (file) + writer = new CefFileWriter(file, true); + return writer; +} + +CefRefPtr CefStreamWriter::CreateForHandler( + CefRefPtr handler) { + DCHECK(handler.get()); + CefRefPtr writer; + if (handler.get()) + writer = new CefHandlerWriter(handler); + return writer; +} + + +// CefFileReader + +CefFileReader::CefFileReader(FILE* file, bool close) + : close_(close), file_(file) { +} + +CefFileReader::~CefFileReader() { + base::AutoLock lock_scope(lock_); + if (close_) + base::CloseFile(file_); +} + +size_t CefFileReader::Read(void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + return fread(ptr, size, n, file_); +} + +int CefFileReader::Seek(int64 offset, int whence) { + base::AutoLock lock_scope(lock_); +#if defined(OS_WIN) + return _fseeki64(file_, offset, whence); +#else + return fseek(file_, offset, whence); +#endif +} + +int64 CefFileReader::Tell() { + base::AutoLock lock_scope(lock_); +#if defined(OS_WIN) + return _ftelli64(file_); +#else + return ftell(file_); +#endif +} + +int CefFileReader::Eof() { + base::AutoLock lock_scope(lock_); + return feof(file_); +} + + +// CefFileWriter + +CefFileWriter::CefFileWriter(FILE* file, bool close) + : file_(file), + close_(close) { +} + +CefFileWriter::~CefFileWriter() { + base::AutoLock lock_scope(lock_); + if (close_) + base::CloseFile(file_); +} + +size_t CefFileWriter::Write(const void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + return (size_t)fwrite(ptr, size, n, file_); +} + +int CefFileWriter::Seek(int64 offset, int whence) { + base::AutoLock lock_scope(lock_); + return fseek(file_, offset, whence); +} + +int64 CefFileWriter::Tell() { + base::AutoLock lock_scope(lock_); + return ftell(file_); +} + +int CefFileWriter::Flush() { + base::AutoLock lock_scope(lock_); + return fflush(file_); +} + + +// CefBytesReader + +CefBytesReader::CefBytesReader(void* data, int64 datasize, bool copy) + : data_(NULL), + datasize_(0), + copy_(false), + offset_(0) { + SetData(data, datasize, copy); +} + +CefBytesReader::~CefBytesReader() { + SetData(NULL, 0, false); +} + +size_t CefBytesReader::Read(void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + size_t s = (datasize_ - offset_) / size; + size_t ret = (n < s ? n : s); + memcpy(ptr, (reinterpret_cast(data_)) + offset_, ret * size); + offset_ += ret * size; + return ret; +} + +int CefBytesReader::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 CefBytesReader::Tell() { + base::AutoLock lock_scope(lock_); + return offset_; +} + +int CefBytesReader::Eof() { + base::AutoLock lock_scope(lock_); + return (offset_ >= datasize_); +} + +void CefBytesReader::SetData(void* data, int64 datasize, bool copy) { + base::AutoLock lock_scope(lock_); + if (copy_) + free(data_); + + copy_ = copy; + offset_ = 0; + datasize_ = datasize; + + if (copy) { + data_ = malloc(datasize); + DCHECK(data_ != NULL); + if (data_) + memcpy(data_, data, datasize); + } else { + data_ = data; + } +} + + +// CefBytesWriter + +CefBytesWriter::CefBytesWriter(size_t grow) + : grow_(grow), + datasize_(grow), + offset_(0) { + DCHECK(grow > 0); // NOLINT(readability/check) + data_ = malloc(grow); + DCHECK(data_ != NULL); +} + +CefBytesWriter::~CefBytesWriter() { + base::AutoLock lock_scope(lock_); + if (data_) + free(data_); +} + +size_t CefBytesWriter::Write(const void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + size_t rv; + if (offset_ + static_cast(size * n) >= datasize_ && + Grow(size * n) == 0) { + rv = 0; + } else { + memcpy(reinterpret_cast(data_) + offset_, ptr, size * n); + offset_ += size * n; + rv = n; + } + + return rv; +} + +int CefBytesWriter::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 CefBytesWriter::Tell() { + base::AutoLock lock_scope(lock_); + return offset_; +} + +int CefBytesWriter::Flush() { + return 0; +} + +std::string CefBytesWriter::GetDataString() { + base::AutoLock lock_scope(lock_); + std::string str(reinterpret_cast(data_), offset_); + return str; +} + +size_t CefBytesWriter::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; +} diff --git a/libcef/browser/stream_impl.h b/libcef/browser/stream_impl.h new file mode 100644 index 000000000..f07eebaab --- /dev/null +++ b/libcef/browser/stream_impl.h @@ -0,0 +1,171 @@ +// 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_LIBCEF_BROWSER_STREAM_IMPL_H_ +#define CEF_LIBCEF_BROWSER_STREAM_IMPL_H_ +#pragma once + +#include "include/cef_stream.h" + +#include +#include + +#include "base/synchronization/lock.h" + +// Implementation of CefStreamReader for files. +class CefFileReader : public CefStreamReader { + public: + CefFileReader(FILE* file, bool close); + virtual ~CefFileReader(); + + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Eof() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return true; } + + protected: + bool close_; + FILE* file_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefFileReader); +}; + +// Implementation of CefStreamWriter for files. +class CefFileWriter : public CefStreamWriter { + public: + CefFileWriter(FILE* file, bool close); + virtual ~CefFileWriter(); + + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Flush() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return true; } + + protected: + FILE* file_; + bool close_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefFileWriter); +}; + +// Implementation of CefStreamReader for byte buffers. +class CefBytesReader : public CefStreamReader { + public: + CefBytesReader(void* data, int64 datasize, bool copy); + virtual ~CefBytesReader(); + + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Eof() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return false; } + + void SetData(void* data, int64 datasize, bool copy); + + void* GetData() { return data_; } + size_t GetDataSize() { return offset_; } + + protected: + void* data_; + int64 datasize_; + bool copy_; + int64 offset_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefBytesReader); +}; + +// Implementation of CefStreamWriter for byte buffers. +class CefBytesWriter : public CefStreamWriter { + public: + explicit CefBytesWriter(size_t grow); + virtual ~CefBytesWriter(); + + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Flush() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return false; } + + void* GetData() { return data_; } + int64 GetDataSize() { return offset_; } + std::string GetDataString(); + + protected: + size_t Grow(size_t size); + + size_t grow_; + void* data_; + int64 datasize_; + int64 offset_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefBytesWriter); +}; + +// Implementation of CefStreamReader for handlers. +class CefHandlerReader : public CefStreamReader { + public: + explicit CefHandlerReader(CefRefPtr handler) + : handler_(handler) {} + + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE { + return handler_->Read(ptr, size, n); + } + virtual int Seek(int64 offset, int whence) OVERRIDE { + return handler_->Seek(offset, whence); + } + virtual int64 Tell() OVERRIDE { + return handler_->Tell(); + } + virtual int Eof() OVERRIDE { + return handler_->Eof(); + } + virtual bool MayBlock() OVERRIDE { + return handler_->MayBlock(); + } + + protected: + CefRefPtr handler_; + + IMPLEMENT_REFCOUNTING(CefHandlerReader); +}; + +// Implementation of CefStreamWriter for handlers. +class CefHandlerWriter : public CefStreamWriter { + public: + explicit CefHandlerWriter(CefRefPtr handler) + : handler_(handler) {} + + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE { + return handler_->Write(ptr, size, n); + } + virtual int Seek(int64 offset, int whence) OVERRIDE { + return handler_->Seek(offset, whence); + } + virtual int64 Tell() OVERRIDE { + return handler_->Tell(); + } + virtual int Flush() OVERRIDE { + return handler_->Flush(); + } + virtual bool MayBlock() OVERRIDE { + return handler_->MayBlock(); + } + + protected: + CefRefPtr handler_; + + IMPLEMENT_REFCOUNTING(CefHandlerWriter); +}; + +#endif // CEF_LIBCEF_BROWSER_STREAM_IMPL_H_ diff --git a/libcef/browser/text_input_client_osr_mac.h b/libcef/browser/text_input_client_osr_mac.h new file mode 100644 index 000000000..5b10caab1 --- /dev/null +++ b/libcef/browser/text_input_client_osr_mac.h @@ -0,0 +1,89 @@ +// 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_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_ +#define CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_ +#pragma once + +#import +#include + +#include "libcef/browser/render_widget_host_view_osr.h" + +#include "base/mac/scoped_nsobject.h" +#include "base/strings/string16.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/common/edit_command.h" +#include "third_party/WebKit/public/web/WebCompositionUnderline.h" + +// Implementation for the NSTextInputClient protocol used for enabling IME on +// mac when window rendering is disabled. + +@interface CefTextInputClientOSRMac : NSObject { + + @public + // The range of current marked text inside the whole content of the DOM node + // being edited. + NSRange markedRange_; + + // The current composition character range and its bounds. + gfx::Range composition_range_; + std::vector composition_bounds_; + + // The current caret bounds. + gfx::Rect caret_rect_; + + @private + // Represents the input-method attributes supported by this object. + base::scoped_nsobject validAttributesForMarkedText_; + + // Indicates if we are currently handling a key down event. + BOOL handlingKeyDown_; + + // Indicates if there is any marked text. + BOOL hasMarkedText_; + + // Indicates whether there was any marked text prior to handling + // the current key event. + BOOL oldHasMarkedText_; + + // Indicates if unmarkText is called or not when handling a keyboard + // event. + BOOL unmarkTextCalled_; + + // The selected range, cached from a message sent by the renderer. + NSRange selectedRange_; + + // Text to be inserted which was generated by handling a key down event. + base::string16 textToBeInserted_; + + // Marked text which was generated by handling a key down event. + base::string16 markedText_; + + // Underline information of the |markedText_|. + std::vector underlines_; + + // Indicates if doCommandBySelector method receives any edit command when + // handling a key down event. + BOOL hasEditCommands_; + + // Contains edit commands received by the -doCommandBySelector: method when + // handling a key down event, not including inserting commands, eg. insertTab, + // etc. + content::EditCommands editCommands_; + + CefRenderWidgetHostViewOSR* renderWidgetHostView_; +} + +@property(nonatomic, readonly) NSRange selectedRange; +@property(nonatomic) BOOL handlingKeyDown; + +- (id)initWithRenderWidgetHostViewOSR:(CefRenderWidgetHostViewOSR*) rwhv; +- (void)HandleKeyEventBeforeTextInputClient:(NSEvent*)keyEvent; +- (void)HandleKeyEventAfterTextInputClient:(NSEvent*)keyEvent; +- (void)cancelComposition; + +@end + +#endif // CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_ diff --git a/libcef/browser/text_input_client_osr_mac.mm b/libcef/browser/text_input_client_osr_mac.mm new file mode 100644 index 000000000..179f588ad --- /dev/null +++ b/libcef/browser/text_input_client_osr_mac.mm @@ -0,0 +1,359 @@ +// 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 "libcef/browser/text_input_client_osr_mac.h" +#include "libcef/browser/browser_host_impl.h" + +#include "base/strings/sys_string_conversions.h" +#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h" +#import "content/browser/renderer_host/text_input_client_mac.h" +#include "content/common/input_messages.h" + +namespace { + +// TODO(suzhe): Upstream this function. +blink::WebColor WebColorFromNSColor(NSColor *color) { + CGFloat r, g, b, a; + [color getRed:&r green:&g blue:&b alpha:&a]; + + return + std::max(0, std::min(static_cast(lroundf(255.0f * a)), 255)) << 24 | + std::max(0, std::min(static_cast(lroundf(255.0f * r)), 255)) << 16 | + std::max(0, std::min(static_cast(lroundf(255.0f * g)), 255)) << 8 | + std::max(0, std::min(static_cast(lroundf(255.0f * b)), 255)); +} + +// Extract underline information from an attributed string. Mostly copied from +// third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm +void ExtractUnderlines(NSAttributedString* string, + std::vector* underlines) { + int length = [[string string] length]; + int i = 0; + while (i < length) { + NSRange range; + NSDictionary* attrs = [string attributesAtIndex:i + longestEffectiveRange:&range + inRange:NSMakeRange(i, length - i)]; + NSNumber *style = [attrs objectForKey: NSUnderlineStyleAttributeName]; + if (style) { + blink::WebColor color = SK_ColorBLACK; + if (NSColor *colorAttr = + [attrs objectForKey:NSUnderlineColorAttributeName]) { + color = WebColorFromNSColor( + [colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]); + } + underlines->push_back(blink::WebCompositionUnderline( + range.location, NSMaxRange(range), color, [style intValue] > 1)); + } + i = range.location + range.length; + } +} + +} // namespace + +extern "C" { + extern NSString* NSTextInputReplacementRangeAttributeName; +} + +@implementation CefTextInputClientOSRMac + +@synthesize selectedRange = selectedRange_; +@synthesize handlingKeyDown = handlingKeyDown_; + +- (id)initWithRenderWidgetHostViewOSR:(CefRenderWidgetHostViewOSR*)rwhv { + self = [super init]; + renderWidgetHostView_ = rwhv; + + return self; +} + +- (NSArray*)validAttributesForMarkedText { + if (!validAttributesForMarkedText_) { + validAttributesForMarkedText_.reset([[NSArray alloc] initWithObjects: + NSUnderlineStyleAttributeName, + NSUnderlineColorAttributeName, + NSMarkedClauseSegmentAttributeName, + NSTextInputReplacementRangeAttributeName, + nil]); + } + return validAttributesForMarkedText_.get(); +} + +- (NSRange)markedRange { + return hasMarkedText_ ? markedRange_ : NSMakeRange(NSNotFound, 0); +} + +- (BOOL)hasMarkedText { + return hasMarkedText_; +} + +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { + BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]]; + NSString* im_text = isAttributedString ? [aString string] : aString; + if (handlingKeyDown_) { + textToBeInserted_.append(base::SysNSStringToUTF16(im_text)); + } else { + gfx::Range replacement_range(replacementRange); + + renderWidgetHostView_->render_widget_host()->ImeConfirmComposition( + base::SysNSStringToUTF16(im_text), replacement_range, false); + } + + // Inserting text will delete all marked text automatically. + hasMarkedText_ = NO; +} + +- (void)doCommandBySelector:(SEL)aSelector { + // An input method calls this function to dispatch an editing command to be + // handled by this view. + if (aSelector == @selector(noop:)) + return; + std::string command([content::RenderWidgetHostViewMacEditCommandHelper:: + CommandNameForSelector(aSelector) UTF8String]); + + // If this method is called when handling a key down event, then we need to + // handle the command in the key event handler. Otherwise we can just handle + // it here. + if (handlingKeyDown_) { + hasEditCommands_ = YES; + // We ignore commands that insert characters, because this was causing + // strange behavior (e.g. tab always inserted a tab rather than moving to + // the next field on the page). + if (!StartsWithASCII(command, "insert", false)) + editCommands_.push_back(content::EditCommand(command, "")); + } else { + renderWidgetHostView_->render_widget_host()->Send( + new InputMsg_ExecuteEditCommand( + renderWidgetHostView_->render_widget_host()->GetRoutingID(), + command, "")); + } +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelRange + replacementRange:(NSRange)replacementRange { + // An input method updates the composition string. + // We send the given text and range to the renderer so it can update the + // composition node of WebKit. + + BOOL isAttributedString = [aString isKindOfClass:[NSAttributedString class]]; + NSString* im_text = isAttributedString ? [aString string] : aString; + int length = [im_text length]; + + // |markedRange_| will get set on a callback from ImeSetComposition(). + selectedRange_ = newSelRange; + markedText_ = base::SysNSStringToUTF16(im_text); + hasMarkedText_ = (length > 0); + underlines_.clear(); + + if (isAttributedString) { + ExtractUnderlines(aString, &underlines_); + } else { + // Use a thin black underline by default. + underlines_.push_back(blink::WebCompositionUnderline(0, length, + SK_ColorBLACK, false)); + } + + // If we are handling a key down event, then SetComposition() will be + // called in keyEvent: method. + // Input methods of Mac use setMarkedText calls with an empty text to cancel + // an ongoing composition. So, we should check whether or not the given text + // is empty to update the input method state. (Our input method backend can + // automatically cancels an ongoing composition when we send an empty text. + // So, it is OK to send an empty text to the renderer.) + if (!handlingKeyDown_) { + renderWidgetHostView_->render_widget_host()->ImeSetComposition( + markedText_, underlines_, newSelRange.location, + NSMaxRange(newSelRange)); + } +} + +- (void)unmarkText { + // Delete the composition node of the renderer and finish an ongoing + // composition. + // It seems an input method calls the setMarkedText method and set an empty + // text when it cancels an ongoing composition, i.e. I have never seen an + // input method calls this method. + hasMarkedText_ = NO; + markedText_.clear(); + underlines_.clear(); + + // If we are handling a key down event, then ConfirmComposition() will be + // called in keyEvent: method. + if (!handlingKeyDown_) { + renderWidgetHostView_->render_widget_host()->ImeConfirmComposition( + base::string16(), gfx::Range::InvalidRange(), false); + } else { + unmarkTextCalled_ = YES; + } +} + +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range + actualRange:(NSRangePointer)actualRange { + if (actualRange) + *actualRange = range; + NSAttributedString* str = content::TextInputClientMac::GetInstance()-> + GetAttributedSubstringFromRange( + renderWidgetHostView_->GetRenderWidgetHost(), range); + return str; +} + +- (NSRect)firstViewRectForCharacterRange:(NSRange)theRange + actualRange:(NSRangePointer)actualRange { + NSRect rect; + gfx::Rect gfxRect; + gfx::Range range(theRange); + gfx::Range actual_range; + if (!renderWidgetHostView_->GetCachedFirstRectForCharacterRange(range, + &gfxRect, &actual_range)) { + rect = content::TextInputClientMac::GetInstance()-> + GetFirstRectForRange(renderWidgetHostView_->GetRenderWidgetHost(), + range.ToNSRange()); + + if (actualRange) + *actualRange = range.ToNSRange(); + } else { + rect = NSRectFromCGRect(gfxRect.ToCGRect()); + } + + return rect; +} + +- (NSRect) screenRectFromViewRect:(NSRect)rect { + NSRect screenRect; + + int screenX, screenY; + renderWidgetHostView_->browser_impl()->GetClient()->GetRenderHandler()-> + GetScreenPoint(renderWidgetHostView_->browser_impl()->GetBrowser(), + rect.origin.x, rect.origin.y, screenX, screenY); + screenRect.origin = NSMakePoint(screenX, screenY); + screenRect.size = rect.size; + + return screenRect; +} + +- (NSRect)firstRectForCharacterRange:(NSRange)theRange + actualRange:(NSRangePointer)actualRange { + NSRect rect = [self firstViewRectForCharacterRange:theRange + actualRange:actualRange]; + + // Convert into screen coordinates for return. + rect = [self screenRectFromViewRect:rect]; + + if (rect.origin.y >= rect.size.height) + rect.origin.y -= rect.size.height; + else + rect.origin.y = 0; + + return rect; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint { + // |thePoint| is in screen coordinates, but needs to be converted to WebKit + // coordinates (upper left origin). Scroll offsets will be taken care of in + // the renderer. + + CefRect view_rect; + renderWidgetHostView_->browser_impl()->GetClient()->GetRenderHandler()-> + GetViewRect(renderWidgetHostView_->browser_impl()->GetBrowser(), + view_rect); + + thePoint.x -= view_rect.x; + thePoint.y -= view_rect.y; + thePoint.y = view_rect.height - thePoint.y; + + NSUInteger index = content::TextInputClientMac::GetInstance()-> + GetCharacterIndexAtPoint(renderWidgetHostView_->GetRenderWidgetHost(), + gfx::Point(thePoint.x, thePoint.y)); + return index; +} + +- (void)HandleKeyEventBeforeTextInputClient:(NSEvent*)keyEvent { + DCHECK([keyEvent type] == NSKeyDown); + // Don't call this method recursively. + DCHECK(!handlingKeyDown_); + + oldHasMarkedText_ = hasMarkedText_; + handlingKeyDown_ = YES; + + // These variables might be set when handling the keyboard event. + // Clear them here so that we can know whether they have changed afterwards. + textToBeInserted_.clear(); + markedText_.clear(); + underlines_.clear(); + unmarkTextCalled_ = NO; + hasEditCommands_ = NO; + editCommands_.clear(); +} + +- (void)HandleKeyEventAfterTextInputClient:(NSEvent*)keyEvent { + handlingKeyDown_ = NO; + + // Then send keypress and/or composition related events. + // If there was a marked text or the text to be inserted is longer than 1 + // character, then we send the text by calling ConfirmComposition(). + // Otherwise, if the text to be inserted only contains 1 character, then we + // can just send a keypress event which is fabricated by changing the type of + // the keydown event, so that we can retain all necessary informations, such + // as unmodifiedText, etc. And we need to set event.skip_in_browser to true to + // prevent the browser from handling it again. + // Note that, |textToBeInserted_| is a UTF-16 string, but it's fine to only + // handle BMP characters here, as we can always insert non-BMP characters as + // text. + + if (!hasMarkedText_ && !oldHasMarkedText_ && + textToBeInserted_.length() <= 1) { + content::NativeWebKeyboardEvent event(keyEvent); + if (textToBeInserted_.length() == 1) { + event.type = blink::WebInputEvent::Type::Char; + event.text[0] = textToBeInserted_[0]; + event.text[1] = 0; + } + renderWidgetHostView_->SendKeyEvent(event); + } + + BOOL textInserted = NO; + if (textToBeInserted_.length() > + ((hasMarkedText_ || oldHasMarkedText_) ? 0u : 1u)) { + renderWidgetHostView_->render_widget_host()->ImeConfirmComposition( + textToBeInserted_, gfx::Range::InvalidRange(), false); + textToBeInserted_ = YES; + } + + // Updates or cancels the composition. If some text has been inserted, then + // we don't need to cancel the composition explicitly. + if (hasMarkedText_ && markedText_.length()) { + // Sends the updated marked text to the renderer so it can update the + // composition node in WebKit. + // When marked text is available, |selectedRange_| will be the range being + // selected inside the marked text. + renderWidgetHostView_->render_widget_host()->ImeSetComposition( + markedText_, underlines_, selectedRange_.location, + NSMaxRange(selectedRange_)); + } else if (oldHasMarkedText_ && !hasMarkedText_ && !textInserted) { + if (unmarkTextCalled_) { + renderWidgetHostView_->render_widget_host()->ImeConfirmComposition( + base::string16(), gfx::Range::InvalidRange(), false); + } else { + renderWidgetHostView_->render_widget_host()->ImeCancelComposition(); + } + } +} + +- (void)cancelComposition { + if (!hasMarkedText_) + return; + + // Cancel the ongoing composition. [NSInputManager markedTextAbandoned:] + // doesn't call any NSTextInput functions, such as setMarkedText or + // insertText. So, we need to send an IPC message to a renderer so it can + // delete the composition node. + NSInputManager *currentInputManager = [NSInputManager currentInputManager]; + [currentInputManager markedTextAbandoned:self]; + + hasMarkedText_ = NO; + // Should not call [self unmarkText] here, because it'll send unnecessary + // cancel composition IPC message to the renderer. +} + +@end diff --git a/libcef/browser/thread_util.h b/libcef/browser/thread_util.h new file mode 100644 index 000000000..2faf57128 --- /dev/null +++ b/libcef/browser/thread_util.h @@ -0,0 +1,49 @@ +// 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_LIBCEF_BROWSER_THREAD_UTIL_H_ +#define CEF_LIBCEF_BROWSER_THREAD_UTIL_H_ +#pragma once + +#include "base/location.h" +#include "base/logging.h" +#include "content/public/browser/browser_thread.h" + +#define CEF_UIT content::BrowserThread::UI +#define CEF_IOT content::BrowserThread::IO +#define CEF_FILET content::BrowserThread::FILE + +#define CEF_CURRENTLY_ON(id) content::BrowserThread::CurrentlyOn(id) +#define CEF_CURRENTLY_ON_UIT() CEF_CURRENTLY_ON(CEF_UIT) +#define CEF_CURRENTLY_ON_IOT() CEF_CURRENTLY_ON(CEF_IOT) +#define CEF_CURRENTLY_ON_FILET() CEF_CURRENTLY_ON(CEF_FILET) + +#define CEF_REQUIRE(id) DCHECK(CEF_CURRENTLY_ON(id)) +#define CEF_REQUIRE_UIT() CEF_REQUIRE(CEF_UIT) +#define CEF_REQUIRE_IOT() CEF_REQUIRE(CEF_IOT) +#define CEF_REQUIRE_FILET() CEF_REQUIRE(CEF_FILET) + +#define CEF_REQUIRE_RETURN(id, var) \ + if (!CEF_CURRENTLY_ON(id)) { \ + NOTREACHED() << "called on invalid thread"; \ + return var; \ + } +#define CEF_REQUIRE_UIT_RETURN(var) CEF_REQUIRE_RETURN(CEF_UIT, var) +#define CEF_REQUIRE_IOT_RETURN(var) CEF_REQUIRE_RETURN(CEF_IOT, var) + +#define CEF_REQUIRE_RETURN_VOID(id) \ + if (!CEF_CURRENTLY_ON(id)) { \ + NOTREACHED() << "called on invalid thread"; \ + return; \ + } +#define CEF_REQUIRE_UIT_RETURN_VOID() CEF_REQUIRE_RETURN_VOID(CEF_UIT) +#define CEF_REQUIRE_IOT_RETURN_VOID() CEF_REQUIRE_RETURN_VOID(CEF_IOT) + +#define CEF_POST_TASK(id, task) \ + content::BrowserThread::PostTask(id, FROM_HERE, task) +#define CEF_POST_DELAYED_TASK(id, task, delay_ms) \ + content::BrowserThread::PostDelayedTask(id, FROM_HERE, task, \ + base::TimeDelta::FromMilliseconds(delay_ms)) + +#endif // CEF_LIBCEF_BROWSER_THREAD_UTIL_H_ diff --git a/libcef/browser/trace_impl.cc b/libcef/browser/trace_impl.cc new file mode 100644 index 000000000..580fee688 --- /dev/null +++ b/libcef/browser/trace_impl.cc @@ -0,0 +1,52 @@ +// 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 "include/cef_trace.h" +#include "libcef/browser/trace_subscriber.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" + +#include "base/time/time.h" + +bool CefBeginTracing(const CefString& categories, + CefRefPtr callback) { + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return false; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + CefTraceSubscriber* subscriber = CefContext::Get()->GetTraceSubscriber(); + if (!subscriber) + return false; + + return subscriber->BeginTracing(categories, callback); +} + +bool CefEndTracing(const CefString& tracing_file, + CefRefPtr callback) { + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return false; + } + + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + CefTraceSubscriber* subscriber = CefContext::Get()->GetTraceSubscriber(); + if (!subscriber) + return false; + + return subscriber->EndTracing(base::FilePath(tracing_file), callback); +} + +int64 CefNowFromSystemTraceTime() { + return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); +} diff --git a/libcef/browser/trace_subscriber.cc b/libcef/browser/trace_subscriber.cc new file mode 100644 index 000000000..158281d55 --- /dev/null +++ b/libcef/browser/trace_subscriber.cc @@ -0,0 +1,76 @@ +// 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 "libcef/browser/trace_subscriber.h" +#include "include/cef_trace.h" +#include "libcef/browser/thread_util.h" + +#include "base/debug/trace_event.h" +#include "content/public/browser/tracing_controller.h" + +using content::TracingController; + +CefTraceSubscriber::CefTraceSubscriber() + : collecting_trace_data_(false), + weak_factory_(this) { + CEF_REQUIRE_UIT(); +} + +CefTraceSubscriber::~CefTraceSubscriber() { + CEF_REQUIRE_UIT(); + if (collecting_trace_data_) { + TracingController::GetInstance()->DisableRecording( + base::FilePath(), + TracingController::TracingFileResultCallback()); + } +} + +bool CefTraceSubscriber::BeginTracing( + const std::string& categories, + CefRefPtr callback) { + CEF_REQUIRE_UIT(); + + if (collecting_trace_data_) + return false; + + collecting_trace_data_ = true; + + TracingController::EnableRecordingDoneCallback done_callback; + if (callback.get()) + done_callback = base::Bind(&CefCompletionCallback::OnComplete, callback); + + TracingController::GetInstance()->EnableRecording( + categories, TracingController::DEFAULT_OPTIONS, done_callback); + return true; +} + +bool CefTraceSubscriber::EndTracing( + const base::FilePath& tracing_file, + CefRefPtr callback) { + CEF_REQUIRE_UIT(); + + if (!collecting_trace_data_) + return false; + + TracingController::TracingFileResultCallback result_callback; + if (callback.get()) { + result_callback = + base::Bind(&CefTraceSubscriber::OnTracingFileResult, + weak_factory_.GetWeakPtr(), callback); + } + + TracingController::GetInstance()->DisableRecording( + tracing_file, result_callback); + return true; +} + +void CefTraceSubscriber::OnTracingFileResult( + CefRefPtr callback, + const base::FilePath& tracing_file) { + CEF_REQUIRE_UIT(); + + collecting_trace_data_ = false; + + callback->OnEndTracingComplete(tracing_file.value()); +} diff --git a/libcef/browser/trace_subscriber.h b/libcef/browser/trace_subscriber.h new file mode 100644 index 000000000..c26332fd2 --- /dev/null +++ b/libcef/browser/trace_subscriber.h @@ -0,0 +1,35 @@ +// 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_LIBCEF_BROWSER_TRACE_SUBSCRIBER_H_ +#define CEF_LIBCEF_BROWSER_TRACE_SUBSCRIBER_H_ +#pragma once + +#include "include/cef_trace.h" + +#include "base/files/file_path.h" +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" + +// May only be accessed on the browser process UI thread. +class CefTraceSubscriber { + public: + CefTraceSubscriber(); + virtual ~CefTraceSubscriber(); + + bool BeginTracing(const std::string& categories, + CefRefPtr callback); + bool EndTracing(const base::FilePath& tracing_file, + CefRefPtr callback); + + private: + void OnTracingFileResult(CefRefPtr callback, + const base::FilePath& tracing_file); + + bool collecting_trace_data_; + base::WeakPtrFactory weak_factory_; +}; + +#endif // CEF_LIBCEF_BROWSER_TRACE_SUBSCRIBER_H_ diff --git a/libcef/browser/url_network_delegate.cc b/libcef/browser/url_network_delegate.cc new file mode 100644 index 000000000..26c6a4001 --- /dev/null +++ b/libcef/browser/url_network_delegate.cc @@ -0,0 +1,184 @@ +// 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 "libcef/browser/url_network_delegate.h" + +#include + +#include "include/cef_urlrequest.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_user_data.h" +#include "libcef/common/request_impl.h" + +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" + +namespace { + +class CefAuthCallbackImpl : public CefAuthCallback { + public: + CefAuthCallbackImpl(const net::NetworkDelegate::AuthCallback& callback, + net::AuthCredentials* credentials) + : callback_(callback), + credentials_(credentials) { + } + ~CefAuthCallbackImpl() { + if (!callback_.is_null()) { + // The auth callback is still pending. Cancel it now. + if (CEF_CURRENTLY_ON_IOT()) { + CancelNow(callback_); + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefAuthCallbackImpl::CancelNow, callback_)); + } + } + } + + virtual void Continue(const CefString& username, + const CefString& password) OVERRIDE { + if (CEF_CURRENTLY_ON_IOT()) { + if (!callback_.is_null()) { + credentials_->Set(username, password); + callback_.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefAuthCallbackImpl::Continue, this, username, password)); + } + } + + virtual void Cancel() OVERRIDE { + if (CEF_CURRENTLY_ON_IOT()) { + if (!callback_.is_null()) { + CancelNow(callback_); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_IOT, base::Bind(&CefAuthCallbackImpl::Cancel, this)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void CancelNow(const net::NetworkDelegate::AuthCallback& callback) { + CEF_REQUIRE_IOT(); + callback.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION); + } + + net::NetworkDelegate::AuthCallback callback_; + net::AuthCredentials* credentials_; + + IMPLEMENT_REFCOUNTING(CefAuthCallbackImpl); +}; + +} // namespace + +CefNetworkDelegate::CefNetworkDelegate() { +} + +CefNetworkDelegate::~CefNetworkDelegate() { +} + +int CefNetworkDelegate::OnBeforeURLRequest( + net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr frame = browser->GetFrameForRequest(request); + + GURL old_url = request->url(); + + // Populate the request data. + CefRefPtr requestPtr(new CefRequestImpl()); + requestPtr->Set(request); + + // Give the client an opportunity to cancel the request. + if (handler->OnBeforeResourceLoad(browser.get(), frame, + requestPtr.get())) { + return net::ERR_ABORTED; + } + + GURL url = GURL(std::string(requestPtr->GetURL())); + if (old_url != url) + new_url ->Swap(&url); + + requestPtr->Get(request); + } + } + } + + return net::OK; +} + +net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr frame = browser->GetFrameForRequest(request); + + CefRefPtr callbackPtr( + new CefAuthCallbackImpl(callback, credentials)); + if (handler->GetAuthCredentials(browser.get(), + frame, + auth_info.is_proxy, + auth_info.challenger.host(), + auth_info.challenger.port(), + auth_info.realm, + auth_info.scheme, + callbackPtr.get())) { + return AUTH_REQUIRED_RESPONSE_IO_PENDING; + } else { + callbackPtr->Disconnect(); + } + } + } + } + + CefURLRequestUserData* user_data = + (CefURLRequestUserData*)request->GetUserData( + CefURLRequestUserData::kUserDataKey); + if (user_data) { + CefRefPtr client = user_data->GetClient(); + if (client.get()) { + CefRefPtr callbackPtr( + new CefAuthCallbackImpl(callback, credentials)); + if (client->GetAuthCredentials(auth_info.is_proxy, + auth_info.challenger.host(), + auth_info.challenger.port(), + auth_info.realm, + auth_info.scheme, + callbackPtr.get())) { + return AUTH_REQUIRED_RESPONSE_IO_PENDING; + } else { + callbackPtr->Disconnect(); + } + } + } + + return AUTH_REQUIRED_RESPONSE_NO_ACTION; +} + +bool CefNetworkDelegate::OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const { + return true; +} diff --git a/libcef/browser/url_network_delegate.h b/libcef/browser/url_network_delegate.h new file mode 100644 index 000000000..420fa69fa --- /dev/null +++ b/libcef/browser/url_network_delegate.h @@ -0,0 +1,34 @@ +// 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_LIBCEF_BROWSER_URL_NETWORK_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_URL_NETWORK_DELEGATE_H_ +#pragma once + +#include "net/base/network_delegate.h" + +// Used for intercepting resource requests, redirects and responses. The single +// instance of this class is managed by CefURLRequestContextGetter. +class CefNetworkDelegate : public net::NetworkDelegate { + public: + CefNetworkDelegate(); + ~CefNetworkDelegate(); + + private: + // net::NetworkDelegate methods. + virtual int OnBeforeURLRequest(net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) OVERRIDE; + virtual AuthRequiredResponse OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) OVERRIDE; + virtual bool OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const; + + DISALLOW_COPY_AND_ASSIGN(CefNetworkDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_NETWORK_DELEGATE_H_ diff --git a/libcef/browser/url_request_context_getter.cc b/libcef/browser/url_request_context_getter.cc new file mode 100644 index 000000000..5e48f1f1c --- /dev/null +++ b/libcef/browser/url_request_context_getter.cc @@ -0,0 +1,394 @@ +// 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 "libcef/browser/url_request_context_getter.h" + +#if defined(OS_WIN) +#include +#endif +#include +#include + +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/browser/scheme_handler.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_network_delegate.h" +#include "libcef/browser/url_request_context_proxy.h" +#include "libcef/browser/url_request_interceptor.h" +#include "libcef/common/cef_switches.h" +#include "libcef/common/content_client.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" +#include "base/threading/thread_restrictions.h" +#include "base/threading/worker_pool.h" +#include "chrome/browser/net/proxy_service_factory.h" +#include "content/browser/net/sqlite_persistent_cookie_store.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/cookie_crypto_delegate.h" +#include "content/public/common/content_client.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/url_constants.h" +#include "net/cert/cert_verifier.h" +#include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_server_properties_impl.h" +#include "net/http/http_util.h" +#include "net/http/transport_security_state.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/default_server_bound_cert_store.h" +#include "net/ssl/server_bound_cert_service.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "url/url_constants.h" +#include "net/url_request/http_user_agent_settings.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "net/url_request/url_request_job_manager.h" + +using content::BrowserThread; + +#if defined(OS_WIN) +#pragma comment(lib, "winhttp.lib") +#endif + +namespace { + +// An implementation of |HttpUserAgentSettings| that provides a static +// HTTP Accept-Language header value and uses |content::GetUserAgent| +// to provide the HTTP User-Agent header value. +class CefHttpUserAgentSettings : public net::HttpUserAgentSettings { + public: + explicit CefHttpUserAgentSettings(const std::string& raw_language_list) + : http_accept_language_(net::HttpUtil::GenerateAcceptLanguageHeader( + raw_language_list)) { + CEF_REQUIRE_IOT(); + } + + virtual ~CefHttpUserAgentSettings() { + CEF_REQUIRE_IOT(); + } + + // net::HttpUserAgentSettings implementation + virtual std::string GetAcceptLanguage() const OVERRIDE { + CEF_REQUIRE_IOT(); + return http_accept_language_; + } + + virtual std::string GetUserAgent() const OVERRIDE { + CEF_REQUIRE_IOT(); + return CefContentClient::Get()->GetUserAgent(); + } + + private: + const std::string http_accept_language_; + + DISALLOW_COPY_AND_ASSIGN(CefHttpUserAgentSettings); +}; + +} // namespace + +CefURLRequestContextGetter::CefURLRequestContextGetter( + base::MessageLoop* io_loop, + base::MessageLoop* file_loop, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) + : io_loop_(io_loop), + file_loop_(file_loop), + request_interceptors_(request_interceptors.Pass()) { + // Must first be created on the UI thread. + CEF_REQUIRE_UIT(); + + std::swap(protocol_handlers_, *protocol_handlers); +} + +CefURLRequestContextGetter::~CefURLRequestContextGetter() { + CEF_REQUIRE_IOT(); + STLDeleteElements(&url_request_context_proxies_); + + // Delete the ProxyService object here so that any pending requests will be + // canceled before the associated URLRequestContext is destroyed in this + // object's destructor. + storage_->set_proxy_service(NULL); +} + +net::URLRequestContext* CefURLRequestContextGetter::GetURLRequestContext() { + CEF_REQUIRE_IOT(); + + if (!url_request_context_.get()) { + const base::FilePath& cache_path = CefContext::Get()->cache_path(); + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + const CefSettings& settings = CefContext::Get()->settings(); + + url_request_context_.reset(new net::URLRequestContext()); + storage_.reset( + new net::URLRequestContextStorage(url_request_context_.get())); + + bool persist_session_cookies = + (settings.persist_session_cookies || + command_line.HasSwitch(switches::kPersistSessionCookies)); + SetCookieStoragePath(cache_path, persist_session_cookies); + + storage_->set_network_delegate(new CefNetworkDelegate); + + storage_->set_server_bound_cert_service(new net::ServerBoundCertService( + new net::DefaultServerBoundCertStore(NULL), + base::WorkerPool::GetTaskRunner(true))); + storage_->set_http_user_agent_settings( + new CefHttpUserAgentSettings("en-us,en")); + + storage_->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); + storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + storage_->set_transport_security_state(new net::TransportSecurityState); + + scoped_ptr system_proxy_service; + system_proxy_service.reset( + ProxyServiceFactory::CreateProxyService( + NULL, + url_request_context_.get(), + url_request_context_->network_delegate(), + CefContentBrowserClient::Get()->proxy_config_service().release(), + command_line, + true)); + storage_->set_proxy_service(system_proxy_service.release()); + + storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); + + // Add support for single sign-on. + url_security_manager_.reset(net::URLSecurityManager::Create(NULL, NULL)); + + std::vector supported_schemes; + supported_schemes.push_back("basic"); + supported_schemes.push_back("digest"); + supported_schemes.push_back("ntlm"); + supported_schemes.push_back("negotiate"); + + storage_->set_http_auth_handler_factory( + net::HttpAuthHandlerRegistryFactory::Create( + supported_schemes, + url_security_manager_.get(), + url_request_context_->host_resolver(), + std::string(), + false, + false)); + storage_->set_http_server_properties( + make_scoped_ptr( + new net::HttpServerPropertiesImpl)); + + net::HttpCache::DefaultBackend* main_backend = + new net::HttpCache::DefaultBackend( + cache_path.empty() ? net::MEMORY_CACHE : net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + cache_path, + 0, + BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::CACHE)); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.host_resolver = + url_request_context_->host_resolver(); + network_session_params.cert_verifier = + url_request_context_->cert_verifier(); + network_session_params.transport_security_state = + url_request_context_->transport_security_state(); + network_session_params.server_bound_cert_service = + url_request_context_->server_bound_cert_service(); + network_session_params.proxy_service = + url_request_context_->proxy_service(); + network_session_params.ssl_config_service = + url_request_context_->ssl_config_service(); + network_session_params.http_auth_handler_factory = + url_request_context_->http_auth_handler_factory(); + network_session_params.network_delegate = + url_request_context_->network_delegate(); + network_session_params.http_server_properties = + url_request_context_->http_server_properties(); + network_session_params.ignore_certificate_errors = + (settings.ignore_certificate_errors || + command_line.HasSwitch(switches::kIgnoreCertificateErrors)); + + net::HttpCache* main_cache = new net::HttpCache(network_session_params, + main_backend); + storage_->set_http_transaction_factory(main_cache); + +#if !defined(DISABLE_FTP_SUPPORT) + ftp_transaction_factory_.reset( + new net::FtpNetworkLayer(network_session_params.host_resolver)); +#endif + + scoped_ptr job_factory( + new net::URLRequestJobFactoryImpl()); + job_factory_impl_ = job_factory.get(); + + scheme::InstallInternalProtectedHandlers(job_factory.get(), + &protocol_handlers_, + ftp_transaction_factory_.get()); + protocol_handlers_.clear(); + + // Set up interceptors in the reverse order. + scoped_ptr top_job_factory = + job_factory.PassAs(); + for (content::URLRequestInterceptorScopedVector::reverse_iterator i = + request_interceptors_.rbegin(); + i != request_interceptors_.rend(); + ++i) { + top_job_factory.reset(new net::URLRequestInterceptingJobFactory( + top_job_factory.Pass(), make_scoped_ptr(*i))); + } + request_interceptors_.weak_clear(); + + storage_->set_job_factory(top_job_factory.release()); + + request_interceptor_.reset(new CefRequestInterceptor); + } + + return url_request_context_.get(); +} + +scoped_refptr + CefURLRequestContextGetter::GetNetworkTaskRunner() const { + return BrowserThread::GetMessageLoopProxyForThread(CEF_IOT); +} + +net::HostResolver* CefURLRequestContextGetter::host_resolver() { + return url_request_context_->host_resolver(); +} + +void CefURLRequestContextGetter::SetCookieStoragePath( + const base::FilePath& path, + bool persist_session_cookies) { + CEF_REQUIRE_IOT(); + + if (url_request_context_->cookie_store() && + ((cookie_store_path_.empty() && path.empty()) || + cookie_store_path_ == path)) { + // The path has not changed so don't do anything. + return; + } + + scoped_refptr persistent_store; + if (!path.empty()) { + // TODO(cef): Move directory creation to the blocking pool instead of + // allowing file IO on this thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (base::DirectoryExists(path) || + base::CreateDirectory(path)) { + const base::FilePath& cookie_path = path.AppendASCII("Cookies"); + persistent_store = + new content::SQLitePersistentCookieStore( + cookie_path, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), + persist_session_cookies, + NULL, + NULL); + } else { + NOTREACHED() << "The cookie storage directory could not be created"; + } + } + + // Set the new cookie store that will be used for all new requests. The old + // cookie store, if any, will be automatically flushed and closed when no + // longer referenced. + scoped_refptr cookie_monster = + new net::CookieMonster(persistent_store.get(), NULL); + storage_->set_cookie_store(cookie_monster); + if (persistent_store.get() && persist_session_cookies) + cookie_monster->SetPersistSessionCookies(true); + cookie_store_path_ = path; + + // Restore the previously supported schemes. + SetCookieSupportedSchemes(cookie_supported_schemes_); +} + +void CefURLRequestContextGetter::SetCookieSupportedSchemes( + const std::vector& schemes) { + CEF_REQUIRE_IOT(); + + cookie_supported_schemes_ = schemes; + + if (cookie_supported_schemes_.empty()) { + cookie_supported_schemes_.push_back("http"); + cookie_supported_schemes_.push_back("https"); + } + + std::set scheme_set; + std::vector::const_iterator it = + cookie_supported_schemes_.begin(); + for (; it != cookie_supported_schemes_.end(); ++it) + scheme_set.insert(*it); + + const char** arr = new const char*[scheme_set.size()]; + std::set::const_iterator it2 = scheme_set.begin(); + for (int i = 0; it2 != scheme_set.end(); ++it2, ++i) + arr[i] = it2->c_str(); + + url_request_context_->cookie_store()->GetCookieMonster()-> + SetCookieableSchemes(arr, scheme_set.size()); + + delete [] arr; +} + +CefURLRequestContextProxy* + CefURLRequestContextGetter::CreateURLRequestContextProxy() { + CEF_REQUIRE_IOT(); + CefURLRequestContextProxy* proxy = new CefURLRequestContextProxy(this); + url_request_context_proxies_.insert(proxy); + return proxy; +} + +void CefURLRequestContextGetter::ReleaseURLRequestContextProxy( + CefURLRequestContextProxy* proxy) { + CEF_REQUIRE_IOT(); + + // Don't do anything if we're currently shutting down. The proxy objects will + // be deleted when this object is destroyed. + if (CefContext::Get()->shutting_down()) + return; + + if (proxy->url_requests()->size() == 0) { + // Safe to delete the proxy. + RequestContextProxySet::iterator it = + url_request_context_proxies_.find(proxy); + DCHECK(it != url_request_context_proxies_.end()); + url_request_context_proxies_.erase(it); + delete proxy; + } else { + proxy->increment_delete_try_count(); + if (proxy->delete_try_count() <= 1) { + // Cancel the pending requests. This may result in additional tasks being + // posted on the IO thread. + std::set::iterator it = + proxy->url_requests()->begin(); + for (; it != proxy->url_requests()->end(); ++it) + const_cast(*it)->Cancel(); + + // Try to delete the proxy again later. + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefURLRequestContextGetter::ReleaseURLRequestContextProxy, + this, proxy)); + } else { + NOTREACHED() << + "too many retries to delete URLRequestContext proxy object"; + } + } +} + +void CefURLRequestContextGetter::CreateProxyConfigService() { + if (proxy_config_service_.get()) + return; + + proxy_config_service_.reset( + net::ProxyService::CreateSystemProxyConfigService( + io_loop_->message_loop_proxy(), file_loop_)); +} diff --git a/libcef/browser/url_request_context_getter.h b/libcef/browser/url_request_context_getter.h new file mode 100644 index 000000000..656cdcd28 --- /dev/null +++ b/libcef/browser/url_request_context_getter.h @@ -0,0 +1,133 @@ +// 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. + +#ifndef CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_H_ +#pragma once + +#include +#include +#include + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/content_browser_client.h" +#include "net/url_request/url_request_context_getter.h" +#include "net/url_request/url_request_job_factory.h" + +namespace base { +class MessageLoop; +} + +namespace net { +class FtpTransactionFactory; +class HostResolver; +class ProxyConfigService; +class URLRequestContextStorage; +class URLRequestJobFactory; +class URLRequestJobFactoryImpl; +class URLSecurityManager; +} + +class CefRequestInterceptor; +class CefURLRequestContextProxy; + +/* +// Classes used in network request processing: +// +// RC = net::URLRequestContext +// Owns various network-related objects including the global cookie manager. +// +// RCP = CefURLRequestContextProxy +// Creates the CSP and forwards requests to the objects owned by RC. +// +// CSP = CefCookieStoreProxy +// Gives the CefCookieManager associated with CefBrowserHostImpl an +// opportunity to handle cookie requests. Otherwise forwards requests via RC +// to the global cookie manager. +// +// RCG = CefURLRequestContextGetter +// Creates the RC and manages RCP lifespan. +// +// RCGP = CefURLRequestContextGetterProxy +// Causes the RCG to create and destroy browser-specific RCPs. +// +// Relationship diagram: +// ref = reference (scoped_refptr) +// own = ownership (scoped_ptr) +// ptr = raw pointer +// +// global cookie manager, etc... +// ^ +// | +// /-own-> RC <-ptr-\ +// / \ +// / /<-ptr-\ \ +// / / \ \ +// CefBrowserContext -ref-> RCG --own-> RCP --ref-> CSP +// ^ ^ / +// ref ptr / +// | / / +// CefBrowserHostImpl -ref-> RCGP----/ / +// ^ / +// \-ref--------------------------/ +*/ + +class CefURLRequestContextGetter : public net::URLRequestContextGetter { + public: + CefURLRequestContextGetter( + base::MessageLoop* io_loop, + base::MessageLoop* file_loop, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors); + virtual ~CefURLRequestContextGetter(); + + // net::URLRequestContextGetter implementation. + virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; + virtual scoped_refptr + GetNetworkTaskRunner() const OVERRIDE; + + net::HostResolver* host_resolver(); + net::URLRequestJobFactoryImpl* job_factory_impl() const { + return job_factory_impl_; + } + + void SetCookieStoragePath(const base::FilePath& path, + bool persist_session_cookies); + void SetCookieSupportedSchemes(const std::vector& schemes); + + // Manage URLRequestContext proxy objects. It's important that proxy objects + // not be destroyed while any in-flight URLRequests exist. These methods + // manage that requirement. + CefURLRequestContextProxy* CreateURLRequestContextProxy(); + void ReleaseURLRequestContextProxy(CefURLRequestContextProxy* proxy); + + private: + void CreateProxyConfigService(); + + base::MessageLoop* io_loop_; + base::MessageLoop* file_loop_; + + scoped_ptr proxy_config_service_; + scoped_ptr request_interceptor_; + scoped_ptr storage_; + scoped_ptr url_request_context_; + scoped_ptr url_security_manager_; + scoped_ptr ftp_transaction_factory_; + content::ProtocolHandlerMap protocol_handlers_; + content::URLRequestInterceptorScopedVector request_interceptors_; + net::URLRequestJobFactoryImpl* job_factory_impl_; + + typedef std::set RequestContextProxySet; + RequestContextProxySet url_request_context_proxies_; + + base::FilePath cookie_store_path_; + std::vector cookie_supported_schemes_; + + DISALLOW_COPY_AND_ASSIGN(CefURLRequestContextGetter); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_H_ diff --git a/libcef/browser/url_request_context_getter_proxy.cc b/libcef/browser/url_request_context_getter_proxy.cc new file mode 100644 index 000000000..5eaaa443a --- /dev/null +++ b/libcef/browser/url_request_context_getter_proxy.cc @@ -0,0 +1,42 @@ +// 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 "libcef/browser/url_request_context_getter_proxy.h" +#include "libcef/browser/thread_util.h" +#include "libcef/browser/url_request_context_getter.h" +#include "libcef/browser/url_request_context_proxy.h" + +CefURLRequestContextGetterProxy::CefURLRequestContextGetterProxy( + CefRefPtr handler, + CefURLRequestContextGetter* parent) + : handler_(handler), + parent_(parent), + context_proxy_(NULL) { + DCHECK(parent); +} + +CefURLRequestContextGetterProxy::~CefURLRequestContextGetterProxy() { + CEF_REQUIRE_IOT(); + if (context_proxy_) + parent_->ReleaseURLRequestContextProxy(context_proxy_); +} + +net::URLRequestContext* + CefURLRequestContextGetterProxy::GetURLRequestContext() { + CEF_REQUIRE_IOT(); + if (!context_proxy_) { + context_proxy_ = parent_->CreateURLRequestContextProxy(); + context_proxy_->Initialize(handler_); + } + return context_proxy_; +} + +scoped_refptr + CefURLRequestContextGetterProxy::GetNetworkTaskRunner() const { + return parent_->GetNetworkTaskRunner(); +} + +net::HostResolver* CefURLRequestContextGetterProxy::GetHostResolver() const { + return parent_->host_resolver(); +} diff --git a/libcef/browser/url_request_context_getter_proxy.h b/libcef/browser/url_request_context_getter_proxy.h new file mode 100644 index 000000000..c134fb533 --- /dev/null +++ b/libcef/browser/url_request_context_getter_proxy.h @@ -0,0 +1,46 @@ +// 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_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_PROXY_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_PROXY_H_ +#pragma once + +#include "include/cef_request_context_handler.h" + +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_request_context_getter.h" + +class CefURLRequestContextGetter; +class CefURLRequestContextProxy; + +namespace net { +class HostResolver; +} + +class CefURLRequestContextGetterProxy : public net::URLRequestContextGetter { + public: + CefURLRequestContextGetterProxy(CefRefPtr handler, + CefURLRequestContextGetter* parent); + virtual ~CefURLRequestContextGetterProxy(); + + // net::URLRequestContextGetter implementation. + virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; + virtual scoped_refptr + GetNetworkTaskRunner() const OVERRIDE; + + net::HostResolver* GetHostResolver() const; + + CefRefPtr handler() const { return handler_; } + + private: + CefRefPtr handler_; + scoped_refptr parent_; + + // The |context_proxy_| object is owned by |parent_|. + CefURLRequestContextProxy* context_proxy_; + + DISALLOW_COPY_AND_ASSIGN(CefURLRequestContextGetterProxy); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_PROXY_H_ diff --git a/libcef/browser/url_request_context_proxy.cc b/libcef/browser/url_request_context_proxy.cc new file mode 100644 index 000000000..3bc9f1522 --- /dev/null +++ b/libcef/browser/url_request_context_proxy.cc @@ -0,0 +1,167 @@ +// 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 "libcef/browser/url_request_context_proxy.h" + +#include + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/cookie_manager_impl.h" +#include "libcef/browser/thread_util.h" + +#include "base/logging.h" +#include "base/message_loop/message_loop_proxy.h" +#include "net/cookies/cookie_store.h" +#include "net/url_request/url_request_context_getter.h" + +namespace { + +class CefCookieStoreProxy : public net::CookieStore { + public: + CefCookieStoreProxy(net::URLRequestContext* parent, + CefRefPtr handler) + : parent_(parent), + handler_(handler) { + } + virtual ~CefCookieStoreProxy() { + CEF_REQUIRE_IOT(); + } + + // net::CookieStore methods. + virtual void SetCookieWithOptionsAsync( + const GURL& url, + const std::string& cookie_line, + const net::CookieOptions& options, + const SetCookiesCallback& callback) OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->SetCookieWithOptionsAsync(url, cookie_line, options, + callback); + } + + virtual void GetCookiesWithOptionsAsync( + const GURL& url, const net::CookieOptions& options, + const GetCookiesCallback& callback) OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->GetCookiesWithOptionsAsync(url, options, callback); + } + + virtual void DeleteCookieAsync(const GURL& url, + const std::string& cookie_name, + const base::Closure& callback) OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteCookieAsync(url, cookie_name, callback); + } + + virtual void GetAllCookiesForURLAsync( + const GURL& url, + const GetCookieListCallback& callback) OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->GetAllCookiesForURLAsync(url, callback); + } + + virtual void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin, + const base::Time& delete_end, + const DeleteCallback& callback) + OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteAllCreatedBetweenAsync(delete_begin, delete_end, + callback); + } + + virtual void DeleteAllCreatedBetweenForHostAsync( + const base::Time delete_begin, + const base::Time delete_end, + const GURL& url, + const DeleteCallback& callback) OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteAllCreatedBetweenForHostAsync(delete_begin, delete_end, + url, callback); + } + + virtual void DeleteSessionCookiesAsync(const DeleteCallback& callback) + OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteSessionCookiesAsync(callback); + } + + virtual net::CookieMonster* GetCookieMonster() OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + return cookie_store->GetCookieMonster(); + } + + private: + net::CookieStore* GetCookieStore() { + CEF_REQUIRE_IOT(); + + scoped_refptr cookie_store; + + if (handler_.get()) { + // Get the manager from the handler. + CefRefPtr manager = handler_->GetCookieManager(); + if (manager.get()) { + cookie_store = + reinterpret_cast( + manager.get())->cookie_monster(); + DCHECK(cookie_store); + } + } + + if (!cookie_store) { + // Use the global cookie store. + cookie_store = parent_->cookie_store(); + } + + DCHECK(cookie_store); + return cookie_store; + } + + // This pointer is guaranteed by the CefRequestContextProxy object. + net::URLRequestContext* parent_; + CefRefPtr handler_; + + DISALLOW_COPY_AND_ASSIGN(CefCookieStoreProxy); +}; + +} // namespace + + +CefURLRequestContextProxy::CefURLRequestContextProxy( + net::URLRequestContextGetter* parent) + : parent_(parent), + delete_try_count_(0) { +} + +CefURLRequestContextProxy::~CefURLRequestContextProxy() { + CEF_REQUIRE_IOT(); +} + +void CefURLRequestContextProxy::Initialize( + CefRefPtr handler) { + CEF_REQUIRE_IOT(); + + net::URLRequestContext* context = parent_->GetURLRequestContext(); + + // Cookie store that proxies to the browser implementation. + cookie_store_proxy_ = new CefCookieStoreProxy(context, handler); + set_cookie_store(cookie_store_proxy_); + + // All other values refer to the parent request context. + set_net_log(context->net_log()); + set_host_resolver(context->host_resolver()); + set_cert_verifier(context->cert_verifier()); + set_transport_security_state(context->transport_security_state()); + set_server_bound_cert_service(context->server_bound_cert_service()); + set_fraudulent_certificate_reporter( + context->fraudulent_certificate_reporter()); + set_proxy_service(context->proxy_service()); + set_ssl_config_service(context->ssl_config_service()); + set_http_auth_handler_factory(context->http_auth_handler_factory()); + set_http_transaction_factory(context->http_transaction_factory()); + set_network_delegate(context->network_delegate()); + set_http_server_properties(context->http_server_properties()); + set_transport_security_state(context->transport_security_state()); + set_http_user_agent_settings(const_cast( + context->http_user_agent_settings())); + set_job_factory(context->job_factory()); +} diff --git a/libcef/browser/url_request_context_proxy.h b/libcef/browser/url_request_context_proxy.h new file mode 100644 index 000000000..bf7a3bc31 --- /dev/null +++ b/libcef/browser/url_request_context_proxy.h @@ -0,0 +1,43 @@ +// 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_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_PROXY_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_PROXY_H_ +#pragma once + +#include "include/cef_request_context_handler.h" + +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_request_context.h" + +class CefBrowserHostImpl; + +namespace net { +class CookieStore; +class URLRequestContextGetter; +} + +class CefURLRequestContextProxy : public net::URLRequestContext { + public: + explicit CefURLRequestContextProxy(net::URLRequestContextGetter* parent); + virtual ~CefURLRequestContextProxy(); + + void Initialize(CefRefPtr handler); + + // We may try to delete this proxy multiple times if URLRequests are still + // pending. Keep track of the number of tries so that they don't become + // excessive. + int delete_try_count() const { return delete_try_count_; } + void increment_delete_try_count() { delete_try_count_++; } + + private: + net::URLRequestContextGetter* parent_; + scoped_refptr cookie_store_proxy_; + + int delete_try_count_; + + DISALLOW_COPY_AND_ASSIGN(CefURLRequestContextProxy); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_PROXY_H_ diff --git a/libcef/browser/url_request_interceptor.cc b/libcef/browser/url_request_interceptor.cc new file mode 100644 index 000000000..64bc0cf31 --- /dev/null +++ b/libcef/browser/url_request_interceptor.cc @@ -0,0 +1,94 @@ +// 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 "libcef/browser/url_request_interceptor.h" + +#include + +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/resource_request_job.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/request_impl.h" + +#include "net/url_request/url_request_job_manager.h" +#include "net/url_request/url_request_redirect_job.h" + +CefRequestInterceptor::CefRequestInterceptor() { + CEF_REQUIRE_IOT(); + net::URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(this); +} + +CefRequestInterceptor::~CefRequestInterceptor() { + CEF_REQUIRE_IOT(); + net::URLRequestJobManager::GetInstance()-> + UnregisterRequestInterceptor(this); +} + +net::URLRequestJob* CefRequestInterceptor::MaybeIntercept( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr frame = browser->GetFrameForRequest(request); + + // Populate the request data. + CefRefPtr req(CefRequest::Create()); + static_cast(req.get())->Set(request); + + // Give the client an opportunity to replace the request. + CefRefPtr resourceHandler = + handler->GetResourceHandler(browser.get(), frame, req); + if (resourceHandler.get()) + return new CefResourceRequestJob(request, network_delegate, + resourceHandler); + } + } + } + + return NULL; +} + +net::URLRequestJob* CefRequestInterceptor::MaybeInterceptRedirect( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const GURL& location) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + if (browser.get()) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + CefRefPtr frame = browser->GetFrameForRequest(request); + + // Give the client an opportunity to redirect the request. + CefString newUrlStr = location.spec(); + handler->OnResourceRedirect(browser.get(), frame, request->url().spec(), + newUrlStr); + if (newUrlStr != location.spec()) { + GURL new_url = GURL(std::string(newUrlStr)); + if (!new_url.is_empty() && new_url.is_valid()) { + return new net::URLRequestRedirectJob( + request, network_delegate, new_url, + net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, + "Resource Redirect"); + } + } + } + } + } + + return NULL; +} + +net::URLRequestJob* CefRequestInterceptor::MaybeInterceptResponse( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) { + return NULL; +} diff --git a/libcef/browser/url_request_interceptor.h b/libcef/browser/url_request_interceptor.h new file mode 100644 index 000000000..6dacc7e15 --- /dev/null +++ b/libcef/browser/url_request_interceptor.h @@ -0,0 +1,33 @@ +// 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_LIBCEF_BROWSER_URL_REQUEST_INTERCEPTOR_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_INTERCEPTOR_H_ +#pragma once + +#include "net/url_request/url_request.h" + +// Used for intercepting resource requests, redirects and responses. The single +// instance of this class is managed by CefURLRequestContextGetter. +class CefRequestInterceptor : public net::URLRequest::Interceptor { + public: + CefRequestInterceptor(); + ~CefRequestInterceptor(); + + // net::URLRequest::Interceptor methods. + virtual net::URLRequestJob* MaybeIntercept( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) OVERRIDE; + virtual net::URLRequestJob* MaybeInterceptRedirect( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const GURL& location) OVERRIDE; + virtual net::URLRequestJob* MaybeInterceptResponse( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(CefRequestInterceptor); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_INTERCEPTOR_H_ diff --git a/libcef/browser/url_request_user_data.cc b/libcef/browser/url_request_user_data.cc new file mode 100644 index 000000000..c21885241 --- /dev/null +++ b/libcef/browser/url_request_user_data.cc @@ -0,0 +1,18 @@ +// 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 "libcef/browser/url_request_user_data.h" + +CefURLRequestUserData::CefURLRequestUserData(CefRefPtr client) + : client_(client) {} + +CefURLRequestUserData::~CefURLRequestUserData() {} + +CefRefPtr CefURLRequestUserData::GetClient() { + return client_; +} + +// static +const void* CefURLRequestUserData::kUserDataKey = + static_cast(&CefURLRequestUserData::kUserDataKey); diff --git a/libcef/browser/url_request_user_data.h b/libcef/browser/url_request_user_data.h new file mode 100644 index 000000000..37b8c0253 --- /dev/null +++ b/libcef/browser/url_request_user_data.h @@ -0,0 +1,27 @@ +// 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_LIBCEF_BROWSER_URL_REQUEST_USER_DATA_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_USER_DATA_H_ + +#include "include/cef_base.h" +#include "base/supports_user_data.h" + +#include "include/cef_urlrequest.h" + +// Used to annotate all URLRequests for which the request can be associated +// with the CefURLRequestClient. +class CefURLRequestUserData : public base::SupportsUserData::Data { + public: + CefURLRequestUserData(CefRefPtr client); + virtual ~CefURLRequestUserData(); + + CefRefPtr GetClient(); + static const void* kUserDataKey; + +private: + CefRefPtr client_; +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_USER_DATA_H_ diff --git a/libcef/browser/web_contents_view_osr.cc b/libcef/browser/web_contents_view_osr.cc new file mode 100644 index 000000000..673b112c3 --- /dev/null +++ b/libcef/browser/web_contents_view_osr.cc @@ -0,0 +1,167 @@ +// 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 "libcef/browser/web_contents_view_osr.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/render_widget_host_view_osr.h" +#include "libcef/common/drag_data_impl.h" + +#include "content/public/browser/render_widget_host.h" + +CefWebContentsViewOSR::CefWebContentsViewOSR( + content::WebContents* web_contents, + content::WebContentsViewDelegate* delegate) + : web_contents_(web_contents), + view_(NULL) { +} + +CefWebContentsViewOSR::~CefWebContentsViewOSR() { +} + +gfx::NativeView CefWebContentsViewOSR::GetNativeView() const { + return gfx::NativeView(); +} + +gfx::NativeView CefWebContentsViewOSR::GetContentNativeView() const { + return gfx::NativeView(); +} + +gfx::NativeWindow CefWebContentsViewOSR::GetTopLevelNativeWindow() const { + return gfx::NativeWindow(); +} + +void CefWebContentsViewOSR::GetContainerBounds(gfx::Rect* out) const { + *out = GetViewBounds(); +} + +void CefWebContentsViewOSR::SizeContents(const gfx::Size& size) { +} + +void CefWebContentsViewOSR::Focus() { +} + +void CefWebContentsViewOSR::SetInitialFocus() { +} + +void CefWebContentsViewOSR::StoreFocus() { +} + +void CefWebContentsViewOSR::RestoreFocus() { +} + +content::DropData* CefWebContentsViewOSR::GetDropData() const { + return NULL; +} + +gfx::Rect CefWebContentsViewOSR::GetViewBounds() const { + return view_ ? view_->GetViewBounds() : gfx::Rect(); +} + +void CefWebContentsViewOSR::CreateView(const gfx::Size& initial_size, + gfx::NativeView context) { +} + +content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget( + content::RenderWidgetHost* render_widget_host) { + if (render_widget_host->GetView()) { + return static_cast( + render_widget_host->GetView()); + } + + view_ = new CefRenderWidgetHostViewOSR(render_widget_host); + return view_; +} + +content::RenderWidgetHostViewBase* + CefWebContentsViewOSR::CreateViewForPopupWidget( + content::RenderWidgetHost* render_widget_host) { + return new CefRenderWidgetHostViewOSR(render_widget_host); +} + +void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) { +} + +void CefWebContentsViewOSR::RenderViewCreated(content::RenderViewHost* host) { + if (view_) + view_->InstallTransparency(); +} + +void CefWebContentsViewOSR::RenderViewSwappedIn( + content::RenderViewHost* host) { +} + +void CefWebContentsViewOSR::SetOverscrollControllerEnabled(bool enabled) { +} + +#if defined(OS_MACOSX) +void CefWebContentsViewOSR::SetAllowOverlappingViews(bool overlapping) { +} + +bool CefWebContentsViewOSR::GetAllowOverlappingViews() const { + return false; +} + +void CefWebContentsViewOSR::SetOverlayView( + content::WebContentsView* overlay, + const gfx::Point& offset) { +} +void CefWebContentsViewOSR::RemoveOverlayView() { +} + +bool CefWebContentsViewOSR::IsEventTracking() const { + return false; +} + +void CefWebContentsViewOSR::CloseTabAfterEventTracking() { +} +#endif // defined(OS_MACOSX) + +void CefWebContentsViewOSR::StartDragging( + const content::DropData& drop_data, + blink::WebDragOperationsMask allowed_ops, + const gfx::ImageSkia& image, + const gfx::Vector2d& image_offset, + const content::DragEventSourceInfo& event_info) { + CefRefPtr browser; + CefRefPtr handler; + bool handled = false; + CefRenderWidgetHostViewOSR* view = + static_cast(view_); + if (view) + browser = view->browser_impl(); + if (browser.get()) + handler = browser->GetClient()->GetRenderHandler(); + DCHECK(handler.get()); + if (handler.get()) { + CefRefPtr drag_data(new CefDragDataImpl(drop_data)); + drag_data->SetReadOnly(true); + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + handled = handler->StartDragging(browser->GetBrowser(), + drag_data.get(), + static_cast(allowed_ops), + event_info.event_location.x(), + event_info.event_location.y()); + } + if (!handled && web_contents_) + web_contents_->SystemDragEnded(); +} + +void CefWebContentsViewOSR::UpdateDragCursor( + blink::WebDragOperation operation) { + CefRefPtr browser; + CefRefPtr handler; + CefRenderWidgetHostViewOSR* view = + static_cast(view_); + if (view) + browser = view->browser_impl(); + if (browser.get()) + handler = browser->GetClient()->GetRenderHandler(); + DCHECK(handler.get()); + if (handler.get()) { + handler->UpdateDragCursor(browser->GetBrowser(), + static_cast(operation)); + } +} diff --git a/libcef/browser/web_contents_view_osr.h b/libcef/browser/web_contents_view_osr.h new file mode 100644 index 000000000..a6f0431af --- /dev/null +++ b/libcef/browser/web_contents_view_osr.h @@ -0,0 +1,76 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_ +#define CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_ + +#include "content/browser/renderer_host/render_view_host_delegate_view.h" +#include "content/browser/web_contents/web_contents_view.h" + +namespace content { +class WebContents; +class WebContentsViewDelegate; +} + +class CefRenderWidgetHostViewOSR; + +// An implementation of WebContentsView for off-screen rendering. +class CefWebContentsViewOSR : public content::WebContentsView, + public content::RenderViewHostDelegateView { + public: + CefWebContentsViewOSR(content::WebContents* web_contents, + content::WebContentsViewDelegate* delegate); + virtual ~CefWebContentsViewOSR(); + + // WebContentsView methods. + virtual gfx::NativeView GetNativeView() const OVERRIDE; + virtual gfx::NativeView GetContentNativeView() const OVERRIDE; + virtual gfx::NativeWindow GetTopLevelNativeWindow() const OVERRIDE; + virtual void GetContainerBounds(gfx::Rect* out) const OVERRIDE; + virtual void SizeContents(const gfx::Size& size) OVERRIDE; + virtual void Focus() OVERRIDE; + virtual void SetInitialFocus() OVERRIDE; + virtual void StoreFocus() OVERRIDE; + virtual void RestoreFocus() OVERRIDE; + virtual content::DropData* GetDropData() const OVERRIDE; + virtual gfx::Rect GetViewBounds() const OVERRIDE; + virtual void CreateView(const gfx::Size& initial_size, + gfx::NativeView context) OVERRIDE; + virtual content::RenderWidgetHostViewBase* CreateViewForWidget( + content::RenderWidgetHost* render_widget_host) OVERRIDE; + virtual content::RenderWidgetHostViewBase* CreateViewForPopupWidget( + content::RenderWidgetHost* render_widget_host) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; + virtual void RenderViewCreated(content::RenderViewHost* host) OVERRIDE; + virtual void RenderViewSwappedIn(content::RenderViewHost* host) OVERRIDE; + virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; + +#if defined(OS_MACOSX) + virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE; + virtual bool GetAllowOverlappingViews() const OVERRIDE; + virtual void SetOverlayView(content::WebContentsView* overlay, + const gfx::Point& offset) OVERRIDE; + virtual void RemoveOverlayView() OVERRIDE; + virtual bool IsEventTracking() const OVERRIDE; + virtual void CloseTabAfterEventTracking() OVERRIDE; +#endif + + // RenderViewHostDelegateView methods. + virtual void StartDragging( + const content::DropData& drop_data, + blink::WebDragOperationsMask allowed_ops, + const gfx::ImageSkia& image, + const gfx::Vector2d& image_offset, + const content::DragEventSourceInfo& event_info) OVERRIDE; + virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE; + + private: + content::WebContents* web_contents_; + CefRenderWidgetHostViewOSR* view_; + + DISALLOW_COPY_AND_ASSIGN(CefWebContentsViewOSR); +}; + +#endif // CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_ diff --git a/libcef/browser/web_plugin_impl.cc b/libcef/browser/web_plugin_impl.cc new file mode 100644 index 000000000..3cb4ecc3c --- /dev/null +++ b/libcef/browser/web_plugin_impl.cc @@ -0,0 +1,224 @@ +// 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 "libcef/browser/web_plugin_impl.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "content/browser/plugin_service_impl.h" + +namespace { + +void PluginsCallbackImpl( + CefRefPtr visitor, + const std::vector& all_plugins) { + CEF_REQUIRE_UIT(); + + int count = 0; + int total = static_cast(all_plugins.size()); + + std::vector::const_iterator it = all_plugins.begin(); + for (; it != all_plugins.end(); ++it, ++count) { + CefRefPtr info(new CefWebPluginInfoImpl(*it)); + if (!visitor->Visit(info.get(), count, total)) + break; + } +} + +} // namespace + + +// CefWebPluginInfoImpl + +CefWebPluginInfoImpl::CefWebPluginInfoImpl( + const content::WebPluginInfo& plugin_info) + : plugin_info_(plugin_info) { +} + +CefString CefWebPluginInfoImpl::GetName() { + return plugin_info_.name; +} + +CefString CefWebPluginInfoImpl::GetPath() { + return plugin_info_.path.value(); +} + +CefString CefWebPluginInfoImpl::GetVersion() { + return plugin_info_.version; +} + +CefString CefWebPluginInfoImpl::GetDescription() { + return plugin_info_.desc; +} + + +// Global functions. + +void CefVisitWebPluginInfo(CefRefPtr visitor) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (!visitor.get()) { + NOTREACHED() << "invalid parameter"; + return; + } + + if (CEF_CURRENTLY_ON_UIT()) { + content::PluginServiceImpl::GetInstance()->GetPlugins( + base::Bind(PluginsCallbackImpl, visitor)); + } else { + // Execute on the UI thread. + CEF_POST_TASK(CEF_UIT, base::Bind(CefVisitWebPluginInfo, visitor)); + } +} + +void CefRefreshWebPlugins() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + // No thread affinity. + content::PluginServiceImpl::GetInstance()->RefreshPlugins(); +} + +void CefAddWebPluginPath(const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + // No thread affinity. + content::PluginServiceImpl::GetInstance()->AddExtraPluginPath( + base::FilePath(path)); +} + +void CefAddWebPluginDirectory(const CefString& dir) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (dir.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + // No thread affinity. + content::PluginServiceImpl::GetInstance()->AddExtraPluginDir( + base::FilePath(dir)); +} + +void CefRemoveWebPluginPath(const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + // No thread affinity. + content::PluginServiceImpl::GetInstance()->RemoveExtraPluginPath( + base::FilePath(path)); +} + +void CefUnregisterInternalWebPlugin(const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + // No thread affinity. + content::PluginServiceImpl::GetInstance()->UnregisterInternalPlugin( + base::FilePath(path)); +} + +void CefForceWebPluginShutdown(const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + if (CEF_CURRENTLY_ON_IOT()) { + content::PluginServiceImpl::GetInstance()->ForcePluginShutdown( + base::FilePath(path)); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, base::Bind(CefForceWebPluginShutdown, path)); + } +} + +void CefRegisterWebPluginCrash(const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty()) { + NOTREACHED() << "invalid parameter"; + return; + } + + if (CEF_CURRENTLY_ON_IOT()) { + content::PluginServiceImpl::GetInstance()->RegisterPluginCrash( + base::FilePath(path)); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, base::Bind(CefRegisterWebPluginCrash, path)); + } +} + +void CefIsWebPluginUnstable( + const CefString& path, + CefRefPtr callback) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return; + } + + if (path.empty() || !callback.get()) { + NOTREACHED() << "invalid parameter"; + return; + } + + if (CEF_CURRENTLY_ON_IOT()) { + callback->IsUnstable(path, + content::PluginServiceImpl::GetInstance()->IsPluginUnstable( + base::FilePath(path))); + } else { + // Execute on the IO thread. + CEF_POST_TASK(CEF_IOT, base::Bind(CefIsWebPluginUnstable, path, callback)); + } +} diff --git a/libcef/browser/web_plugin_impl.h b/libcef/browser/web_plugin_impl.h new file mode 100644 index 000000000..20acd73dc --- /dev/null +++ b/libcef/browser/web_plugin_impl.h @@ -0,0 +1,27 @@ +// 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_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_ +#define CEF_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_ +#pragma once + +#include "include/cef_web_plugin.h" +#include "content/public/common/webplugininfo.h" + +class CefWebPluginInfoImpl : public CefWebPluginInfo { + public: + explicit CefWebPluginInfoImpl(const content::WebPluginInfo& plugin_info); + + virtual CefString GetName() OVERRIDE; + virtual CefString GetPath() OVERRIDE; + virtual CefString GetVersion() OVERRIDE; + virtual CefString GetDescription() OVERRIDE; + + private: + content::WebPluginInfo plugin_info_; + + IMPLEMENT_REFCOUNTING(CefWebPluginInfoImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_WEB_PLUGIN_IMPL_H_ diff --git a/libcef/browser/window_delegate_view.cc b/libcef/browser/window_delegate_view.cc new file mode 100644 index 000000000..e0be95d34 --- /dev/null +++ b/libcef/browser/window_delegate_view.cc @@ -0,0 +1,63 @@ +// Copyright 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 "libcef/browser/window_delegate_view.h" + +#include "content/public/browser/web_contents.h" +#include "ui/views/background.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" + +CefWindowDelegateView::CefWindowDelegateView(SkColor background_color) + : background_color_(background_color), + web_view_(NULL) { +} + +void CefWindowDelegateView::Init( + gfx::AcceleratedWidget parent_widget, + content::WebContents* web_contents, + const gfx::Rect& bounds) { + DCHECK(!web_view_); + web_view_ = new views::WebView(web_contents->GetBrowserContext()); + web_view_->SetWebContents(web_contents); + web_view_->SetPreferredSize(bounds.size()); + + views::Widget* widget = new views::Widget; + + // See CalculateWindowStylesFromInitParams in + // ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to + // Windows style flags. + views::Widget::InitParams params; + params.parent_widget = parent_widget; + params.bounds = bounds; + params.delegate = this; + // Set the WS_CHILD flag. + params.child = true; + // Set the WS_VISIBLE flag. + params.type = views::Widget::InitParams::TYPE_CONTROL; + // Don't set the WS_EX_COMPOSITED flag. + params.opacity = views::Widget::InitParams::OPAQUE_WINDOW; + + // Results in a call to InitContent(). + widget->Init(params); + + // |widget| should now be associated with |this|. + DCHECK_EQ(widget, GetWidget()); + // |widget| must be top-level for focus handling to work correctly. + DCHECK(widget->is_top_level()); +} + +void CefWindowDelegateView::InitContent() { + set_background(views::Background::CreateSolidBackground(background_color_)); + SetLayoutManager(new views::FillLayout()); + AddChildView(web_view_); +} + +void CefWindowDelegateView::ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) { + if (details.is_add && details.child == this) + InitContent(); +} + diff --git a/libcef/browser/window_delegate_view.h b/libcef/browser/window_delegate_view.h new file mode 100644 index 000000000..8380a77c3 --- /dev/null +++ b/libcef/browser/window_delegate_view.h @@ -0,0 +1,50 @@ +// Copyright 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_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ +#define CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ +#pragma once + +#include "ui/views/widget/widget_delegate.h" + +namespace content { +class WebContents; +} + +namespace views { +class WebView; +} + +// Manages the views-based root window that hosts the web contents. This object +// will be deleted automatically when the associated root window is destroyed. +class CefWindowDelegateView : public views::WidgetDelegateView { + public: + explicit CefWindowDelegateView(SkColor background_color); + + // Create the Widget and associated root window. + void Init(gfx::AcceleratedWidget parent_widget, + content::WebContents* web_contents, + const gfx::Rect& bounds); + + private: + // Initialize the Widget's content. + void InitContent(); + + // WidgetDelegateView methods: + virtual bool CanResize() const OVERRIDE { return true; } + virtual bool CanMaximize() const OVERRIDE { return true; } + virtual View* GetContentsView() OVERRIDE { return this; } + + // View methods: + virtual void ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) OVERRIDE; + + private: + SkColor background_color_; + views::WebView* web_view_; + + DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView); +}; + +#endif // CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_ diff --git a/libcef/browser/window_x11.cc b/libcef/browser/window_x11.cc new file mode 100644 index 000000000..ef62f7878 --- /dev/null +++ b/libcef/browser/window_x11.cc @@ -0,0 +1,374 @@ +// Copyright 2014 The Chromium Embedded Framework Authors. +// Portions copyright 2014 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 "libcef/browser/window_x11.h" +#include "libcef/browser/thread_util.h" + +#include +#include +#include + +#include "ui/base/x/x11_util.h" +#include "ui/events/platform/x11/x11_event_source.h" +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" +#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" + +namespace { + +const char kWMDeleteWindow[] = "WM_DELETE_WINDOW"; +const char kWMProtocols[] = "WM_PROTOCOLS"; +const char kNetWMPing[] = "_NET_WM_PING"; +const char kNetWMPid[] = "_NET_WM_PID"; +const char kXdndProxy[] = "XdndProxy"; + +const char* kAtomsToCache[] = { + kWMDeleteWindow, + kWMProtocols, + kNetWMPing, + kNetWMPid, + kXdndProxy, + NULL +}; + +::Window FindEventTarget(const base::NativeEvent& xev) { + ::Window target = xev->xany.window; + if (xev->type == GenericEvent) + target = static_cast(xev->xcookie.data)->event; + return target; +} + +::Window FindChild(::Display* display, ::Window window) { + ::Window root; + ::Window parent; + ::Window* children; + unsigned int nchildren; + if (XQueryTree(display, window, &root, &parent, &children, &nchildren)) { + DCHECK_EQ(1U, nchildren); + return children[0]; + } + return None; +} + +} // namespace + +CEF_EXPORT XDisplay* cef_get_xdisplay() { + if (!CEF_CURRENTLY_ON(CEF_UIT)) + return NULL; + return gfx::GetXDisplay(); +} + +CefWindowX11::CefWindowX11(CefRefPtr browser, + ::Window parent_xwindow, + const gfx::Rect& bounds) + : browser_(browser), + xdisplay_(gfx::GetXDisplay()), + parent_xwindow_(parent_xwindow), + xwindow_(0), + window_mapped_(false), + bounds_(bounds), + focus_pending_(false), + atom_cache_(xdisplay_, kAtomsToCache), + weak_ptr_factory_(this) { + if (parent_xwindow_ == None) + parent_xwindow_ = DefaultRootWindow(xdisplay_); + + XSetWindowAttributes swa; + memset(&swa, 0, sizeof(swa)); + swa.background_pixmap = None; + swa.override_redirect = false; + xwindow_ = XCreateWindow( + xdisplay_, parent_xwindow_, + bounds.x(), bounds.y(), bounds.width(), bounds.height(), + 0, // border width + CopyFromParent, // depth + InputOutput, + CopyFromParent, // visual + CWBackPixmap | CWOverrideRedirect, + &swa); + + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); + + long event_mask = FocusChangeMask | StructureNotifyMask | PropertyChangeMask; + XSelectInput(xdisplay_, xwindow_, event_mask); + XFlush(xdisplay_); + + // TODO(erg): We currently only request window deletion events. We also + // should listen for activation events and anything else that GTK+ listens + // for, and do something useful. + ::Atom protocols[2]; + protocols[0] = atom_cache_.GetAtom(kWMDeleteWindow); + protocols[1] = atom_cache_.GetAtom(kNetWMPing); + XSetWMProtocols(xdisplay_, xwindow_, protocols, 2); + + // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with + // the desktop environment. + XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL); + + // Likewise, the X server needs to know this window's pid so it knows which + // program to kill if the window hangs. + // XChangeProperty() expects "pid" to be long. + COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long); + long pid = getpid(); + XChangeProperty(xdisplay_, + xwindow_, + atom_cache_.GetAtom(kNetWMPid), + XA_CARDINAL, + 32, + PropModeReplace, + reinterpret_cast(&pid), 1); + + // Allow subclasses to create and cache additional atoms. + atom_cache_.allow_uncached_atoms(); +} + +CefWindowX11::~CefWindowX11() { + DCHECK(!xwindow_); + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); +} + +void CefWindowX11::Close() { + XEvent ev = {0}; + ev.xclient.type = ClientMessage; + ev.xclient.window = xwindow_; + ev.xclient.message_type = atom_cache_.GetAtom(kWMProtocols); + ev.xclient.format = 32; + ev.xclient.data.l[0] = atom_cache_.GetAtom(kWMDeleteWindow); + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(xdisplay_, xwindow_, False, NoEventMask, &ev); +} + +void CefWindowX11::Show() { + if (xwindow_ == None) + return; + + if (!window_mapped_) { + // Before we map the window, set size hints. Otherwise, some window managers + // will ignore toplevel XMoveWindow commands. + XSizeHints size_hints; + size_hints.flags = PPosition | PWinGravity; + size_hints.x = bounds_.x(); + size_hints.y = bounds_.y(); + // Set StaticGravity so that the window position is not affected by the + // frame width when running with window manager. + size_hints.win_gravity = StaticGravity; + XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); + + XMapWindow(xdisplay_, xwindow_); + + // We now block until our window is mapped. Some X11 APIs will crash and + // burn if passed |xwindow_| before the window is mapped, and XMapWindow is + // asynchronous. + if (ui::X11EventSource::GetInstance()) + ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_); + window_mapped_ = true; + } +} + +void CefWindowX11::Hide() { + if (xwindow_ == None) + return; + + if (window_mapped_) { + XWithdrawWindow(xdisplay_, xwindow_, 0); + window_mapped_ = false; + } +} + +void CefWindowX11::Focus() { + if (xwindow_ == None || !window_mapped_) + return; + + if (browser_) { + ::Window child = FindChild(xdisplay_, xwindow_); + if (child && ui::IsWindowVisible(child)) { + // Give focus to the child DesktopWindowTreeHostX11. + XSetInputFocus(xdisplay_, child, RevertToParent, CurrentTime); + } + } else { + XSetInputFocus(xdisplay_, xwindow_, RevertToParent, CurrentTime); + } +} + +void CefWindowX11::SetBounds(const gfx::Rect& bounds) { + if (xwindow_ == None) + return; + + bool origin_changed = bounds_.origin() != bounds.origin(); + bool size_changed = bounds_.size() != bounds.size(); + XWindowChanges changes = {0}; + unsigned value_mask = 0; + + if (size_changed) { + changes.width = bounds.width(); + changes.height = bounds.height(); + value_mask = CWHeight | CWWidth; + } + + if (origin_changed) { + changes.x = bounds.x(); + changes.y = bounds.y(); + value_mask |= CWX | CWY; + } + + if (value_mask) + XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); +} + +gfx::Rect CefWindowX11::GetBoundsInScreen() { + int x, y; + Window child; + if (XTranslateCoordinates(xdisplay_, xwindow_, DefaultRootWindow(xdisplay_), + 0, 0, &x, &y, &child)) { + return gfx::Rect(gfx::Point(x, y), bounds_.size()); + } + return gfx::Rect(); +} + +bool CefWindowX11::CanDispatchEvent(const ui::PlatformEvent& event) { + ::Window target = FindEventTarget(event); + return target == xwindow_; +} + +uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) { + XEvent* xev = event; + switch (xev->type) { + case ConfigureNotify: { + DCHECK_EQ(xwindow_, xev->xconfigure.event); + DCHECK_EQ(xwindow_, xev->xconfigure.window); + // It's possible that the X window may be resized by some other means + // than from within Aura (e.g. the X window manager can change the + // size). Make sure the root window size is maintained properly. + gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, + xev->xconfigure.width, xev->xconfigure.height); + bounds_ = bounds; + + if (browser_) { + ::Window child = FindChild(xdisplay_, xwindow_); + if (child) { + // Resize the child DesktopWindowTreeHostX11 to match this window. + XWindowChanges changes = {0}; + changes.width = bounds.width(); + changes.height = bounds.height(); + XConfigureWindow(xdisplay_, child, CWHeight | CWWidth, &changes); + + // Explicitly set the screen bounds so that WindowTreeHost::*Screen() + // methods return the correct results. + views::DesktopWindowTreeHostX11* window_tree_host = + views::DesktopWindowTreeHostX11::GetHostForXID(child); + if (window_tree_host) + window_tree_host->set_screen_bounds(bounds); + + // Find the top-most window containing the browser window. + views::X11TopmostWindowFinder finder; + ::Window topmost_window = finder.FindWindowAt(bounds.origin()); + DCHECK(topmost_window); + + // Configure the drag&drop proxy property for the top-most window so + // that all drag&drop-related messages will be sent to the child + // DesktopWindowTreeHostX11. The proxy property is referenced by + // DesktopDragDropClientAuraX11::FindWindowFor. + ::Window proxy_target = gfx::kNullAcceleratedWidget; + ui::GetXIDProperty(topmost_window, kXdndProxy, &proxy_target); + if (proxy_target != child) { + // Set the proxy target for the top-most window. + XChangeProperty(xdisplay_, + topmost_window, + atom_cache_.GetAtom(kXdndProxy), + XA_WINDOW, + 32, + PropModeReplace, + reinterpret_cast(&child), 1); + // Do the same for the proxy target per the spec. + XChangeProperty(xdisplay_, + child, + atom_cache_.GetAtom(kXdndProxy), + XA_WINDOW, + 32, + PropModeReplace, + reinterpret_cast(&child), 1); + } + } + } + break; + } + case ClientMessage: { + Atom message_type = xev->xclient.message_type; + if (message_type == atom_cache_.GetAtom(kWMProtocols)) { + Atom protocol = static_cast(xev->xclient.data.l[0]); + if (protocol == atom_cache_.GetAtom(kWMDeleteWindow)) { + // We have received a close message from the window manager. + if (browser_ && browser_->destruction_state() <= + CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) { + if (browser_->destruction_state() == + CefBrowserHostImpl::DESTRUCTION_STATE_NONE) { + // Request that the browser close. + browser_->CloseBrowser(false); + } + + // Cancel the close. + } else { + // Allow the close. + XDestroyWindow(xdisplay_, xwindow_); + } + } else if (protocol == atom_cache_.GetAtom(kNetWMPing)) { + XEvent reply_event = *xev; + reply_event.xclient.window = parent_xwindow_; + + XSendEvent(xdisplay_, + reply_event.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &reply_event); + XFlush(xdisplay_); + } + } + break; + } + case DestroyNotify: + xwindow_ = None; + + if (browser_) { + // Force the browser to be destroyed and release the reference added + // in PlatformCreateWindow(). + browser_->WindowDestroyed(); + } + + delete this; + break; + case FocusIn: + // This message is recieved first followed by a "_NET_ACTIVE_WINDOW" + // message sent to the root window. When X11DesktopHandler handles the + // "_NET_ACTIVE_WINDOW" message it will erroneously mark the WebView + // (hosted in a DesktopWindowTreeHostX11) as unfocused. Use a delayed + // task here to restore the WebView's focus state. + if (!focus_pending_) { + focus_pending_ = true; + CEF_POST_DELAYED_TASK(CEF_UIT, + base::Bind(&CefWindowX11::ContinueFocus, + weak_ptr_factory_.GetWeakPtr()), + 100); + } + break; + case FocusOut: + // Cancel the pending focus change if some other window has gained focus + // while waiting for the async task to run. Otherwise we can get stuck in + // a focus change loop. + if (focus_pending_) + focus_pending_ = false; + break; + } + + return ui::POST_DISPATCH_STOP_PROPAGATION; +} + +void CefWindowX11::ContinueFocus() { + if (!focus_pending_) + return; + if (browser_) + browser_->SetFocus(true); + focus_pending_ = false; +} diff --git a/libcef/browser/window_x11.h b/libcef/browser/window_x11.h new file mode 100644 index 000000000..7475e93fe --- /dev/null +++ b/libcef/browser/window_x11.h @@ -0,0 +1,72 @@ +// Copyright 2014 The Chromium Embedded Framework Authors. +// Portions copyright 2014 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_LIBCEF_BROWSER_WINDOW_X11_H_ +#define CEF_LIBCEF_BROWSER_WINDOW_X11_H_ +#pragma once + +#include + +#include "libcef/browser/browser_host_impl.h" + +#include "base/memory/weak_ptr.h" +#include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/x/x11_atom_cache.h" + +// Object wrapper for an X11 Window. +// Based on WindowTreeHostX11 and DesktopWindowTreeHostX11. +class CefWindowX11 : public ui::PlatformEventDispatcher { + public: + CefWindowX11(CefRefPtr browser, + ::Window parent_xwindow, + const gfx::Rect& bounds); + virtual ~CefWindowX11(); + + void Close(); + + void Show(); + void Hide(); + + void Focus(); + + void SetBounds(const gfx::Rect& bounds); + + gfx::Rect GetBoundsInScreen(); + + // ui::PlatformEventDispatcher methods: + virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE; + virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE; + + ::Window xwindow() const { return xwindow_; } + gfx::Rect bounds() const { return bounds_; } + + private: + void ContinueFocus(); + + CefRefPtr browser_; + + // The display and the native X window hosting the root window. + ::Display* xdisplay_; + ::Window parent_xwindow_; + ::Window xwindow_; + + // Is the window mapped to the screen? + bool window_mapped_; + + // The bounds of |xwindow_|. + gfx::Rect bounds_; + + bool focus_pending_; + + ui::X11AtomCache atom_cache_; + + // Must always be the last member. + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CefWindowX11); +}; + +#endif // CEF_LIBCEF_BROWSER_WINDOW_X11_H_ diff --git a/libcef/browser/xml_reader_impl.cc b/libcef/browser/xml_reader_impl.cc new file mode 100644 index 000000000..b66ea6326 --- /dev/null +++ b/libcef/browser/xml_reader_impl.cc @@ -0,0 +1,446 @@ +// 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 "libcef/browser/xml_reader_impl.h" +#include "include/cef_stream.h" +#include "base/logging.h" + +// Static functions + +// static +CefRefPtr CefXmlReader::Create(CefRefPtr stream, + EncodingType encodingType, + const CefString& URI) { + CefRefPtr impl(new CefXmlReaderImpl()); + if (!impl->Initialize(stream, encodingType, URI)) + return NULL; + return impl.get(); +} + + +// CefXmlReaderImpl + +namespace { + +/** + * xmlInputReadCallback: + * @context: an Input context + * @buffer: the buffer to store data read + * @len: the length of the buffer in bytes + * + * Callback used in the I/O Input API to read the resource + * + * Returns the number of bytes read or -1 in case of error + */ +int XMLCALL xml_read_callback(void * context, char * buffer, int len) { + CefRefPtr reader(static_cast(context)); + return reader->Read(buffer, 1, len); +} + +/** + * xmlTextReaderErrorFunc: + * @arg: the user argument + * @msg: the message + * @severity: the severity of the error + * @locator: a locator indicating where the error occured + * + * Signature of an error callback from a reader parser + */ +void XMLCALL xml_error_callback(void *arg, const char *msg, + xmlParserSeverities severity, + xmlTextReaderLocatorPtr locator) { + if (!msg) + return; + + std::string error_str(msg); + if (!error_str.empty() && error_str[error_str.length()-1] == '\n') + error_str.resize(error_str.length()-1); + + std::stringstream ss; + ss << error_str << ", line " << xmlTextReaderLocatorLineNumber(locator); + + LOG(INFO) << ss.str(); + + CefRefPtr impl(static_cast(arg)); + impl->AppendError(ss.str()); +} + +/** + * xmlStructuredErrorFunc: + * @userData: user provided data for the error callback + * @error: the error being raised. + * + * Signature of the function to use when there is an error and + * the module handles the new error reporting mechanism. + */ +void XMLCALL xml_structured_error_callback(void *userData, xmlErrorPtr error) { + if (!error->message) + return; + + std::string error_str(error->message); + if (!error_str.empty() && error_str[error_str.length()-1] == '\n') + error_str.resize(error_str.length()-1); + + std::stringstream ss; + ss << error_str << ", line " << error->line; + + LOG(INFO) << ss.str(); + + CefRefPtr impl(static_cast(userData)); + impl->AppendError(ss.str()); +} + +CefString xmlCharToString(const xmlChar* xmlStr, bool free) { + if (!xmlStr) + return CefString(); + + const char* str = reinterpret_cast(xmlStr); + CefString wstr = std::string(str); + + if (free) + xmlFree(const_cast(xmlStr)); + + return wstr; +} + +} // namespace + +CefXmlReaderImpl::CefXmlReaderImpl() + : supported_thread_id_(base::PlatformThread::CurrentId()), reader_(NULL) { +} + +CefXmlReaderImpl::~CefXmlReaderImpl() { + if (reader_ != NULL) { + if (!VerifyContext()) { + // Close() is supposed to be called directly. We'll try to free the reader + // now on the wrong thread but there's no guarantee this call won't crash. + xmlFreeTextReader(reader_); + } else { + Close(); + } + } +} + +bool CefXmlReaderImpl::Initialize(CefRefPtr stream, + EncodingType encodingType, + const CefString& URI) { + xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; + switch (encodingType) { + case XML_ENCODING_UTF8: + enc = XML_CHAR_ENCODING_UTF8; + break; + case XML_ENCODING_UTF16LE: + enc = XML_CHAR_ENCODING_UTF16LE; + break; + case XML_ENCODING_UTF16BE: + enc = XML_CHAR_ENCODING_UTF16BE; + break; + case XML_ENCODING_ASCII: + enc = XML_CHAR_ENCODING_ASCII; + break; + default: + break; + } + + // Create the input buffer. + xmlParserInputBufferPtr input_buffer = xmlAllocParserInputBuffer(enc); + if (!input_buffer) + return false; + + input_buffer->context = stream.get(); + input_buffer->readcallback = xml_read_callback; + + // Create the text reader. + std::string uriStr = URI; + reader_ = xmlNewTextReader(input_buffer, uriStr.c_str()); + if (!reader_) { + // Free the input buffer. + xmlFreeParserInputBuffer(input_buffer); + return false; + } + + // Keep a reference to the stream. + stream_ = stream; + + // Register the error callbacks. + xmlTextReaderSetErrorHandler(reader_, xml_error_callback, this); + xmlTextReaderSetStructuredErrorHandler(reader_, + xml_structured_error_callback, this); + + return true; +} + +bool CefXmlReaderImpl::MoveToNextNode() { + if (!VerifyContext()) + return false; + + return xmlTextReaderRead(reader_) == 1 ? true : false; +} + +bool CefXmlReaderImpl::Close() { + if (!VerifyContext()) + return false; + + // The input buffer will be freed automatically. + xmlFreeTextReader(reader_); + reader_ = NULL; + return true; +} + +bool CefXmlReaderImpl::HasError() { + if (!VerifyContext()) + return false; + + return !error_buf_.str().empty(); +} + +CefString CefXmlReaderImpl::GetError() { + if (!VerifyContext()) + return CefString(); + + return error_buf_.str(); +} + +CefXmlReader::NodeType CefXmlReaderImpl::GetType() { + if (!VerifyContext()) + return XML_NODE_UNSUPPORTED; + + switch (xmlTextReaderNodeType(reader_)) { + case XML_READER_TYPE_ELEMENT: + return XML_NODE_ELEMENT_START; + case XML_READER_TYPE_END_ELEMENT: + return XML_NODE_ELEMENT_END; + case XML_READER_TYPE_ATTRIBUTE: + return XML_NODE_ATTRIBUTE; + case XML_READER_TYPE_TEXT: + return XML_NODE_TEXT; + case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: + case XML_READER_TYPE_WHITESPACE: + return XML_NODE_WHITESPACE; + case XML_READER_TYPE_CDATA: + return XML_NODE_CDATA; + case XML_READER_TYPE_ENTITY_REFERENCE: + return XML_NODE_ENTITY_REFERENCE; + case XML_READER_TYPE_PROCESSING_INSTRUCTION: + return XML_NODE_PROCESSING_INSTRUCTION; + case XML_READER_TYPE_COMMENT: + return XML_NODE_COMMENT; + case XML_READER_TYPE_DOCUMENT_TYPE: + return XML_NODE_DOCUMENT_TYPE; + default: + break; + } + + return XML_NODE_UNSUPPORTED; +} + +int CefXmlReaderImpl::GetDepth() { + if (!VerifyContext()) + return -1; + + return xmlTextReaderDepth(reader_); +} + +CefString CefXmlReaderImpl::GetLocalName() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstLocalName(reader_), false); +} + +CefString CefXmlReaderImpl::GetPrefix() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstPrefix(reader_), false); +} + +CefString CefXmlReaderImpl::GetQualifiedName() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstName(reader_), false); +} + +CefString CefXmlReaderImpl::GetNamespaceURI() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstNamespaceUri(reader_), false); +} + +CefString CefXmlReaderImpl::GetBaseURI() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstBaseUri(reader_), false); +} + +CefString CefXmlReaderImpl::GetXmlLang() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderConstXmlLang(reader_), false); +} + +bool CefXmlReaderImpl::IsEmptyElement() { + if (!VerifyContext()) + return false; + + return xmlTextReaderIsEmptyElement(reader_) == 1 ? true : false; +} + +bool CefXmlReaderImpl::HasValue() { + if (!VerifyContext()) + return false; + + if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) { + // Provide special handling to return entity reference values. + return true; + } else { + return xmlTextReaderHasValue(reader_) == 1 ? true : false; + } +} + +CefString CefXmlReaderImpl::GetValue() { + if (!VerifyContext()) + return CefString(); + + if (xmlTextReaderNodeType(reader_) == XML_READER_TYPE_ENTITY_REFERENCE) { + // Provide special handling to return entity reference values. + xmlNodePtr node = xmlTextReaderCurrentNode(reader_); + if (node->content != NULL) + return xmlCharToString(node->content, false); + return CefString(); + } else { + return xmlCharToString(xmlTextReaderConstValue(reader_), false); + } +} + +bool CefXmlReaderImpl::HasAttributes() { + if (!VerifyContext()) + return false; + + return xmlTextReaderHasAttributes(reader_) == 1 ? true : false; +} + +size_t CefXmlReaderImpl::GetAttributeCount() { + if (!VerifyContext()) + return 0; + + return xmlTextReaderAttributeCount(reader_); +} + +CefString CefXmlReaderImpl::GetAttribute(int index) { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderGetAttributeNo(reader_, index), true); +} + +CefString CefXmlReaderImpl::GetAttribute(const CefString& qualifiedName) { + if (!VerifyContext()) + return CefString(); + + std::string qualifiedNameStr = qualifiedName; + return xmlCharToString(xmlTextReaderGetAttribute(reader_, + BAD_CAST qualifiedNameStr.c_str()), true); +} + +CefString CefXmlReaderImpl::GetAttribute(const CefString& localName, + const CefString& namespaceURI) { + if (!VerifyContext()) + return CefString(); + + std::string localNameStr = localName; + std::string namespaceURIStr = namespaceURI; + return xmlCharToString(xmlTextReaderGetAttributeNs(reader_, + BAD_CAST localNameStr.c_str(), BAD_CAST namespaceURIStr.c_str()), true); +} + +CefString CefXmlReaderImpl::GetInnerXml() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderReadInnerXml(reader_), true); +} + +CefString CefXmlReaderImpl::GetOuterXml() { + if (!VerifyContext()) + return CefString(); + + return xmlCharToString(xmlTextReaderReadOuterXml(reader_), true); +} + +int CefXmlReaderImpl::GetLineNumber() { + if (!VerifyContext()) + return -1; + + return xmlTextReaderGetParserLineNumber(reader_); +} + +bool CefXmlReaderImpl::MoveToAttribute(int index) { + if (!VerifyContext()) + return false; + + return xmlTextReaderMoveToAttributeNo(reader_, index) == 1 ? true : false; +} + +bool CefXmlReaderImpl::MoveToAttribute(const CefString& qualifiedName) { + if (!VerifyContext()) + return false; + + std::string qualifiedNameStr = qualifiedName; + return xmlTextReaderMoveToAttribute(reader_, + BAD_CAST qualifiedNameStr.c_str()) == 1 ? true : false; +} + +bool CefXmlReaderImpl::MoveToAttribute(const CefString& localName, + const CefString& namespaceURI) { + if (!VerifyContext()) + return false; + + std::string localNameStr = localName; + std::string namespaceURIStr = namespaceURI; + return xmlTextReaderMoveToAttributeNs(reader_, + BAD_CAST localNameStr.c_str(), BAD_CAST namespaceURIStr.c_str()) == 1 ? + true : false; +} + +bool CefXmlReaderImpl::MoveToFirstAttribute() { + if (!VerifyContext()) + return false; + + return xmlTextReaderMoveToFirstAttribute(reader_) == 1 ? true : false; +} + +bool CefXmlReaderImpl::MoveToNextAttribute() { + if (!VerifyContext()) + return false; + + return xmlTextReaderMoveToNextAttribute(reader_) == 1 ? true : false; +} + +bool CefXmlReaderImpl::MoveToCarryingElement() { + if (!VerifyContext()) + return false; + + return xmlTextReaderMoveToElement(reader_) == 1 ? true : false; +} + +void CefXmlReaderImpl::AppendError(const CefString& error_str) { + if (!error_buf_.str().empty()) + error_buf_ << L"\n"; + error_buf_ << error_str; +} + +bool CefXmlReaderImpl::VerifyContext() { + if (base::PlatformThread::CurrentId() != supported_thread_id_) { + // This object should only be accessed from the thread that created it. + NOTREACHED(); + return false; + } + + return (reader_ != NULL); +} diff --git a/libcef/browser/xml_reader_impl.h b/libcef/browser/xml_reader_impl.h new file mode 100644 index 000000000..5f8af1629 --- /dev/null +++ b/libcef/browser/xml_reader_impl.h @@ -0,0 +1,73 @@ +// 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_LIBCEF_BROWSER_XML_READER_IMPL_H_ +#define CEF_LIBCEF_BROWSER_XML_READER_IMPL_H_ +#pragma once + +#include +#include + +#include "include/cef_xml_reader.h" +#include "base/threading/platform_thread.h" + +// Implementation of CefXmlReader +class CefXmlReaderImpl : public CefXmlReader { + public: + CefXmlReaderImpl(); + ~CefXmlReaderImpl(); + + // Initialize the reader context. + bool Initialize(CefRefPtr stream, + EncodingType encodingType, const CefString& URI); + + virtual bool MoveToNextNode() OVERRIDE; + virtual bool Close() OVERRIDE; + virtual bool HasError() OVERRIDE; + virtual CefString GetError() OVERRIDE; + virtual NodeType GetType() OVERRIDE; + virtual int GetDepth() OVERRIDE; + virtual CefString GetLocalName() OVERRIDE; + virtual CefString GetPrefix() OVERRIDE; + virtual CefString GetQualifiedName() OVERRIDE; + virtual CefString GetNamespaceURI() OVERRIDE; + virtual CefString GetBaseURI() OVERRIDE; + virtual CefString GetXmlLang() OVERRIDE; + virtual bool IsEmptyElement() OVERRIDE; + virtual bool HasValue() OVERRIDE; + virtual CefString GetValue() OVERRIDE; + virtual bool HasAttributes() OVERRIDE; + virtual size_t GetAttributeCount() OVERRIDE; + virtual CefString GetAttribute(int index) OVERRIDE; + virtual CefString GetAttribute(const CefString& qualifiedName) OVERRIDE; + virtual CefString GetAttribute(const CefString& localName, + const CefString& namespaceURI) OVERRIDE; + virtual CefString GetInnerXml() OVERRIDE; + virtual CefString GetOuterXml() OVERRIDE; + virtual int GetLineNumber() OVERRIDE; + virtual bool MoveToAttribute(int index) OVERRIDE; + virtual bool MoveToAttribute(const CefString& qualifiedName) OVERRIDE; + virtual bool MoveToAttribute(const CefString& localName, + const CefString& namespaceURI) OVERRIDE; + virtual bool MoveToFirstAttribute() OVERRIDE; + virtual bool MoveToNextAttribute() OVERRIDE; + virtual bool MoveToCarryingElement() OVERRIDE; + + // Add another line to the error string. + void AppendError(const CefString& error_str); + + // Verify that the reader exists and is being accessed from the correct + // thread. + bool VerifyContext(); + + protected: + base::PlatformThreadId supported_thread_id_; + CefRefPtr stream_; + xmlTextReaderPtr reader_; + std::stringstream error_buf_; + + IMPLEMENT_REFCOUNTING(CefXmlReaderImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_XML_READER_IMPL_H_ diff --git a/libcef/browser/zip_reader_impl.cc b/libcef/browser/zip_reader_impl.cc new file mode 100644 index 000000000..dca92ae36 --- /dev/null +++ b/libcef/browser/zip_reader_impl.cc @@ -0,0 +1,280 @@ +// 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 "libcef/browser/zip_reader_impl.h" +#include +#include "include/cef_stream.h" +#include "base/logging.h" + +// Static functions + +// static +CefRefPtr CefZipReader::Create( + CefRefPtr stream) { + CefRefPtr impl(new CefZipReaderImpl()); + if (!impl->Initialize(stream)) + return NULL; + return impl.get(); +} + + +// CefZipReaderImpl + +namespace { + +voidpf ZCALLBACK zlib_open_callback OF((voidpf opaque, const void* filename, + int mode)) { + // The stream is already implicitly open so just return the pointer. + return opaque; +} + +uLong ZCALLBACK zlib_read_callback OF((voidpf opaque, voidpf stream, void* buf, + uLong size)) { + CefRefPtr reader(static_cast(opaque)); + return reader->Read(buf, 1, size); +} + +ZPOS64_T ZCALLBACK zlib_tell_callback OF((voidpf opaque, voidpf stream)) { + CefRefPtr reader(static_cast(opaque)); + return reader->Tell(); +} + +long ZCALLBACK zlib_seek_callback OF((voidpf opaque, // NOLINT(runtime/int) + voidpf stream, ZPOS64_T offset, + int origin)) { + CefRefPtr reader(static_cast(opaque)); + int whence; + switch (origin) { + case ZLIB_FILEFUNC_SEEK_CUR: + whence = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END: + whence = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET: + whence = SEEK_SET; + break; + default: + NOTREACHED(); + return -1; + } + return reader->Seek(offset, whence); +} + +int ZCALLBACK zlib_close_callback OF((voidpf opaque, voidpf stream)) { + CefRefPtr reader(static_cast(opaque)); + // Release the reference added by CefZipReaderImpl::Initialize(). + reader->Release(); + return 0; +} + +int ZCALLBACK zlib_error_callback OF((voidpf opaque, voidpf stream)) { + return 0; +} + +} // namespace + +CefZipReaderImpl::CefZipReaderImpl() + : supported_thread_id_(base::PlatformThread::CurrentId()), reader_(NULL), + has_fileopen_(false), + has_fileinfo_(false), + filesize_(0), + filemodified_(0) { +} + +CefZipReaderImpl::~CefZipReaderImpl() { + if (reader_ != NULL) { + if (!VerifyContext()) { + // Close() is supposed to be called directly. We'll try to free the reader + // now on the wrong thread but there's no guarantee this call won't crash. + if (has_fileopen_) + unzCloseCurrentFile(reader_); + unzClose(reader_); + } else { + Close(); + } + } +} + +bool CefZipReaderImpl::Initialize(CefRefPtr stream) { + zlib_filefunc64_def filefunc_def; + filefunc_def.zopen64_file = zlib_open_callback; + filefunc_def.zread_file = zlib_read_callback; + filefunc_def.zwrite_file = NULL; + filefunc_def.ztell64_file = zlib_tell_callback; + filefunc_def.zseek64_file = zlib_seek_callback; + filefunc_def.zclose_file = zlib_close_callback; + filefunc_def.zerror_file = zlib_error_callback; + filefunc_def.opaque = stream.get(); + + // Add a reference that will be released by zlib_close_callback(). + stream->AddRef(); + + reader_ = unzOpen2_64("", &filefunc_def); + return (reader_ != NULL); +} + +bool CefZipReaderImpl::MoveToFirstFile() { + if (!VerifyContext()) + return false; + + if (has_fileopen_) + CloseFile(); + + has_fileinfo_ = false; + + return (unzGoToFirstFile(reader_) == UNZ_OK); +} + +bool CefZipReaderImpl::MoveToNextFile() { + if (!VerifyContext()) + return false; + + if (has_fileopen_) + CloseFile(); + + has_fileinfo_ = false; + + return (unzGoToNextFile(reader_) == UNZ_OK); +} + +bool CefZipReaderImpl::MoveToFile(const CefString& fileName, + bool caseSensitive) { + if (!VerifyContext()) + return false; + + if (has_fileopen_) + CloseFile(); + + has_fileinfo_ = false; + + std::string fileNameStr = fileName; + return (unzLocateFile(reader_, fileNameStr.c_str(), + (caseSensitive ? 1 : 2)) == UNZ_OK); +} + +bool CefZipReaderImpl::Close() { + if (!VerifyContext()) + return false; + + if (has_fileopen_) + CloseFile(); + + int result = unzClose(reader_); + reader_ = NULL; + return (result == UNZ_OK); +} + +CefString CefZipReaderImpl::GetFileName() { + if (!VerifyContext() || !GetFileInfo()) + return CefString(); + + return filename_; +} + +int64 CefZipReaderImpl::GetFileSize() { + if (!VerifyContext() || !GetFileInfo()) + return -1; + + return filesize_; +} + +time_t CefZipReaderImpl::GetFileLastModified() { + if (!VerifyContext() || !GetFileInfo()) + return 0; + + return filemodified_; +} + +bool CefZipReaderImpl::OpenFile(const CefString& password) { + if (!VerifyContext()) + return false; + + if (has_fileopen_) + CloseFile(); + + bool ret; + + if (password.empty()) { + ret = (unzOpenCurrentFile(reader_) == UNZ_OK); + } else { + std::string passwordStr = password; + ret = (unzOpenCurrentFilePassword(reader_, passwordStr.c_str()) == UNZ_OK); + } + + if (ret) + has_fileopen_ = true; + return ret; +} + +bool CefZipReaderImpl::CloseFile() { + if (!VerifyContext() || !has_fileopen_) + return false; + + has_fileopen_ = false; + has_fileinfo_ = false; + + return (unzCloseCurrentFile(reader_) == UNZ_OK); +} + +int CefZipReaderImpl::ReadFile(void* buffer, size_t bufferSize) { + if (!VerifyContext() || !has_fileopen_) + return -1; + + return unzReadCurrentFile(reader_, buffer, bufferSize); +} + +int64 CefZipReaderImpl::Tell() { + if (!VerifyContext() || !has_fileopen_) + return -1; + + return unztell64(reader_); +} + +bool CefZipReaderImpl::Eof() { + if (!VerifyContext() || !has_fileopen_) + return true; + + return (unzeof(reader_) == 1 ? true : false); +} + +bool CefZipReaderImpl::GetFileInfo() { + if (has_fileinfo_) + return true; + + char file_name[512] = {0}; + unz_file_info file_info; + memset(&file_info, 0, sizeof(file_info)); + + if (unzGetCurrentFileInfo(reader_, &file_info, file_name, sizeof(file_name), + NULL, 0, NULL, 0) != UNZ_OK) { + return false; + } + + has_fileinfo_ = true; + filename_ = std::string(file_name); + filesize_ = file_info.uncompressed_size; + + struct tm time; + memset(&time, 0, sizeof(time)); + time.tm_sec = file_info.tmu_date.tm_sec; + time.tm_min = file_info.tmu_date.tm_min; + time.tm_hour = file_info.tmu_date.tm_hour; + time.tm_mday = file_info.tmu_date.tm_mday; + time.tm_mon = file_info.tmu_date.tm_mon; + time.tm_year = file_info.tmu_date.tm_year; + filemodified_ = mktime(&time); + + return true; +} + +bool CefZipReaderImpl::VerifyContext() { + if (base::PlatformThread::CurrentId() != supported_thread_id_) { + // This object should only be accessed from the thread that created it. + NOTREACHED(); + return false; + } + + return (reader_ != NULL); +} diff --git a/libcef/browser/zip_reader_impl.h b/libcef/browser/zip_reader_impl.h new file mode 100644 index 000000000..d53d157a0 --- /dev/null +++ b/libcef/browser/zip_reader_impl.h @@ -0,0 +1,55 @@ +// 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_LIBCEF_BROWSER_ZIP_READER_IMPL_H_ +#define CEF_LIBCEF_BROWSER_ZIP_READER_IMPL_H_ +#pragma once + +#include + +#include "include/cef_zip_reader.h" +#include "base/threading/platform_thread.h" +#include "third_party/zlib/contrib/minizip/unzip.h" + +// Implementation of CefZipReader +class CefZipReaderImpl : public CefZipReader { + public: + CefZipReaderImpl(); + ~CefZipReaderImpl(); + + // Initialize the reader context. + bool Initialize(CefRefPtr stream); + + virtual bool MoveToFirstFile(); + virtual bool MoveToNextFile(); + virtual bool MoveToFile(const CefString& fileName, bool caseSensitive); + virtual bool Close(); + virtual CefString GetFileName(); + virtual int64 GetFileSize(); + virtual time_t GetFileLastModified(); + virtual bool OpenFile(const CefString& password); + virtual bool CloseFile(); + virtual int ReadFile(void* buffer, size_t bufferSize); + virtual int64 Tell(); + virtual bool Eof(); + + bool GetFileInfo(); + + // Verify that the reader exists and is being accessed from the correct + // thread. + bool VerifyContext(); + + protected: + base::PlatformThreadId supported_thread_id_; + unzFile reader_; + bool has_fileopen_; + bool has_fileinfo_; + CefString filename_; + int64 filesize_; + time_t filemodified_; + + IMPLEMENT_REFCOUNTING(CefZipReaderImpl); +}; + +#endif // CEF_LIBCEF_BROWSER_ZIP_READER_IMPL_H_ diff --git a/libcef/common/base_impl.cc b/libcef/common/base_impl.cc new file mode 100644 index 000000000..483225dde --- /dev/null +++ b/libcef/common/base_impl.cc @@ -0,0 +1,345 @@ +// 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 "include/internal/cef_trace_event_internal.h" +#include "include/internal/cef_logging_internal.h" +#include "include/internal/cef_thread_internal.h" + +#include "base/debug/trace_event.h" +#include "base/logging.h" +#include "base/threading/platform_thread.h" + +// The contents of this file are a compilation unit that is not called by other +// functions in the the library. Consiquently MSVS will exclude it during the +// linker stage if we don't call a stub function. +#if defined(COMPILER_MSVC) +#pragma optimize("", off) +#endif + +void base_impl_stub() {} + +#if defined(COMPILER_MSVC) +#pragma optimize("", on) +#endif + + +CEF_EXPORT void cef_trace_event_instant(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_COPY_INSTANT0(category, name, TRACE_EVENT_SCOPE_THREAD); + } else if (arg2_name == NULL) { + TRACE_EVENT_COPY_INSTANT1(category, name, TRACE_EVENT_SCOPE_THREAD, + arg1_name, arg1_val); + } else { + TRACE_EVENT_COPY_INSTANT2(category, name, TRACE_EVENT_SCOPE_THREAD, + arg1_name, arg1_val, arg2_name, arg2_val); + } + } else { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_INSTANT0(category, name, TRACE_EVENT_SCOPE_THREAD); + } else if (arg2_name == NULL) { + TRACE_EVENT_INSTANT1(category, name, TRACE_EVENT_SCOPE_THREAD, + arg1_name, arg1_val); + } else { + TRACE_EVENT_INSTANT2(category, name, TRACE_EVENT_SCOPE_THREAD, + arg1_name, arg1_val, arg2_name, arg2_val); + } + } +} + +CEF_EXPORT void cef_trace_event_begin(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_COPY_BEGIN0(category, name); + } else if (arg2_name == NULL) { + TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val); + } else { + TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } else { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_BEGIN0(category, name); + } else if (arg2_name == NULL) { + TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val); + } else { + TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } +} + +CEF_EXPORT void cef_trace_event_end(const char* category, + const char* name, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_COPY_END0(category, name); + } else if (arg2_name == NULL) { + TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val); + } else { + TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } else { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_END0(category, name); + } else if (arg2_name == NULL) { + TRACE_EVENT_END1(category, name, arg1_name, arg1_val); + } else { + TRACE_EVENT_END2(category, name, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } +} + +CEF_EXPORT void cef_trace_counter(const char* category, + const char* name, + const char* value1_name, + uint64 value1_val, + const char* value2_name, + uint64 value2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (value1_name == NULL && value2_name == NULL) { + TRACE_COPY_COUNTER1(category, name, value1_val); + } else { + TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, + value2_name, value2_val); + } + } else { + if (value1_name == NULL && value2_name == NULL) { + TRACE_COUNTER1(category, name, value1_val); + } else { + TRACE_COUNTER2(category, name, value1_name, value1_val, + value2_name, value2_val); + } + } +} + +CEF_EXPORT void cef_trace_counter_id(const char* category, + const char* name, + uint64 id, + const char* value1_name, + uint64 value1_val, + const char* value2_name, + uint64 value2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (value1_name == NULL && value2_name == NULL) { + TRACE_COPY_COUNTER_ID1(category, name, id, value1_val); + } else { + TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, + value1_val, value2_name, value2_val); + } + } else { + if (value1_name == NULL && value2_name == NULL) { + TRACE_COUNTER_ID1(category, name, id, value1_val); + } else { + TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, + value2_name, value2_val); + } + } +} + +CEF_EXPORT void cef_trace_event_async_begin(const char* category, + const char* name, + uint64 id, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id); + } else if (arg2_name == NULL) { + TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val); + } else { + TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } else { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_ASYNC_BEGIN0(category, name, id); + } else if (arg2_name == NULL) { + TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val); + } else { + TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, + arg2_name, arg2_val); + } + } +} + +CEF_EXPORT void cef_trace_event_async_step_into(const char* category, + const char* name, + uint64 id, + uint64 step, + const char* arg1_name, + uint64 arg1_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL) { + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step); + } else { + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, + arg1_name, arg1_val); + } + } else { + if (arg1_name == NULL) { + TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step); + } else { + TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, + arg1_name, arg1_val); + } + } +} + +CEF_EXPORT void cef_trace_event_async_step_past(const char* category, + const char* name, + uint64 id, + uint64 step, + const char* arg1_name, + uint64 arg1_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL) { + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step); + } else { + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, + arg1_name, arg1_val); + } + } else { + if (arg1_name == NULL) { + TRACE_EVENT_ASYNC_STEP_PAST0(category, name, id, step); + } else { + TRACE_EVENT_ASYNC_STEP_PAST1(category, name, id, step, + arg1_name, arg1_val); + } + } +} + +CEF_EXPORT void cef_trace_event_async_end(const char* category, + const char* name, + uint64 id, + const char* arg1_name, + uint64 arg1_val, + const char* arg2_name, + uint64 arg2_val, + int copy) { + DCHECK(category); + DCHECK(name); + if (!category || !name) + return; + + if (copy) { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_COPY_ASYNC_END0(category, name, id); + } else if (arg2_name == NULL) { + TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, + arg1_val); + } else { + TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, + arg1_val, arg2_name, arg2_val); + } + } else { + if (arg1_name == NULL && arg2_name == NULL) { + TRACE_EVENT_ASYNC_END0(category, name, id); + } else if (arg2_name == NULL) { + TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, + arg1_val); + } else { + TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, + arg1_val, arg2_name, arg2_val); + } + } +} + +CEF_EXPORT int cef_get_min_log_level() { + return logging::GetMinLogLevel(); +} + +CEF_EXPORT int cef_get_vlog_level(const char* file_start, size_t N) { + return logging::GetVlogLevelHelper(file_start, N); +} + +CEF_EXPORT void cef_log(const char* file, + int line, + int severity, + const char* message) { + logging::LogMessage(file, line, severity).stream() << message; +} + +CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id() { + return base::PlatformThread::CurrentId(); +} + +CEF_EXPORT cef_platform_thread_handle_t + cef_get_current_platform_thread_handle() { +#if defined(OS_WIN) + return base::PlatformThread::CurrentId(); +#else + return base::PlatformThread::CurrentHandle().platform_handle(); +#endif +} diff --git a/libcef/common/breakpad_client.cc b/libcef/common/breakpad_client.cc new file mode 100644 index 000000000..64744ea88 --- /dev/null +++ b/libcef/common/breakpad_client.cc @@ -0,0 +1,58 @@ +// Copyright 2013 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 "libcef/common/breakpad_client.h" +#include "libcef/common/cef_switches.h" +#include "include/cef_version.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/files/file_path.h" +#include "base/strings/string16.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" + +CefBreakpadClient::CefBreakpadClient() {} +CefBreakpadClient::~CefBreakpadClient() {} + +#if defined(OS_WIN) +void CefBreakpadClient::GetProductNameAndVersion( + const base::FilePath& exe_path, + base::string16* product_name, + base::string16* version, + base::string16* special_build, + base::string16* channel_name) { + *product_name = base::ASCIIToUTF16("cef"); + *version = base::UTF8ToUTF16(base::StringPrintf( + "%d.%d.%d", CEF_VERSION_MAJOR, CHROME_VERSION_BUILD, CEF_REVISION)); + *special_build = base::string16(); + *channel_name = base::string16(); +} +#endif + +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) +void CefBreakpadClient::GetProductNameAndVersion(std::string* product_name, + std::string* version) { + *product_name = "cef"; + *version = base::StringPrintf( + "%d.%d.%d", CEF_VERSION_MAJOR, CHROME_VERSION_BUILD, CEF_REVISION); +} + +base::FilePath CefBreakpadClient::GetReporterLogFilename() { + return base::FilePath(FILE_PATH_LITERAL("uploads.log")); +} +#endif + +bool CefBreakpadClient::GetCrashDumpLocation(base::FilePath* crash_dir) { +#if !defined(OS_WIN) + if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) + return false; + *crash_dir = CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kCrashDumpsDir); + return true; +#else + NOTREACHED(); + return false; +#endif +} diff --git a/libcef/common/breakpad_client.h b/libcef/common/breakpad_client.h new file mode 100644 index 000000000..964a9ecaa --- /dev/null +++ b/libcef/common/breakpad_client.h @@ -0,0 +1,43 @@ +// Copyright 2013 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_LIBCEF_COMMON_BREAKPAD_CLIENT_H_ +#define CEF_LIBCEF_COMMON_BREAKPAD_CLIENT_H_ + +#include "base/compiler_specific.h" +#include "components/breakpad/app/breakpad_client.h" + +class CefBreakpadClient : public breakpad::BreakpadClient { + public: + CefBreakpadClient(); + virtual ~CefBreakpadClient(); + +#if defined(OS_WIN) + // Returns a textual description of the product type and version to include + // in the crash report. + virtual void GetProductNameAndVersion(const base::FilePath& exe_path, + base::string16* product_name, + base::string16* version, + base::string16* special_build, + base::string16* channel_name) OVERRIDE; +#endif + +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) + // Returns a textual description of the product type and version to include + // in the crash report. + virtual void GetProductNameAndVersion(std::string* product_name, + std::string* version) OVERRIDE; + + virtual base::FilePath GetReporterLogFilename() OVERRIDE; +#endif + + // The location where minidump files should be written. Returns true if + // |crash_dir| was set. + virtual bool GetCrashDumpLocation(base::FilePath* crash_dir) OVERRIDE; + +private: + DISALLOW_COPY_AND_ASSIGN(CefBreakpadClient); +}; + +#endif // CEF_LIBCEF_COMMON_BREAKPAD_CLIENT_H_ diff --git a/libcef/common/cef_message_generator.cc b/libcef/common/cef_message_generator.cc new file mode 100644 index 000000000..6e16dc1d4 --- /dev/null +++ b/libcef/common/cef_message_generator.cc @@ -0,0 +1,33 @@ +// 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. + +// Get basic type definitions. +#define IPC_MESSAGE_IMPL +#include "libcef/common/cef_message_generator.h" + +// Generate constructors. +#include "ipc/struct_constructor_macros.h" +#include "libcef/common/cef_message_generator.h" + +// Generate destructors. +#include "ipc/struct_destructor_macros.h" +#include "libcef/common/cef_message_generator.h" + +// Generate param traits write methods. +#include "ipc/param_traits_write_macros.h" +namespace IPC { +#include "libcef/common/cef_message_generator.h" +} // namespace IPC + +// Generate param traits read methods. +#include "ipc/param_traits_read_macros.h" +namespace IPC { +#include "libcef/common/cef_message_generator.h" +} // namespace IPC + +// Generate param traits log methods. +#include "ipc/param_traits_log_macros.h" +namespace IPC { +#include "libcef/common/cef_message_generator.h" +} // namespace IPC diff --git a/libcef/common/cef_message_generator.h b/libcef/common/cef_message_generator.h new file mode 100644 index 000000000..124361160 --- /dev/null +++ b/libcef/common/cef_message_generator.h @@ -0,0 +1,7 @@ +// 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. + +// Multiply-included file, hence no include guard. + +#include "libcef/common/cef_messages.h" diff --git a/libcef/common/cef_messages.cc b/libcef/common/cef_messages.cc new file mode 100644 index 000000000..9727d843e --- /dev/null +++ b/libcef/common/cef_messages.cc @@ -0,0 +1,116 @@ +// 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 "libcef/common/cef_messages.h" + +namespace IPC { + +// Extracted from chrome/common/automation_messages.cc. + +// Only the net::UploadData ParamTraits<> definition needs this definition, so +// keep this in the implementation file so we can forward declare UploadData in +// the header. +template <> +struct ParamTraits { + typedef net::UploadElement param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, static_cast(p.type())); + switch (p.type()) { + case net::UploadElement::TYPE_BYTES: { + m->WriteData(p.bytes(), static_cast(p.bytes_length())); + break; + } + default: { + DCHECK(p.type() == net::UploadElement::TYPE_FILE); + WriteParam(m, p.file_path()); + WriteParam(m, p.file_range_offset()); + WriteParam(m, p.file_range_length()); + WriteParam(m, p.expected_file_modification_time()); + break; + } + } + } + static bool Read(const Message* m, PickleIterator* iter, param_type* r) { + int type; + if (!ReadParam(m, iter, &type)) + return false; + switch (type) { + case net::UploadElement::TYPE_BYTES: { + const char* data; + int len; + if (!m->ReadData(iter, &data, &len)) + return false; + r->SetToBytes(data, len); + break; + } + default: { + DCHECK(type == net::UploadElement::TYPE_FILE); + base::FilePath file_path; + uint64 offset, length; + base::Time expected_modification_time; + if (!ReadParam(m, iter, &file_path)) + return false; + if (!ReadParam(m, iter, &offset)) + return false; + if (!ReadParam(m, iter, &length)) + return false; + if (!ReadParam(m, iter, &expected_modification_time)) + return false; + r->SetToFilePathRange(file_path, offset, length, + expected_modification_time); + break; + } + } + return true; + } + static void Log(const param_type& p, std::string* l) { + l->append(""); + } +}; + +void ParamTraits >::Write(Message* m, + const param_type& p) { + WriteParam(m, p.get() != NULL); + if (p) { + WriteParam(m, p->elements()); + WriteParam(m, p->identifier()); + WriteParam(m, p->is_chunked()); + WriteParam(m, p->last_chunk_appended()); + } +} + +bool ParamTraits >::Read(const Message* m, + PickleIterator* iter, + param_type* r) { + bool has_object; + if (!ReadParam(m, iter, &has_object)) + return false; + if (!has_object) + return true; + ScopedVector elements; + if (!ReadParam(m, iter, &elements)) + return false; + int64 identifier; + if (!ReadParam(m, iter, &identifier)) + return false; + bool is_chunked = false; + if (!ReadParam(m, iter, &is_chunked)) + return false; + bool last_chunk_appended = false; + if (!ReadParam(m, iter, &last_chunk_appended)) + return false; + *r = new net::UploadData; + (*r)->swap_elements(&elements); + (*r)->set_identifier(identifier); + (*r)->set_is_chunked(is_chunked); + (*r)->set_last_chunk_appended(last_chunk_appended); + return true; +} + +void ParamTraits >::Log(const param_type& p, + std::string* l) { + l->append(""); +} + +} // namespace IPC diff --git a/libcef/common/cef_messages.h b/libcef/common/cef_messages.h new file mode 100644 index 000000000..bc354516d --- /dev/null +++ b/libcef/common/cef_messages.h @@ -0,0 +1,251 @@ +// Copyright (c) 2012 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. + +// IPC messages for CEF. +// Multiply-included message file, hence no include guard. + +#include "libcef/common/upload_data.h" + +#include "base/memory/shared_memory.h" +#include "base/values.h" +#include "content/public/common/common_param_traits.h" +#include "content/public/common/referrer.h" +#include "ipc/ipc_message_macros.h" + +// TODO(cef): Re-using the message start for extensions may be problematic in +// the future. It would be better if ipc_message_utils.h contained a value +// reserved for consumers of the content API. +// See: http://crbug.com/110911 +#define IPC_MESSAGE_START ExtensionMsgStart + + +// Common types. + +// Parameters structure for a request. +IPC_STRUCT_BEGIN(Cef_Request_Params) + // Unique request id to match requests and responses. + IPC_STRUCT_MEMBER(int, request_id) + + // Unique id of the target frame. -1 if unknown / invalid. + IPC_STRUCT_MEMBER(int64, frame_id) + + // True if the request is user-initiated instead of internal. + IPC_STRUCT_MEMBER(bool, user_initiated) + + // True if a response is expected. + IPC_STRUCT_MEMBER(bool, expect_response) + + // Message name. + IPC_STRUCT_MEMBER(std::string, name) + + // List of message arguments. + IPC_STRUCT_MEMBER(base::ListValue, arguments) +IPC_STRUCT_END() + +// Parameters structure for a response. +IPC_STRUCT_BEGIN(Cef_Response_Params) + // Unique request id to match requests and responses. + IPC_STRUCT_MEMBER(int, request_id) + + // True if a response ack is expected. + IPC_STRUCT_MEMBER(bool, expect_response_ack) + + // True on success. + IPC_STRUCT_MEMBER(bool, success) + + // Response or error string depending on the value of |success|. + IPC_STRUCT_MEMBER(std::string, response) +IPC_STRUCT_END() + +// Parameters structure for a cross-origin white list entry. +IPC_STRUCT_BEGIN(Cef_CrossOriginWhiteListEntry_Params) + IPC_STRUCT_MEMBER(std::string, source_origin) + IPC_STRUCT_MEMBER(std::string, target_protocol) + IPC_STRUCT_MEMBER(std::string, target_domain) + IPC_STRUCT_MEMBER(bool, allow_target_subdomains) +IPC_STRUCT_END() + + +// Messages sent from the browser to the renderer. + +// Parameters for a resource request. +IPC_STRUCT_BEGIN(CefMsg_LoadRequest_Params) + // The request method: GET, POST, etc. + IPC_STRUCT_MEMBER(std::string, method) + + // The requested URL. + IPC_STRUCT_MEMBER(GURL, url) + + // The URL to send in the "Referer" header field. Can be empty if there is + // no referrer. + IPC_STRUCT_MEMBER(GURL, referrer) + // One of the blink::WebReferrerPolicy values. + IPC_STRUCT_MEMBER(int, referrer_policy) + + // Identifies the frame within the RenderView that sent the request. + // -1 if unknown / invalid. + IPC_STRUCT_MEMBER(int64, frame_id) + + // Usually the URL of the document in the top-level window, which may be + // checked by the third-party cookie blocking policy. Leaving it empty may + // lead to undesired cookie blocking. Third-party cookie blocking can be + // bypassed by setting first_party_for_cookies = url, but this should ideally + // only be done if there really is no way to determine the correct value. + IPC_STRUCT_MEMBER(GURL, first_party_for_cookies) + + // Additional HTTP request headers. + IPC_STRUCT_MEMBER(std::string, headers) + + // net::URLRequest load flags (0 by default). + IPC_STRUCT_MEMBER(int, load_flags) + + // Optional upload data (may be null). + IPC_STRUCT_MEMBER(scoped_refptr, upload_data) +IPC_STRUCT_END() + +// Tell the renderer to load a request. +IPC_MESSAGE_ROUTED1(CefMsg_LoadRequest, + CefMsg_LoadRequest_Params) + +// Sent when the browser has a request for the renderer. The renderer may +// respond with a CefHostMsg_Response. +IPC_MESSAGE_ROUTED1(CefMsg_Request, + Cef_Request_Params) + +// Optional message sent in response to a CefHostMsg_Request. +IPC_MESSAGE_ROUTED1(CefMsg_Response, + Cef_Response_Params) + +// Optional Ack message sent to the browser to notify that a CefHostMsg_Response +// has been processed. +IPC_MESSAGE_ROUTED1(CefMsg_ResponseAck, + int /* request_id */) + +// Sent to child processes to add or remove a cross-origin whitelist entry. +IPC_MESSAGE_CONTROL2(CefProcessMsg_ModifyCrossOriginWhitelistEntry, + bool /* add */, + Cef_CrossOriginWhiteListEntry_Params /* params */) + +// Sent to child processes to clear the cross-origin whitelist. +IPC_MESSAGE_CONTROL0(CefProcessMsg_ClearCrossOriginWhitelist) + + +// Messages sent from the renderer to the browser. + +// Parameters for a newly created render thread. +IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewRenderThreadInfo_Params) + IPC_STRUCT_MEMBER(std::vector, + cross_origin_whitelist_entries) + + IPC_STRUCT_MEMBER(base::ListValue, extra_info) +IPC_STRUCT_END() + +// Retrieve information about a newly created render thread. +IPC_SYNC_MESSAGE_CONTROL0_1( + CefProcessHostMsg_GetNewRenderThreadInfo, + CefProcessHostMsg_GetNewRenderThreadInfo_Params /* params*/) + +// Parameters for a newly created browser window. +IPC_STRUCT_BEGIN(CefProcessHostMsg_GetNewBrowserInfo_Params) + IPC_STRUCT_MEMBER(int, browser_id) + IPC_STRUCT_MEMBER(bool, is_popup) + IPC_STRUCT_MEMBER(bool, is_windowless) +IPC_STRUCT_END() + +// Retrieve information about a newly created browser. +IPC_SYNC_MESSAGE_CONTROL2_1( + CefProcessHostMsg_GetNewBrowserInfo, + int /* render_view_routing_id */, + int /* render_frame_routing_id */, + CefProcessHostMsg_GetNewBrowserInfo_Params /* params*/) + +// Sent when a frame is identified for the first time. +IPC_MESSAGE_ROUTED3(CefHostMsg_FrameIdentified, + int64 /* frame_id */, + int64 /* parent_frame_id */, + base::string16 /* frame_name */) + +// Sent when a frame has been detached. +IPC_MESSAGE_ROUTED1(CefHostMsg_FrameDetached, + int64 /* frame_id */) + +// Sent when a new frame has been given focus. +IPC_MESSAGE_ROUTED1(CefHostMsg_FrameFocusChange, + int64 /* frame_id */) + +// Sent when a frame has finished loading. Based on ViewHostMsg_DidFinishLoad. +IPC_MESSAGE_ROUTED4(CefHostMsg_DidFinishLoad, + int64 /* frame_id */, + GURL /* validated_url */, + bool /* is_main_frame */, + int /* http_status_code */) + +// Sent when a new URL is about to be loaded in the main frame. Used for the +// cookie manager. +IPC_MESSAGE_ROUTED1(CefHostMsg_LoadingURLChange, + GURL /* loading_url */) + +// Sent when the renderer has a request for the browser. The browser may respond +// with a CefMsg_Response. +IPC_MESSAGE_ROUTED1(CefHostMsg_Request, + Cef_Request_Params) + +// Optional message sent in response to a CefMsg_Request. +IPC_MESSAGE_ROUTED1(CefHostMsg_Response, + Cef_Response_Params) + +// Optional Ack message sent to the browser to notify that a CefMsg_Response +// has been processed. +IPC_MESSAGE_ROUTED1(CefHostMsg_ResponseAck, + int /* request_id */) + + +// Pepper PDF plugin messages excerpted from chrome/common/render_messages.h. +// Including all of render_messages.h would bring in a number of chrome +// dependencies that are better off avoided. + +// The currently displayed PDF has an unsupported feature. +IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_PDFHasUnsupportedFeature) + +// Brings up SaveAs... dialog to save specified URL. +IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_PDFSaveURLAs, + GURL /* url */, + content::Referrer /* referrer */) + +// Updates the content restrictions, i.e. to disable print/copy. +IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_PDFUpdateContentRestrictions, + int /* restrictions */) + +// Brings up a Password... dialog for protected documents. +IPC_SYNC_MESSAGE_ROUTED1_1(ChromeViewHostMsg_PDFModalPromptForPassword, + std::string /* prompt */, + std::string /* actual_value */) + + +// Singly-included section for struct and custom IPC traits. +#ifndef CEF_LIBCEF_COMMON_CEF_MESSAGES_H_ +#define CEF_LIBCEF_COMMON_CEF_MESSAGES_H_ + +namespace IPC { + +// Extracted from chrome/common/automation_messages.h. +template <> +struct ParamTraits > { + typedef scoped_refptr param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, PickleIterator* iter, param_type* r); + static void Log(const param_type& p, std::string* l); +}; + +} // namespace IPC + +#endif // CEF_LIBCEF_COMMON_CEF_MESSAGES_H_ + +#include "chrome/common/prerender_messages.h" +#include "chrome/common/print_messages.h" + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) +#include "chrome/common/chrome_utility_printing_messages.h" +#endif diff --git a/libcef/common/cef_switches.cc b/libcef/common/cef_switches.cc new file mode 100644 index 000000000..6084bc1bb --- /dev/null +++ b/libcef/common/cef_switches.cc @@ -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 "libcef/common/cef_switches.h" + +namespace switches { + +// Log file path. +const char kLogFile[] = "log-file"; + +// Severity of messages to log. +const char kLogSeverity[] = "log-severity"; +const char kLogSeverity_Verbose[] = "verbose"; +const char kLogSeverity_Info[] = "info"; +const char kLogSeverity_Warning[] = "warning"; +const char kLogSeverity_Error[] = "error"; +const char kLogSeverity_Disable[] = "disable"; + +// Path to resources directory. +const char kResourcesDirPath[] = "resources-dir-path"; + +// Path to locales directory. +const char kLocalesDirPath[] = "locales-dir-path"; + +// Path to locales directory. +const char kDisablePackLoading[] = "disable-pack-loading"; + +// Stack size for uncaught exceptions. +const char kUncaughtExceptionStackSize[] = "uncaught-exception-stack-size"; + +// Context safety implementation type. +const char kContextSafetyImplementation[] = "context-safety-implementation"; + +// Default encoding. +const char kDefaultEncoding[] = "default-encoding"; + +// Disable opening of windows via JavaScript. +const char kDisableJavascriptOpenWindows[] = + "disable-javascript-open-windows"; + +// Disable closing of windows via JavaScript. +const char kDisableJavascriptCloseWindows[] = + "disable-javascript-close-windows"; + +// Disable clipboard access via JavaScript. +const char kDisableJavascriptAccessClipboard[] = + "disable-javascript-access-clipboard"; + +// Disable DOM paste via JavaScript execCommand("paste"). +const char kDisableJavascriptDomPaste[] = "disable-javascript-dom-paste"; + +// Enable caret browsing. +const char kEnableCaretBrowsing[] = "enable-caret-browsing"; + +// Allow universal access from file URLs. +const char kAllowUniversalAccessFromFileUrls[] = + "allow-universal-access-from-files"; + +// Disable loading of images from the network. A cached image will still be +// rendered if requested. +const char kDisableImageLoading[] = "disable-image-loading"; + +// Shrink stand-alone images to fit. +const char kImageShrinkStandaloneToFit[] = "image-shrink-standalone-to-fit"; + +// Disable resizing of text areas. +const char kDisableTextAreaResize[] = "disable-text-area-resize"; + +// Disable using the tab key to advance focus to links. +const char kDisableTabToLinks[] = "disable-tab-to-links"; + +// Persist session cookies. +const char kPersistSessionCookies[] = "persist-session-cookies"; + +// Enable media (WebRTC audio/video) streaming. +const char kEnableMediaStream[] = "enable-media-stream"; + +// Enable speech input (x-webkit-speech). +const char kEnableSpeechInput[] = "enable-speech-input"; + +// Enable the speech input profanity filter. +const char kEnableProfanityFilter[] = "enable-profanity-filter"; + +// The directory breakpad should store minidumps in. +const char kCrashDumpsDir[] = "crash-dumps-dir"; + +} // namespace switches diff --git a/libcef/common/cef_switches.h b/libcef/common/cef_switches.h new file mode 100644 index 000000000..f3bdf9bfd --- /dev/null +++ b/libcef/common/cef_switches.h @@ -0,0 +1,44 @@ +// 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. + +// Defines all the "cef" command-line switches. + +#ifndef CEF_LIBCEF_COMMON_CEF_SWITCHES_H_ +#define CEF_LIBCEF_COMMON_CEF_SWITCHES_H_ +#pragma once + +namespace switches { + +extern const char kLogFile[]; +extern const char kLogSeverity[]; +extern const char kLogSeverity_Verbose[]; +extern const char kLogSeverity_Info[]; +extern const char kLogSeverity_Warning[]; +extern const char kLogSeverity_Error[]; +extern const char kLogSeverity_Disable[]; +extern const char kResourcesDirPath[]; +extern const char kLocalesDirPath[]; +extern const char kDisablePackLoading[]; +extern const char kUncaughtExceptionStackSize[]; +extern const char kContextSafetyImplementation[]; +extern const char kDefaultEncoding[]; +extern const char kDisableJavascriptOpenWindows[]; +extern const char kDisableJavascriptCloseWindows[]; +extern const char kDisableJavascriptAccessClipboard[]; +extern const char kDisableJavascriptDomPaste[]; +extern const char kEnableCaretBrowsing[]; +extern const char kAllowUniversalAccessFromFileUrls[]; +extern const char kDisableImageLoading[]; +extern const char kImageShrinkStandaloneToFit[]; +extern const char kDisableTextAreaResize[]; +extern const char kDisableTabToLinks[]; +extern const char kPersistSessionCookies[]; +extern const char kEnableMediaStream[]; +extern const char kEnableSpeechInput[]; +extern const char kEnableProfanityFilter[]; +extern const char kCrashDumpsDir[]; + +} // namespace switches + +#endif // CEF_LIBCEF_COMMON_CEF_SWITCHES_H_ diff --git a/libcef/common/command_line_impl.cc b/libcef/common/command_line_impl.cc new file mode 100644 index 000000000..8075b0ccc --- /dev/null +++ b/libcef/common/command_line_impl.cc @@ -0,0 +1,159 @@ +// 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 "libcef/common/command_line_impl.h" + +#include "base/files/file_path.h" +#include "base/logging.h" + +CefCommandLineImpl::CefCommandLineImpl(CommandLine* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +bool CefCommandLineImpl::IsValid() { + return !detached(); +} + +bool CefCommandLineImpl::IsReadOnly() { + return read_only(); +} + +CefRefPtr CefCommandLineImpl::Copy() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return new CefCommandLineImpl( + new CommandLine(const_value().argv()), true, false); +} + +void CefCommandLineImpl::InitFromArgv(int argc, const char* const* argv) { +#if !defined(OS_WIN) + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->InitFromArgv(argc, argv); +#else + NOTREACHED() << "method not supported on this platform"; +#endif +} + +void CefCommandLineImpl::InitFromString(const CefString& command_line) { +#if defined(OS_WIN) + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->ParseFromString(command_line); +#else + NOTREACHED() << "method not supported on this platform"; +#endif +} + +void CefCommandLineImpl::Reset() { + CEF_VALUE_VERIFY_RETURN_VOID(true); + CommandLine::StringVector argv; + argv.push_back(mutable_value()->GetProgram().value()); + mutable_value()->InitFromArgv(argv); + + const CommandLine::SwitchMap& map = mutable_value()->GetSwitches(); + const_cast(&map)->clear(); +} + +void CefCommandLineImpl::GetArgv(std::vector& argv) { + CEF_VALUE_VERIFY_RETURN_VOID(false); + const CommandLine::StringVector& cmd_argv = const_value().argv(); + CommandLine::StringVector::const_iterator it = cmd_argv.begin(); + for (; it != cmd_argv.end(); ++it) + argv.push_back(*it); +} + +CefString CefCommandLineImpl::GetCommandLineString() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetCommandLineString(); +} + +CefString CefCommandLineImpl::GetProgram() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetProgram().value(); +} + +void CefCommandLineImpl::SetProgram(const CefString& program) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->SetProgram(base::FilePath(program)); +} + +bool CefCommandLineImpl::HasSwitches() { + CEF_VALUE_VERIFY_RETURN(false, false); + return (const_value().GetSwitches().size() > 0); +} + +bool CefCommandLineImpl::HasSwitch(const CefString& name) { + CEF_VALUE_VERIFY_RETURN(false, false); + return const_value().HasSwitch(name); +} + +CefString CefCommandLineImpl::GetSwitchValue(const CefString& name) { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().GetSwitchValueNative(name); +} + +void CefCommandLineImpl::GetSwitches(SwitchMap& switches) { + CEF_VALUE_VERIFY_RETURN_VOID(false); + const CommandLine::SwitchMap& map = const_value().GetSwitches(); + CommandLine::SwitchMap::const_iterator it = map.begin(); + for (; it != map.end(); ++it) + switches.insert(std::make_pair(it->first, it->second)); +} + +void CefCommandLineImpl::AppendSwitch(const CefString& name) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->AppendSwitch(name); +} + +void CefCommandLineImpl::AppendSwitchWithValue(const CefString& name, + const CefString& value) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->AppendSwitchNative(name, value); +} + +bool CefCommandLineImpl::HasArguments() { + CEF_VALUE_VERIFY_RETURN(false, false); + return (const_value().GetArgs().size() > 0); +} + +void CefCommandLineImpl::GetArguments(ArgumentList& arguments) { + CEF_VALUE_VERIFY_RETURN_VOID(false); + const CommandLine::StringVector& vec = const_value().GetArgs(); + CommandLine::StringVector::const_iterator it = vec.begin(); + for (; it != vec.end(); ++it) + arguments.push_back(*it); +} + +void CefCommandLineImpl::AppendArgument(const CefString& argument) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->AppendArgNative(argument); +} + +void CefCommandLineImpl::PrependWrapper(const CefString& wrapper) { + CEF_VALUE_VERIFY_RETURN_VOID(true); + mutable_value()->PrependWrapper(wrapper); +} + + +// CefCommandLine implementation. + +// static +CefRefPtr CefCommandLine::CreateCommandLine() { + return new CefCommandLineImpl( + new CommandLine(CommandLine::NO_PROGRAM), true, false); +} + +// static +CefRefPtr CefCommandLine::GetGlobalCommandLine() { + // Uses a singleton reference object. + static CefRefPtr commandLinePtr; + if (!commandLinePtr.get()) { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line) + commandLinePtr = new CefCommandLineImpl(command_line, false, true); + } + return commandLinePtr.get(); +} diff --git a/libcef/common/command_line_impl.h b/libcef/common/command_line_impl.h new file mode 100644 index 000000000..85f472657 --- /dev/null +++ b/libcef/common/command_line_impl.h @@ -0,0 +1,50 @@ +// 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_LIBCEF_COMMON_COMMAND_LINE_IMPL_H_ +#define CEF_LIBCEF_COMMON_COMMAND_LINE_IMPL_H_ +#pragma once + +#include "include/cef_command_line.h" +#include "libcef/common/value_base.h" + +#include "base/command_line.h" + +// CefCommandLine implementation +class CefCommandLineImpl : public CefValueBase { + public: + CefCommandLineImpl(CommandLine* value, + bool will_delete, + bool read_only); + + // CefCommandLine methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual void InitFromArgv(int argc, const char* const* argv) OVERRIDE; + virtual void InitFromString(const CefString& command_line) OVERRIDE; + virtual void Reset() OVERRIDE; + virtual void GetArgv(std::vector& argv) OVERRIDE; + virtual CefString GetCommandLineString() OVERRIDE; + virtual CefString GetProgram() OVERRIDE; + virtual void SetProgram(const CefString& program) OVERRIDE; + virtual bool HasSwitches() OVERRIDE; + virtual bool HasSwitch(const CefString& name) OVERRIDE; + virtual CefString GetSwitchValue(const CefString& name) OVERRIDE; + virtual void GetSwitches(SwitchMap& switches) OVERRIDE; + virtual void AppendSwitch(const CefString& name) OVERRIDE; + virtual void AppendSwitchWithValue(const CefString& name, + const CefString& value) OVERRIDE; + virtual bool HasArguments() OVERRIDE; + virtual void GetArguments(ArgumentList& arguments) OVERRIDE; + virtual void AppendArgument(const CefString& argument) OVERRIDE; + virtual void PrependWrapper(const CefString& wrapper) OVERRIDE; + + // Must hold the controller lock while using this value. + const CommandLine& command_line() { return const_value(); } + + DISALLOW_COPY_AND_ASSIGN(CefCommandLineImpl); +}; + +#endif // CEF_LIBCEF_COMMON_COMMAND_LINE_IMPL_H_ diff --git a/libcef/common/content_client.cc b/libcef/common/content_client.cc new file mode 100644 index 000000000..f9bada753 --- /dev/null +++ b/libcef/common/content_client.cc @@ -0,0 +1,256 @@ +// 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 "libcef/common/content_client.h" +#include "include/cef_stream.h" +#include "include/cef_version.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/common/scheme_registrar_impl.h" +#include "libcef/common/scheme_registration.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/string_piece.h" +#include "base/strings/stringprintf.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/pepper_plugin_info.h" +#include "content/public/common/user_agent.h" +#include "ppapi/shared_impl/ppapi_permissions.h" +#include "ui/base/resource/resource_bundle.h" + +namespace { + +CefContentClient* g_content_client = NULL; + +const char kPDFPluginName[] = "Chrome PDF Viewer"; +const char kPDFPluginMimeType[] = "application/pdf"; +const char kPDFPluginExtension[] = "pdf"; +const char kPDFPluginDescription[] = "Portable Document Format"; +const uint32 kPDFPluginPermissions = ppapi::PERMISSION_PRIVATE | + ppapi::PERMISSION_DEV; + +// Appends the known built-in plugins to the given vector. +// Based on chrome/common/chrome_content_client.cc. +void ComputeBuiltInPlugins(std::vector* plugins) { + // PDF. + // + // Once we're sandboxed, we can't know if the PDF plugin is available or not; + // but (on Linux) this function is always called once before we're sandboxed. + // So the first time through test if the file is available and then skip the + // check on subsequent calls if yes. + static bool skip_pdf_file_check = false; + base::FilePath path; + if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) { + if (skip_pdf_file_check || base::PathExists(path)) { + content::PepperPluginInfo pdf; + pdf.path = path; + pdf.name = kPDFPluginName; + // Only in-process loading is currently supported. See issue #1331. + pdf.is_out_of_process = false; + content::WebPluginMimeType pdf_mime_type(kPDFPluginMimeType, + kPDFPluginExtension, + kPDFPluginDescription); + pdf.mime_types.push_back(pdf_mime_type); + pdf.permissions = kPDFPluginPermissions; + plugins->push_back(pdf); + + skip_pdf_file_check = true; + } + } +} + +} // namespace + +CefContentClient::CefContentClient(CefRefPtr application) + : application_(application), + pack_loading_disabled_(false), + allow_pack_file_load_(false), + scheme_info_list_locked_(false) { + DCHECK(!g_content_client); + g_content_client = this; +} + +CefContentClient::~CefContentClient() { + g_content_client = NULL; +} + +// static +CefContentClient* CefContentClient::Get() { + return g_content_client; +} + +void CefContentClient::AddPepperPlugins( + std::vector* plugins) { + ComputeBuiltInPlugins(plugins); +} + +void CefContentClient::AddAdditionalSchemes( + std::vector* standard_schemes, + std::vector* savable_schemes) { + DCHECK(!scheme_info_list_locked_); + + if (application_.get()) { + CefRefPtr schemeRegistrar( + new CefSchemeRegistrarImpl()); + application_->OnRegisterCustomSchemes(schemeRegistrar.get()); + schemeRegistrar->GetStandardSchemes(standard_schemes); + + // No references to the registar should be kept. + schemeRegistrar->Detach(); + DCHECK(schemeRegistrar->VerifyRefCount()); + } + + scheme::AddInternalSchemes(standard_schemes); + + scheme_info_list_locked_ = true; +} + +std::string CefContentClient::GetUserAgent() const { + std::string product_version; + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kProductVersion)) { + product_version = + command_line.GetSwitchValueASCII(switches::kProductVersion); + } else { + product_version = base::StringPrintf("Chrome/%d.%d.%d.%d", + CHROME_VERSION_MAJOR, CHROME_VERSION_MINOR, CHROME_VERSION_BUILD, + CHROME_VERSION_PATCH); + } + + return content::BuildUserAgentFromProduct(product_version); +} + +base::string16 CefContentClient::GetLocalizedString(int message_id) const { + base::string16 value = + ResourceBundle::GetSharedInstance().GetLocalizedString(message_id); + if (value.empty()) + LOG(ERROR) << "No localized string available for id " << message_id; + + return value; +} + +base::StringPiece CefContentClient::GetDataResource( + int resource_id, + ui::ScaleFactor scale_factor) const { + base::StringPiece value = + ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( + resource_id, scale_factor); + if (value.empty()) + LOG(ERROR) << "No data resource available for id " << resource_id; + + return value; +} + +gfx::Image& CefContentClient::GetNativeImageNamed(int resource_id) const { + gfx::Image& value = + ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); + if (value.IsEmpty()) + LOG(ERROR) << "No native image available for id " << resource_id; + + return value; +} + +void CefContentClient::AddCustomScheme(const SchemeInfo& scheme_info) { + DCHECK(!scheme_info_list_locked_); + scheme_info_list_.push_back(scheme_info); + + if (CefContentBrowserClient::Get()) { + CefContentBrowserClient::Get()->RegisterCustomScheme( + scheme_info.scheme_name); + } +} + +const CefContentClient::SchemeInfoList* CefContentClient::GetCustomSchemes() { + DCHECK(scheme_info_list_locked_); + return &scheme_info_list_; +} + +bool CefContentClient::HasCustomScheme(const std::string& scheme_name) { + DCHECK(scheme_info_list_locked_); + if (scheme_info_list_.empty()) + return false; + + SchemeInfoList::const_iterator it = scheme_info_list_.begin(); + for (; it != scheme_info_list_.end(); ++it) { + if (it->scheme_name == scheme_name) + return true; + } + + return false; +} + +base::FilePath CefContentClient::GetPathForResourcePack( + const base::FilePath& pack_path, + ui::ScaleFactor scale_factor) { + // Only allow the cef pack file to load. + if (!pack_loading_disabled_ && allow_pack_file_load_) + return pack_path; + return base::FilePath(); +} + +base::FilePath CefContentClient::GetPathForLocalePack( + const base::FilePath& pack_path, + const std::string& locale) { + if (!pack_loading_disabled_) + return pack_path; + return base::FilePath(); +} + +gfx::Image CefContentClient::GetImageNamed(int resource_id) { + return gfx::Image(); +} + +gfx::Image CefContentClient::GetNativeImageNamed( + int resource_id, + ui::ResourceBundle::ImageRTL rtl) { + return gfx::Image(); +} + +base::RefCountedStaticMemory* CefContentClient::LoadDataResourceBytes( + int resource_id, + ui::ScaleFactor scale_factor) { + return NULL; +} + +bool CefContentClient::GetRawDataResource(int resource_id, + ui::ScaleFactor scale_factor, + base::StringPiece* value) { + if (application_.get()) { + CefRefPtr handler = + application_->GetResourceBundleHandler(); + if (handler.get()) { + void* data = NULL; + size_t data_size = 0; + if (handler->GetDataResource(resource_id, data, data_size)) + *value = base::StringPiece(static_cast(data), data_size); + } + } + + return (pack_loading_disabled_ || !value->empty()); +} + +bool CefContentClient::GetLocalizedString(int message_id, + base::string16* value) { + if (application_.get()) { + CefRefPtr handler = + application_->GetResourceBundleHandler(); + if (handler.get()) { + CefString cef_str; + if (handler->GetLocalizedString(message_id, cef_str)) + *value = cef_str; + } + } + + return (pack_loading_disabled_ || !value->empty()); +} + +scoped_ptr CefContentClient::GetFont( + ui::ResourceBundle::FontStyle style) { + return scoped_ptr(); +} diff --git a/libcef/common/content_client.h b/libcef/common/content_client.h new file mode 100644 index 000000000..70ddb1f57 --- /dev/null +++ b/libcef/common/content_client.h @@ -0,0 +1,92 @@ +// 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_LIBCEF_COMMON_CONTENT_CLIENT_H_ +#define CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_ +#pragma once + +#include +#include +#include + +#include "include/cef_app.h" + +#include "base/compiler_specific.h" +#include "content/public/common/content_client.h" +#include "ui/base/resource/resource_bundle.h" + +class CefContentClient : public content::ContentClient, + public ui::ResourceBundle::Delegate { + public: + explicit CefContentClient(CefRefPtr application); + virtual ~CefContentClient(); + + // Returns the singleton CefContentClient instance. + static CefContentClient* Get(); + + // content::ContentClient methods. + virtual void AddPepperPlugins( + std::vector* plugins) OVERRIDE; + virtual void AddAdditionalSchemes( + std::vector* standard_schemes, + std::vector* savable_schemes) OVERRIDE; + virtual std::string GetUserAgent() const OVERRIDE; + virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE; + virtual base::StringPiece GetDataResource( + int resource_id, + ui::ScaleFactor scale_factor) const OVERRIDE; + virtual gfx::Image& GetNativeImageNamed(int resource_id) const OVERRIDE; + + struct SchemeInfo { + std::string scheme_name; + bool is_standard; + bool is_local; + bool is_display_isolated; + }; + typedef std::list SchemeInfoList; + + // Custom scheme registration. + void AddCustomScheme(const SchemeInfo& scheme_info); + const SchemeInfoList* GetCustomSchemes(); + bool HasCustomScheme(const std::string& scheme_name); + + CefRefPtr application() const { return application_; } + + void set_pack_loading_disabled(bool val) { pack_loading_disabled_ = val; } + bool pack_loading_disabled() const { return pack_loading_disabled_; } + void set_allow_pack_file_load(bool val) { allow_pack_file_load_ = val; } + + private: + // ui::ResourceBundle::Delegate methods. + virtual base::FilePath GetPathForResourcePack( + const base::FilePath& pack_path, + ui::ScaleFactor scale_factor) OVERRIDE; + virtual base::FilePath GetPathForLocalePack( + const base::FilePath& pack_path, + const std::string& locale) OVERRIDE; + virtual gfx::Image GetImageNamed(int resource_id) OVERRIDE; + virtual gfx::Image GetNativeImageNamed( + int resource_id, + ui::ResourceBundle::ImageRTL rtl) OVERRIDE; + virtual base::RefCountedStaticMemory* LoadDataResourceBytes( + int resource_id, + ui::ScaleFactor scale_factor) OVERRIDE; + virtual bool GetRawDataResource(int resource_id, + ui::ScaleFactor scale_factor, + base::StringPiece* value) OVERRIDE; + virtual bool GetLocalizedString(int message_id, + base::string16* value) OVERRIDE; + virtual scoped_ptr GetFont( + ui::ResourceBundle::FontStyle style) OVERRIDE; + + CefRefPtr application_; + bool pack_loading_disabled_; + bool allow_pack_file_load_; + + // Custom schemes handled by the client. + SchemeInfoList scheme_info_list_; + bool scheme_info_list_locked_; +}; + +#endif // CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_ diff --git a/libcef/common/drag_data_impl.cc b/libcef/common/drag_data_impl.cc new file mode 100644 index 000000000..f5c42dfa5 --- /dev/null +++ b/libcef/common/drag_data_impl.cc @@ -0,0 +1,194 @@ +// 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 + +#include "libcef/browser/stream_impl.h" +#include "libcef/common/drag_data_impl.h" +#include "base/files/file_path.h" +#include "net/base/filename_util.h" +#include "net/base/net_util.h" + +#define CHECK_READONLY_RETURN_VOID() \ + if (read_only_) { \ + NOTREACHED() << "object is read only"; \ + return; \ + } + +CefDragDataImpl::CefDragDataImpl(const content::DropData& data) + : data_(data), + read_only_(false) { +} + +CefDragDataImpl::CefDragDataImpl() + : read_only_(false) { +} + +CefRefPtr CefDragData::Create() { + return new CefDragDataImpl(); +} + +CefRefPtr CefDragDataImpl::Clone() { + CefDragDataImpl* drag_data = NULL; + { + base::AutoLock lock_scope(lock_); + drag_data = new CefDragDataImpl(data_); + } + return drag_data; +} + +bool CefDragDataImpl::IsReadOnly() { + base::AutoLock lock_scope(lock_); + return read_only_; +} + +bool CefDragDataImpl::IsLink() { + base::AutoLock lock_scope(lock_); + return (data_.url.is_valid() && data_.file_description_filename.empty()); +} + +bool CefDragDataImpl::IsFragment() { + base::AutoLock lock_scope(lock_); + return (!data_.url.is_valid() && data_.file_description_filename.empty() && + data_.filenames.empty()); +} + +bool CefDragDataImpl::IsFile() { + base::AutoLock lock_scope(lock_); + return (!data_.file_description_filename.empty() || !data_.filenames.empty()); +} + +CefString CefDragDataImpl::GetLinkURL() { + base::AutoLock lock_scope(lock_); + return data_.url.spec(); +} + +CefString CefDragDataImpl::GetLinkTitle() { + base::AutoLock lock_scope(lock_); + return data_.url_title; +} + +CefString CefDragDataImpl::GetLinkMetadata() { + base::AutoLock lock_scope(lock_); + return data_.download_metadata; +} + +CefString CefDragDataImpl::GetFragmentText() { + base::AutoLock lock_scope(lock_); + return data_.text.is_null() ? CefString() : CefString(data_.text.string()); +} + +CefString CefDragDataImpl::GetFragmentHtml() { + base::AutoLock lock_scope(lock_); + return data_.html.is_null() ? CefString() : CefString(data_.html.string()); +} + +CefString CefDragDataImpl::GetFragmentBaseURL() { + base::AutoLock lock_scope(lock_); + return data_.html_base_url.spec(); +} + +CefString CefDragDataImpl::GetFileName() { + base::AutoLock lock_scope(lock_); + if (data_.file_description_filename.empty()) + return CefString(); + + base::FilePath file_name(CefString(data_.file_description_filename)); + // Images without ALT text will only have a file extension so we need to + // synthesize one from the provided extension and URL. + if (file_name.BaseName().RemoveExtension().empty()) { + CefString extension = file_name.Extension(); + // Retrieve the name from the URL. + CefString suggested_file_name = + net::GetSuggestedFilename(data_.url, "", "", "", "", ""); + file_name = base::FilePath(suggested_file_name).ReplaceExtension(extension); + } + return file_name.value(); +} + +size_t CefDragDataImpl::GetFileContents(CefRefPtr writer) { + base::AutoLock lock_scope(lock_); + if (data_.file_contents.empty()) + return 0; + + char* data = const_cast(data_.file_contents.c_str()); + size_t size = data_.file_contents.size(); + + if (!writer.get()) + return size; + + return writer->Write(data, 1, size); +} + +bool CefDragDataImpl::GetFileNames(std::vector& names) { + base::AutoLock lock_scope(lock_); + if (data_.filenames.empty()) + return false; + + std::vector::const_iterator it = + data_.filenames.begin(); + for (; it != data_.filenames.end(); ++it) + names.push_back(it->path.value()); + + return true; +} + +void CefDragDataImpl::SetLinkURL(const CefString& url) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.url = GURL(url.ToString()); +} + +void CefDragDataImpl::SetLinkTitle(const CefString& title) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.url_title = title.ToString16(); +} + +void CefDragDataImpl::SetLinkMetadata(const CefString& data) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.download_metadata = data.ToString16(); +} + +void CefDragDataImpl::SetFragmentText(const CefString& text) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.text = base::NullableString16(text.ToString16(), false); +} + +void CefDragDataImpl::SetFragmentHtml(const CefString& fragment) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.html = base::NullableString16(fragment.ToString16(), false); +} + +void CefDragDataImpl::SetFragmentBaseURL(const CefString& fragment) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.html_base_url = GURL(fragment.ToString()); +} + +void CefDragDataImpl::ResetFileContents() { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.file_contents.erase(); + data_.file_description_filename.erase(); +} + +void CefDragDataImpl::AddFile(const CefString& path, + const CefString& display_name) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + data_.filenames.push_back(ui::FileInfo(base::FilePath(path), + base::FilePath(display_name))); +} + +void CefDragDataImpl::SetReadOnly(bool read_only) { + base::AutoLock lock_scope(lock_); + if (read_only_ == read_only) + return; + + read_only_ = read_only; +} diff --git a/libcef/common/drag_data_impl.h b/libcef/common/drag_data_impl.h new file mode 100644 index 000000000..61e6d14aa --- /dev/null +++ b/libcef/common/drag_data_impl.h @@ -0,0 +1,66 @@ +// 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_LIBCEF_COMMON_DRAG_DATA_IMPL_H_ +#define CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_ +#pragma once + +#include "include/cef_drag_data.h" + +#include + +#include "base/synchronization/lock.h" +#include "content/public/common/drop_data.h" + +// Implementation of CefDragData. +class CefDragDataImpl : public CefDragData { + public: + CefDragDataImpl(); + explicit CefDragDataImpl(const content::DropData& data); + virtual CefRefPtr Clone(); + virtual bool IsReadOnly(); + + virtual bool IsLink(); + virtual bool IsFragment(); + virtual bool IsFile(); + virtual CefString GetLinkURL(); + virtual CefString GetLinkTitle(); + virtual CefString GetLinkMetadata(); + virtual CefString GetFragmentText(); + virtual CefString GetFragmentHtml(); + virtual CefString GetFragmentBaseURL(); + virtual CefString GetFileName(); + virtual size_t GetFileContents(CefRefPtr writer); + virtual bool GetFileNames(std::vector& names); + + virtual void SetLinkURL(const CefString& url); + virtual void SetLinkTitle(const CefString& title); + virtual void SetLinkMetadata(const CefString& data); + virtual void SetFragmentText(const CefString& text); + virtual void SetFragmentHtml(const CefString& fragment); + virtual void SetFragmentBaseURL(const CefString& fragment); + virtual void ResetFileContents(); + virtual void AddFile(const CefString& path, const CefString& display_name); + + // This method is not safe. Use Lock/Unlock to get mutually exclusive access. + const content::DropData& drop_data() { + return data_; + } + + void SetReadOnly(bool read_only); + + base::Lock& lock() { return lock_; } + + private: + content::DropData data_; + + // True if this object is read-only. + bool read_only_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefDragDataImpl); +}; + +#endif // CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_ diff --git a/libcef/common/http_header_utils.cc b/libcef/common/http_header_utils.cc new file mode 100644 index 000000000..249833bc5 --- /dev/null +++ b/libcef/common/http_header_utils.cc @@ -0,0 +1,43 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "libcef/common/http_header_utils.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_util.h" + +using net::HttpResponseHeaders; + +namespace HttpHeaderUtils { + +std::string GenerateHeaders(const HeaderMap& map) { + std::string headers; + + for (HeaderMap::const_iterator header = map.begin(); + header != map.end(); + ++header) { + const CefString& key = header->first; + const CefString& value = header->second; + + if (!key.empty()) { + // Delimit with "\r\n". + if (!headers.empty()) + headers += "\r\n"; + + headers += std::string(key) + ": " + std::string(value); + } + } + + return headers; +} + +void ParseHeaders(const std::string& header_str, HeaderMap& map) { + // Parse the request header values + for (net::HttpUtil::HeadersIterator i(header_str.begin(), + header_str.end(), "\n"); + i.GetNext(); ) { + map.insert(std::make_pair(i.name(), i.values())); + } +} + +} // namespace HttpHeaderUtils diff --git a/libcef/common/http_header_utils.h b/libcef/common/http_header_utils.h new file mode 100644 index 000000000..579b4a9cf --- /dev/null +++ b/libcef/common/http_header_utils.h @@ -0,0 +1,22 @@ +// 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_LIBCEF_COMMON_HTTP_HEADER_UTILS_H_ +#define CEF_LIBCEF_COMMON_HTTP_HEADER_UTILS_H_ +#pragma once + +#include + +#include "include/cef_request.h" + +namespace HttpHeaderUtils { + +typedef CefRequest::HeaderMap HeaderMap; + +std::string GenerateHeaders(const HeaderMap& map); +void ParseHeaders(const std::string& header_str, HeaderMap& map); + +}; // namespace HttpHeaderUtils + +#endif // CEF_LIBCEF_COMMON_HTTP_HEADER_UTILS_H_ diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc new file mode 100644 index 000000000..2d8aa112c --- /dev/null +++ b/libcef/common/main_delegate.cc @@ -0,0 +1,594 @@ +// 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 "libcef/common/main_delegate.h" +#include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" +#include "libcef/common/breakpad_client.h" +#include "libcef/common/cef_switches.h" +#include "libcef/common/command_line_impl.h" +#include "libcef/renderer/content_renderer_client.h" +#include "libcef/utility/content_utility_client.h" + +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/file_util.h" +#include "base/lazy_instance.h" +#include "base/path_service.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_main_runner.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/main_function_params.h" +#include "ui/base/layout.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_paths.h" +#include "ui/base/ui_base_switches.h" + +#if defined(OS_WIN) +#include // NOLINT(build/include_order) +#include "components/breakpad/app/breakpad_win.h" +#endif + +#if defined(OS_MACOSX) +#include "base/mac/os_crash_dumps.h" +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "components/breakpad/app/breakpad_mac.h" +#include "content/public/common/content_paths.h" +#endif + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +#include "components/breakpad/app/breakpad_linux.h" +#endif + +namespace { + +base::LazyInstance::Leaky g_shell_breakpad_client = + LAZY_INSTANCE_INITIALIZER; + +#if defined(OS_MACOSX) + +base::FilePath GetFrameworksPath() { + // Start out with the path to the running executable. + base::FilePath execPath; + PathService::Get(base::FILE_EXE, &execPath); + + // Get the main bundle path. + base::FilePath bundlePath = base::mac::GetAppBundlePath(execPath); + + // Go into the Contents/Frameworks directory. + return bundlePath.Append(FILE_PATH_LITERAL("Contents")) + .Append(FILE_PATH_LITERAL("Frameworks")); +} + +// The framework bundle path is used for loading resources, libraries, etc. +base::FilePath GetFrameworkBundlePath() { + return GetFrameworksPath().Append( + FILE_PATH_LITERAL("Chromium Embedded Framework.framework")); +} + +base::FilePath GetResourcesFilePath() { + return GetFrameworkBundlePath().Append(FILE_PATH_LITERAL("Resources")); +} + +base::FilePath GetLibrariesFilePath() { + return GetFrameworkBundlePath().Append(FILE_PATH_LITERAL("Libraries")); +} + +void OverrideFrameworkBundlePath() { + base::mac::SetOverrideFrameworkBundlePath(GetFrameworkBundlePath()); +} + +void OverrideChildProcessPath() { + // Retrieve the name of the running executable. + base::FilePath path; + PathService::Get(base::FILE_EXE, &path); + + std::string name = path.BaseName().value(); + + base::FilePath helper_path = GetFrameworksPath() + .Append(FILE_PATH_LITERAL(name+" Helper.app")) + .Append(FILE_PATH_LITERAL("Contents")) + .Append(FILE_PATH_LITERAL("MacOS")) + .Append(FILE_PATH_LITERAL(name+" Helper")); + + PathService::Override(content::CHILD_PROCESS_EXE, helper_path); +} + +#else // !defined(OS_MACOSX) + +base::FilePath GetResourcesFilePath() { + base::FilePath pak_dir; + PathService::Get(base::DIR_MODULE, &pak_dir); + return pak_dir; +} + +base::FilePath GetLibrariesFilePath() { + return GetResourcesFilePath(); +} + +#endif // !defined(OS_MACOSX) + +// File name of the internal PDF plugin on different platforms. +const base::FilePath::CharType kInternalPDFPluginFileName[] = +#if defined(OS_WIN) + FILE_PATH_LITERAL("pdf.dll"); +#elif defined(OS_MACOSX) + FILE_PATH_LITERAL("PDF.plugin"); +#else // Linux and Chrome OS + FILE_PATH_LITERAL("libpdf.so"); +#endif + +void OverridePdfPluginPath() { + base::FilePath plugin_path = GetLibrariesFilePath(); + plugin_path = plugin_path.Append(kInternalPDFPluginFileName); + PathService::Override(chrome::FILE_PDF_PLUGIN, plugin_path); +} + +// Returns true if |scale_factor| is supported by this platform. +// Same as ResourceBundle::IsScaleFactorSupported. +bool IsScaleFactorSupported(ui::ScaleFactor scale_factor) { + const std::vector& supported_scale_factors = + ui::GetSupportedScaleFactors(); + return std::find(supported_scale_factors.begin(), + supported_scale_factors.end(), + scale_factor) != supported_scale_factors.end(); +} + +// Used to run the UI on a separate thread. +class CefUIThread : public base::Thread { + public: + explicit CefUIThread(const content::MainFunctionParams& main_function_params) + : base::Thread("CefUIThread"), + main_function_params_(main_function_params) { + } + + virtual void Init() OVERRIDE { +#if defined(OS_WIN) + // Initializes the COM library on the current thread. + CoInitialize(NULL); +#endif + + // Use our own browser process runner. + browser_runner_.reset(content::BrowserMainRunner::Create()); + + // Initialize browser process state. Uses the current thread's mesage loop. + int exit_code = browser_runner_->Initialize(main_function_params_); + CHECK_EQ(exit_code, -1); + } + + virtual void CleanUp() OVERRIDE { + browser_runner_->Shutdown(); + browser_runner_.reset(NULL); + +#if defined(OS_WIN) + // Closes the COM library on the current thread. CoInitialize must + // be balanced by a corresponding call to CoUninitialize. + CoUninitialize(); +#endif + } + + protected: + content::MainFunctionParams main_function_params_; + scoped_ptr browser_runner_; +}; + +} // namespace + +CefMainDelegate::CefMainDelegate(CefRefPtr application) + : content_client_(application) { + // Necessary so that exported functions from base_impl.cc will be included + // in the binary. + extern void base_impl_stub(); + base_impl_stub(); +} + +CefMainDelegate::~CefMainDelegate() { +} + +bool CefMainDelegate::BasicStartupComplete(int* exit_code) { +#if defined(OS_MACOSX) + OverrideFrameworkBundlePath(); +#endif + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + std::string process_type = + command_line->GetSwitchValueASCII(switches::kProcessType); + + if (process_type.empty()) { + // In the browser process. Populate the global command-line object. + const CefSettings& settings = CefContext::Get()->settings(); + + if (settings.command_line_args_disabled) { + // Remove any existing command-line arguments. + CommandLine::StringVector argv; + argv.push_back(command_line->GetProgram().value()); + command_line->InitFromArgv(argv); + + const CommandLine::SwitchMap& map = command_line->GetSwitches(); + const_cast(&map)->clear(); + } + + if (settings.single_process) + command_line->AppendSwitch(switches::kSingleProcess); + + bool no_sandbox = settings.no_sandbox ? true : false; + + if (settings.browser_subprocess_path.length > 0) { + base::FilePath file_path = + base::FilePath(CefString(&settings.browser_subprocess_path)); + if (!file_path.empty()) { + command_line->AppendSwitchPath(switches::kBrowserSubprocessPath, + file_path); + +#if defined(OS_WIN) + // The sandbox is not supported when using a separate subprocess + // executable on Windows. + no_sandbox = true; +#endif + } + } + + if (no_sandbox) + command_line->AppendSwitch(switches::kNoSandbox); + + if (settings.user_agent.length > 0) { + command_line->AppendSwitchASCII(switches::kUserAgent, + CefString(&settings.user_agent)); + } else if (settings.product_version.length > 0) { + command_line->AppendSwitchASCII(switches::kProductVersion, + CefString(&settings.product_version)); + } + + if (settings.locale.length > 0) { + command_line->AppendSwitchASCII(switches::kLang, + CefString(&settings.locale)); + } else if (!command_line->HasSwitch(switches::kLang)) { + command_line->AppendSwitchASCII(switches::kLang, "en-US"); + } + + if (settings.log_file.length > 0) { + base::FilePath file_path = base::FilePath(CefString(&settings.log_file)); + if (!file_path.empty()) + command_line->AppendSwitchPath(switches::kLogFile, file_path); + } + + if (settings.log_severity != LOGSEVERITY_DEFAULT) { + std::string log_severity; + switch (settings.log_severity) { + case LOGSEVERITY_VERBOSE: + log_severity = switches::kLogSeverity_Verbose; + break; + case LOGSEVERITY_INFO: + log_severity = switches::kLogSeverity_Info; + break; + case LOGSEVERITY_WARNING: + log_severity = switches::kLogSeverity_Warning; + break; + case LOGSEVERITY_ERROR: + log_severity = switches::kLogSeverity_Error; + break; + case LOGSEVERITY_DISABLE: + log_severity = switches::kLogSeverity_Disable; + break; + default: + break; + } + if (!log_severity.empty()) + command_line->AppendSwitchASCII(switches::kLogSeverity, log_severity); + } + + if (settings.javascript_flags.length > 0) { + command_line->AppendSwitchASCII(switches::kJavaScriptFlags, + CefString(&settings.javascript_flags)); + } + + if (settings.pack_loading_disabled) { + command_line->AppendSwitch(switches::kDisablePackLoading); + } else { + if (settings.resources_dir_path.length > 0) { + base::FilePath file_path = + base::FilePath(CefString(&settings.resources_dir_path)); + if (!file_path.empty()) { + command_line->AppendSwitchPath(switches::kResourcesDirPath, + file_path); + } + } + + if (settings.locales_dir_path.length > 0) { + base::FilePath file_path = + base::FilePath(CefString(&settings.locales_dir_path)); + if (!file_path.empty()) + command_line->AppendSwitchPath(switches::kLocalesDirPath, file_path); + } + } + + if (settings.remote_debugging_port >= 1024 && + settings.remote_debugging_port <= 65535) { + command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, + base::IntToString(settings.remote_debugging_port)); + } + + if (settings.uncaught_exception_stack_size > 0) { + command_line->AppendSwitchASCII(switches::kUncaughtExceptionStackSize, + base::IntToString(settings.uncaught_exception_stack_size)); + } + + if (settings.context_safety_implementation != 0) { + command_line->AppendSwitchASCII(switches::kContextSafetyImplementation, + base::IntToString(settings.context_safety_implementation)); + } + + if (settings.windowless_rendering_enabled) { +#if defined(OS_MACOSX) + // The delegated renderer is not yet enabled by default on OS X. + command_line->AppendSwitch(switches::kEnableDelegatedRenderer); +#endif + } + } + + if (content_client_.application().get()) { + // Give the application a chance to view/modify the command line. + CefRefPtr commandLinePtr( + new CefCommandLineImpl(command_line, false, false)); + content_client_.application()->OnBeforeCommandLineProcessing( + CefString(process_type), commandLinePtr.get()); + commandLinePtr->Detach(NULL); + } + + // Initialize logging. + logging::LoggingSettings log_settings; + const base::FilePath& log_file = + command_line->GetSwitchValuePath(switches::kLogFile); + log_settings.log_file = log_file.value().c_str(); + log_settings.lock_log = logging::DONT_LOCK_LOG_FILE; + log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE; + + logging::LogSeverity log_severity = logging::LOG_INFO; + + std::string log_severity_str = + command_line->GetSwitchValueASCII(switches::kLogSeverity); + if (!log_severity_str.empty()) { + if (LowerCaseEqualsASCII(log_severity_str, + switches::kLogSeverity_Verbose)) { + log_severity = logging::LOG_VERBOSE; + } else if (LowerCaseEqualsASCII(log_severity_str, + switches::kLogSeverity_Warning)) { + log_severity = logging::LOG_WARNING; + } else if (LowerCaseEqualsASCII(log_severity_str, + switches::kLogSeverity_Error)) { + log_severity = logging::LOG_ERROR; + } else if (LowerCaseEqualsASCII(log_severity_str, + switches::kLogSeverity_Disable)) { + log_severity = LOGSEVERITY_DISABLE; + } + } + + if (log_severity == LOGSEVERITY_DISABLE) { + log_settings.logging_dest = logging::LOG_NONE; + } else { + log_settings.logging_dest = logging::LOG_TO_ALL; + logging::SetMinLogLevel(log_severity); + } + + logging::InitLogging(log_settings); + + content::SetContentClient(&content_client_); + + return false; +} + +void CefMainDelegate::PreSandboxStartup() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + const std::string& process_type = + command_line.GetSwitchValueASCII(switches::kProcessType); + + if (command_line.HasSwitch(switches::kEnableCrashReporter)) { + breakpad::SetBreakpadClient(g_shell_breakpad_client.Pointer()); +#if defined(OS_MACOSX) + base::mac::DisableOSCrashDumps(); + breakpad::InitCrashReporter(process_type); + breakpad::InitCrashProcessInfo(process_type); +#elif defined(OS_POSIX) && !defined(OS_MACOSX) + if (process_type != switches::kZygoteProcess) + breakpad::InitCrashReporter(process_type); +#elif defined(OS_WIN) + UINT new_flags = + SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; + UINT existing_flags = SetErrorMode(new_flags); + SetErrorMode(existing_flags | new_flags); + breakpad::InitCrashReporter(process_type); +#endif + } + +#if defined(OS_MACOSX) + if (!command_line.HasSwitch(switches::kProcessType)) { + // Only override the child process path when executing the main process. + OverrideChildProcessPath(); + } +#endif + + OverridePdfPluginPath(); + + if (command_line.HasSwitch(switches::kDisablePackLoading)) + content_client_.set_pack_loading_disabled(true); + + InitializeResourceBundle(); + + if (process_type == switches::kUtilityProcess || + process_type == switches::kZygoteProcess) { + CefContentUtilityClient::PreSandboxStartup(); + } +} + +int CefMainDelegate::RunProcess( + const std::string& process_type, + const content::MainFunctionParams& main_function_params) { + if (process_type.empty()) { + const CefSettings& settings = CefContext::Get()->settings(); + if (!settings.multi_threaded_message_loop) { + // Use our own browser process runner. + browser_runner_.reset(content::BrowserMainRunner::Create()); + + // Initialize browser process state. Results in a call to + // CefBrowserMain::PreMainMessageLoopStart() which creates the UI message + // loop. + int exit_code = browser_runner_->Initialize(main_function_params); + if (exit_code >= 0) + return exit_code; + } else { + // Run the UI on a separate thread. + scoped_ptr thread; + thread.reset(new CefUIThread(main_function_params)); + base::Thread::Options options; + options.message_loop_type = base::MessageLoop::TYPE_UI; + if (!thread->StartWithOptions(options)) { + NOTREACHED() << "failed to start UI thread"; + return 1; + } + ui_thread_.swap(thread); + } + + return 0; + } + + return -1; +} + +void CefMainDelegate::ProcessExiting(const std::string& process_type) { + ResourceBundle::CleanupSharedInstance(); +} + +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX) +void CefMainDelegate::ZygoteForked() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kEnableCrashReporter)) { + const std::string& process_type = command_line.GetSwitchValueASCII( + switches::kProcessType); + breakpad::InitCrashReporter(process_type); + } +} +#endif + +content::ContentBrowserClient* CefMainDelegate::CreateContentBrowserClient() { + browser_client_.reset(new CefContentBrowserClient); + return browser_client_.get(); +} + +content::ContentRendererClient* + CefMainDelegate::CreateContentRendererClient() { + renderer_client_.reset(new CefContentRendererClient); + return renderer_client_.get(); +} + +content::ContentUtilityClient* CefMainDelegate::CreateContentUtilityClient() { + utility_client_.reset(new CefContentUtilityClient); + return utility_client_.get(); +} + +void CefMainDelegate::ShutdownBrowser() { + if (browser_runner_.get()) { + browser_runner_->Shutdown(); + browser_runner_.reset(NULL); + } + if (ui_thread_.get()) { + // Blocks until the thread has stopped. + ui_thread_->Stop(); + ui_thread_.reset(); + } +} + +void CefMainDelegate::InitializeResourceBundle() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + base::FilePath cef_pak_file, cef_100_percent_pak_file, + cef_200_percent_pak_file, devtools_pak_file, locales_dir; + + if (!content_client_.pack_loading_disabled()) { + base::FilePath resources_dir; + if (command_line.HasSwitch(switches::kResourcesDirPath)) { + resources_dir = + command_line.GetSwitchValuePath(switches::kResourcesDirPath); + } + if (resources_dir.empty()) + resources_dir = GetResourcesFilePath(); + + if (!resources_dir.empty()) { + cef_pak_file = resources_dir.Append(FILE_PATH_LITERAL("cef.pak")); + cef_100_percent_pak_file = + resources_dir.Append(FILE_PATH_LITERAL("cef_100_percent.pak")); + cef_200_percent_pak_file = + resources_dir.Append(FILE_PATH_LITERAL("cef_200_percent.pak")); + devtools_pak_file = + resources_dir.Append(FILE_PATH_LITERAL("devtools_resources.pak")); + } + + if (command_line.HasSwitch(switches::kLocalesDirPath)) + locales_dir = command_line.GetSwitchValuePath(switches::kLocalesDirPath); + + if (!locales_dir.empty()) + PathService::Override(ui::DIR_LOCALES, locales_dir); + } + + std::string locale = command_line.GetSwitchValueASCII(switches::kLang); + DCHECK(!locale.empty()); + + const std::string loaded_locale = + ui::ResourceBundle::InitSharedInstanceWithLocale(locale, + &content_client_); + ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); + + if (!content_client_.pack_loading_disabled()) { + if (loaded_locale.empty()) + LOG(ERROR) << "Could not load locale pak for " << locale; + + content_client_.set_allow_pack_file_load(true); + + if (base::PathExists(cef_pak_file)) { + resource_bundle.AddDataPackFromPath(cef_pak_file, ui::SCALE_FACTOR_NONE); + } else { + LOG(ERROR) << "Could not load cef.pak"; + } + + // On OS X and Linux/Aura always load the 1x data pack first as the 2x data + // pack contains both 1x and 2x images. + const bool load_100_percent = +#if defined(OS_WIN) + IsScaleFactorSupported(ui::SCALE_FACTOR_100P); +#else + true; +#endif + + if (load_100_percent) { + if (base::PathExists(cef_100_percent_pak_file)) { + resource_bundle.AddDataPackFromPath( + cef_100_percent_pak_file, ui::SCALE_FACTOR_100P); + } else { + LOG(ERROR) << "Could not load cef_100_percent.pak"; + } + } + + if (IsScaleFactorSupported(ui::SCALE_FACTOR_200P)) { + if (base::PathExists(cef_200_percent_pak_file)) { + resource_bundle.AddDataPackFromPath( + cef_200_percent_pak_file, ui::SCALE_FACTOR_200P); + } else { + LOG(ERROR) << "Could not load cef_200_percent.pak"; + } + } + + if (base::PathExists(devtools_pak_file)) { + resource_bundle.AddDataPackFromPath( + devtools_pak_file, ui::SCALE_FACTOR_NONE); + } + + content_client_.set_allow_pack_file_load(false); + } +} diff --git a/libcef/common/main_delegate.h b/libcef/common/main_delegate.h new file mode 100644 index 000000000..da1fdbe84 --- /dev/null +++ b/libcef/common/main_delegate.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_ +#define CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_ +#pragma once + +#include + +#include "libcef/common/content_client.h" +#include "include/cef_app.h" + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/app/content_main_delegate.h" + +namespace base { +class Thread; +} + +namespace content { +class BrowserMainRunner; +} + +class CefContentBrowserClient; +class CefContentRendererClient; +class CefContentUtilityClient; + +class CefMainDelegate : public content::ContentMainDelegate { + public: + explicit CefMainDelegate(CefRefPtr application); + virtual ~CefMainDelegate(); + + virtual bool BasicStartupComplete(int* exit_code) OVERRIDE; + virtual void PreSandboxStartup() OVERRIDE; + virtual int RunProcess( + const std::string& process_type, + const content::MainFunctionParams& main_function_params) OVERRIDE; + virtual void ProcessExiting(const std::string& process_type) OVERRIDE; +#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX) + virtual void ZygoteForked() OVERRIDE; +#endif + virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE; + virtual content::ContentRendererClient* + CreateContentRendererClient() OVERRIDE; + virtual content::ContentUtilityClient* CreateContentUtilityClient() OVERRIDE; + + // Shut down the browser runner. + void ShutdownBrowser(); + + CefContentBrowserClient* browser_client() { return browser_client_.get(); } + CefContentClient* content_client() { return &content_client_; } + + private: + void InitializeResourceBundle(); + + scoped_ptr browser_runner_; + scoped_ptr ui_thread_; + + scoped_ptr browser_client_; + scoped_ptr renderer_client_; + scoped_ptr utility_client_; + CefContentClient content_client_; + + DISALLOW_COPY_AND_ASSIGN(CefMainDelegate); +}; + +#endif // CEF_LIBCEF_COMMON_MAIN_DELEGATE_H_ diff --git a/libcef/common/net_resource_provider.cc b/libcef/common/net_resource_provider.cc new file mode 100644 index 000000000..13fbbcf62 --- /dev/null +++ b/libcef/common/net_resource_provider.cc @@ -0,0 +1,10 @@ +// 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 "libcef/common/content_client.h" +#include "libcef/common/net_resource_provider.h" + +base::StringPiece NetResourceProvider(int key) { + return CefContentClient::Get()->GetDataResource(key, ui::SCALE_FACTOR_NONE); +} diff --git a/libcef/common/net_resource_provider.h b/libcef/common/net_resource_provider.h new file mode 100644 index 000000000..73e5ad75e --- /dev/null +++ b/libcef/common/net_resource_provider.h @@ -0,0 +1,14 @@ +// 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_LIBCEF_COMMON_NET_RESOURCE_PROVIDER_H_ +#define CEF_LIBCEF_COMMON_NET_RESOURCE_PROVIDER_H_ +#pragma once + +#include "base/strings/string_piece.h" + +// This is called indirectly by the network layer to access resources. +base::StringPiece NetResourceProvider(int key); + +#endif // CEF_LIBCEF_COMMON_NET_RESOURCE_PROVIDER_H_ diff --git a/libcef/common/process_message_impl.cc b/libcef/common/process_message_impl.cc new file mode 100644 index 000000000..e6dabd87e --- /dev/null +++ b/libcef/common/process_message_impl.cc @@ -0,0 +1,76 @@ +// 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 "libcef/common/process_message_impl.h" +#include "libcef/common/cef_messages.h" +#include "libcef/common/values_impl.h" + +#include "base/logging.h" + +namespace { + +void CopyList(const base::ListValue& source, + base::ListValue& target) { + base::ListValue::const_iterator it = source.begin(); + for (; it != source.end(); ++it) + target.Append((*it)->DeepCopy()); +} + +void CopyValue(const Cef_Request_Params& source, + Cef_Request_Params& target) { + target.name = source.name; + CopyList(source.arguments, target.arguments); +} + +} // namespace + +// static +CefRefPtr CefProcessMessage::Create(const CefString& name) { + Cef_Request_Params* params = new Cef_Request_Params(); + params->name = name; + return new CefProcessMessageImpl(params, true, false); +} + +CefProcessMessageImpl::CefProcessMessageImpl(Cef_Request_Params* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +bool CefProcessMessageImpl::CopyTo(Cef_Request_Params& target) { + CEF_VALUE_VERIFY_RETURN(false, false); + CopyValue(const_value(), target); + return true; +} + +bool CefProcessMessageImpl::IsValid() { + return !detached(); +} + +bool CefProcessMessageImpl::IsReadOnly() { + return read_only(); +} + +CefRefPtr CefProcessMessageImpl::Copy() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + Cef_Request_Params* params = new Cef_Request_Params(); + CopyValue(const_value(), *params); + return new CefProcessMessageImpl(params, true, false); +} + +CefString CefProcessMessageImpl::GetName() { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + return const_value().name; +} + +CefRefPtr CefProcessMessageImpl::GetArgumentList() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return CefListValueImpl::GetOrCreateRef( + const_cast(&(const_value().arguments)), + const_cast(&const_value()), + read_only(), + controller()); +} diff --git a/libcef/common/process_message_impl.h b/libcef/common/process_message_impl.h new file mode 100644 index 000000000..28e078a90 --- /dev/null +++ b/libcef/common/process_message_impl.h @@ -0,0 +1,35 @@ +// 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_LIBCEF_COMMON_PROCESS_MESSAGE_IMPL_H_ +#define CEF_LIBCEF_COMMON_PROCESS_MESSAGE_IMPL_H_ +#pragma once + +#include "include/cef_process_message.h" +#include "libcef/common/value_base.h" + +struct Cef_Request_Params; + +// CefProcessMessage implementation +class CefProcessMessageImpl + : public CefValueBase { + public: + CefProcessMessageImpl(Cef_Request_Params* value, + bool will_delete, + bool read_only); + + // Copies the underlying value to the specified |target| structure. + bool CopyTo(Cef_Request_Params& target); + + // CefProcessMessage methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual CefRefPtr GetArgumentList() OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(CefProcessMessageImpl); +}; + +#endif // CEF_LIBCEF_COMMON_PROCESS_MESSAGE_IMPL_H_ diff --git a/libcef/common/request_impl.cc b/libcef/common/request_impl.cc new file mode 100644 index 000000000..812df1f76 --- /dev/null +++ b/libcef/common/request_impl.cc @@ -0,0 +1,815 @@ +// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include +#include + +#include "libcef/common/http_header_utils.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/task_runner_impl.h" +#include "libcef/common/upload_data.h" + +#include "base/logging.h" +#include "content/public/browser/resource_request_info.h" +#include "net/base/upload_data_stream.h" +#include "net/base/upload_element_reader.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_file_element_reader.h" +#include "net/http/http_request_headers.h" +#include "net/url_request/url_request.h" +#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebURLError.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "webkit/common/resource_type.h" + +namespace { + +// A subclass of net::UploadBytesElementReader that keeps the associated +// UploadElement alive until the request completes. +class BytesElementReader : public net::UploadBytesElementReader { + public: + explicit BytesElementReader(scoped_ptr element) + : net::UploadBytesElementReader(element->bytes(), + element->bytes_length()), + element_(element.Pass()) { + DCHECK_EQ(net::UploadElement::TYPE_BYTES, element_->type()); + } + + virtual ~BytesElementReader() {} + + private: + scoped_ptr element_; + + DISALLOW_COPY_AND_ASSIGN(BytesElementReader); +}; + +base::TaskRunner* GetFileTaskRunner() { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetTaskRunner(TID_FILE); + DCHECK(task_runner); + return task_runner; +} + +// A subclass of net::UploadFileElementReader that keeps the associated +// UploadElement alive until the request completes. +class FileElementReader : public net::UploadFileElementReader { + public: + explicit FileElementReader(scoped_ptr element) + : net::UploadFileElementReader( + GetFileTaskRunner(), + element->file_path(), + element->file_range_offset(), + element->file_range_length(), + element->expected_file_modification_time()), + element_(element.Pass()) { + DCHECK_EQ(net::UploadElement::TYPE_FILE, element_->type()); + } + + virtual ~FileElementReader() {} + + private: + scoped_ptr element_; + + DISALLOW_COPY_AND_ASSIGN(FileElementReader); +}; + +} // namespace + + +#define CHECK_READONLY_RETURN(val) \ + if (read_only_) { \ + NOTREACHED() << "object is read only"; \ + return val; \ + } + +#define CHECK_READONLY_RETURN_VOID() \ + if (read_only_) { \ + NOTREACHED() << "object is read only"; \ + return; \ + } + + +// CefRequest ----------------------------------------------------------------- + +// static +CefRefPtr CefRequest::Create() { + CefRefPtr request(new CefRequestImpl()); + return request; +} + + +// CefRequestImpl ------------------------------------------------------------- + +CefRequestImpl::CefRequestImpl() + : method_("GET"), + resource_type_(RT_SUB_RESOURCE), + transition_type_(TT_EXPLICIT), + flags_(UR_FLAG_NONE), + read_only_(false) { +} + +bool CefRequestImpl::IsReadOnly() { + base::AutoLock lock_scope(lock_); + return read_only_; +} + +CefString CefRequestImpl::GetURL() { + base::AutoLock lock_scope(lock_); + return url_; +} + +void CefRequestImpl::SetURL(const CefString& url) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + url_ = url; +} + +CefString CefRequestImpl::GetMethod() { + base::AutoLock lock_scope(lock_); + return method_; +} + +void CefRequestImpl::SetMethod(const CefString& method) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + method_ = method; +} + +CefRefPtr CefRequestImpl::GetPostData() { + base::AutoLock lock_scope(lock_); + return postdata_; +} + +void CefRequestImpl::SetPostData(CefRefPtr postData) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + postdata_ = postData; +} + +void CefRequestImpl::GetHeaderMap(HeaderMap& headerMap) { + base::AutoLock lock_scope(lock_); + headerMap = headermap_; +} + +void CefRequestImpl::SetHeaderMap(const HeaderMap& headerMap) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + headermap_ = headerMap; +} + +void CefRequestImpl::Set(const CefString& url, + const CefString& method, + CefRefPtr postData, + const HeaderMap& headerMap) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + url_ = url; + method_ = method; + postdata_ = postData; + headermap_ = headerMap; +} + +int CefRequestImpl::GetFlags() { + base::AutoLock lock_scope(lock_); + return flags_; +} +void CefRequestImpl::SetFlags(int flags) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + flags_ = flags; +} + +CefString CefRequestImpl::GetFirstPartyForCookies() { + base::AutoLock lock_scope(lock_); + return first_party_for_cookies_; +} +void CefRequestImpl::SetFirstPartyForCookies(const CefString& url) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + first_party_for_cookies_ = url; +} + +CefRequestImpl::ResourceType CefRequestImpl::GetResourceType() { + base::AutoLock lock_scope(lock_); + return resource_type_; +} + +CefRequestImpl::TransitionType CefRequestImpl::GetTransitionType() { + base::AutoLock lock_scope(lock_); + return transition_type_; +} + +void CefRequestImpl::Set(net::URLRequest* request) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + url_ = request->url().spec(); + method_ = request->method(); + first_party_for_cookies_ = request->first_party_for_cookies().spec(); + + net::HttpRequestHeaders headers = request->extra_request_headers(); + + // URLRequest::SetReferrer ensures that we do not send username and password + // fields in the referrer. + GURL referrer(request->referrer()); + + // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins + // from overriding headers that are controlled using other means. Otherwise a + // plugin could set a referrer although sending the referrer is inhibited. + headers.RemoveHeader(net::HttpRequestHeaders::kReferer); + + // Our consumer should have made sure that this is a safe referrer. See for + // instance WebCore::FrameLoader::HideReferrer. + if (referrer.is_valid()) + headers.SetHeader(net::HttpRequestHeaders::kReferer, referrer.spec()); + + // Transfer request headers + GetHeaderMap(headers, headermap_); + + // Transfer post data, if any + const net::UploadDataStream* data = request->get_upload(); + if (data) { + postdata_ = CefPostData::Create(); + static_cast(postdata_.get())->Set(*data); + } else if (postdata_.get()) { + postdata_ = NULL; + } + + const content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + if (info) { + resource_type_ = + static_cast(info->GetResourceType()); + transition_type_ = + static_cast(info->GetPageTransition()); + } else { + resource_type_ = RT_SUB_RESOURCE; + transition_type_ = TT_EXPLICIT; + } +} + +void CefRequestImpl::Get(net::URLRequest* request) { + base::AutoLock lock_scope(lock_); + + request->set_method(method_); + if (!first_party_for_cookies_.empty()) { + request->set_first_party_for_cookies( + GURL(std::string(first_party_for_cookies_))); + } + + CefString referrerStr; + referrerStr.FromASCII(net::HttpRequestHeaders::kReferer); + HeaderMap headerMap = headermap_; + HeaderMap::iterator it = headerMap.find(referrerStr); + if (it == headerMap.end()) { + request->SetReferrer(""); + } else { + request->SetReferrer(it->second); + headerMap.erase(it); + } + net::HttpRequestHeaders headers; + headers.AddHeadersFromString(HttpHeaderUtils::GenerateHeaders(headerMap)); + request->SetExtraRequestHeaders(headers); + + if (postdata_.get()) { + request->set_upload( + make_scoped_ptr(static_cast(postdata_.get())->Get())); + } else if (request->get_upload()) { + request->set_upload(scoped_ptr()); + } +} + +void CefRequestImpl::Set(const blink::WebURLRequest& request) { + DCHECK(!request.isNull()); + + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + url_ = request.url().spec().utf16(); + method_ = request.httpMethod(); + + const blink::WebHTTPBody& body = request.httpBody(); + if (!body.isNull()) { + postdata_ = new CefPostDataImpl(); + static_cast(postdata_.get())->Set(body); + } else if (postdata_.get()) { + postdata_ = NULL; + } + + headermap_.clear(); + GetHeaderMap(request, headermap_); + + flags_ = UR_FLAG_NONE; + if (request.cachePolicy() == blink::WebURLRequest::ReloadIgnoringCacheData) + flags_ |= UR_FLAG_SKIP_CACHE; + if (request.allowStoredCredentials()) + flags_ |= UR_FLAG_ALLOW_CACHED_CREDENTIALS; + if (request.reportUploadProgress()) + flags_ |= UR_FLAG_REPORT_UPLOAD_PROGRESS; + if (request.reportRawHeaders()) + flags_ |= UR_FLAG_REPORT_RAW_HEADERS; + + first_party_for_cookies_ = request.firstPartyForCookies().spec().utf16(); + + resource_type_ = static_cast( + ::ResourceType::FromTargetType(request.targetType())); +} + +void CefRequestImpl::Get(blink::WebURLRequest& request) { + request.initialize(); + base::AutoLock lock_scope(lock_); + + GURL gurl = GURL(url_.ToString()); + request.setURL(blink::WebURL(gurl)); + + std::string method(method_); + request.setHTTPMethod(blink::WebString::fromUTF8(method.c_str())); + request.setTargetType(blink::WebURLRequest::TargetIsMainFrame); + + blink::WebHTTPBody body; + if (postdata_.get()) { + body.initialize(); + static_cast(postdata_.get())->Get(body); + request.setHTTPBody(body); + } + + SetHeaderMap(headermap_, request); + + request.setCachePolicy((flags_ & UR_FLAG_SKIP_CACHE) ? + blink::WebURLRequest::ReloadIgnoringCacheData : + blink::WebURLRequest::UseProtocolCachePolicy); + + #define SETBOOLFLAG(obj, flags, method, FLAG) \ + obj.method((flags & (FLAG)) == (FLAG)) + + SETBOOLFLAG(request, flags_, setAllowStoredCredentials, + UR_FLAG_ALLOW_CACHED_CREDENTIALS); + SETBOOLFLAG(request, flags_, setReportUploadProgress, + UR_FLAG_REPORT_UPLOAD_PROGRESS); + SETBOOLFLAG(request, flags_, setReportRawHeaders, + UR_FLAG_REPORT_RAW_HEADERS); + + if (!first_party_for_cookies_.empty()) { + GURL gurl = GURL(first_party_for_cookies_.ToString()); + request.setFirstPartyForCookies(blink::WebURL(gurl)); + } +} + +void CefRequestImpl::SetReadOnly(bool read_only) { + base::AutoLock lock_scope(lock_); + if (read_only_ == read_only) + return; + + read_only_ = read_only; + + if (postdata_.get()) + static_cast(postdata_.get())->SetReadOnly(read_only); +} + +// static +void CefRequestImpl::GetHeaderMap(const net::HttpRequestHeaders& headers, + HeaderMap& map) { + if (headers.IsEmpty()) + return; + + net::HttpRequestHeaders::Iterator it(headers); + do { + map.insert(std::make_pair(it.name(), it.value())); + } while (it.GetNext()); +} + + +// static +void CefRequestImpl::GetHeaderMap(const blink::WebURLRequest& request, + HeaderMap& map) { + class HeaderVisitor : public blink::WebHTTPHeaderVisitor { + public: + explicit HeaderVisitor(HeaderMap* map) : map_(map) {} + + virtual void visitHeader(const blink::WebString& name, + const blink::WebString& value) { + map_->insert(std::make_pair(base::string16(name), + base::string16(value))); + } + + private: + HeaderMap* map_; + }; + + HeaderVisitor visitor(&map); + request.visitHTTPHeaderFields(&visitor); +} + +// static +void CefRequestImpl::SetHeaderMap(const HeaderMap& map, + blink::WebURLRequest& request) { + HeaderMap::const_iterator it = map.begin(); + for (; it != map.end(); ++it) + request.setHTTPHeaderField(base::string16(it->first), + base::string16(it->second)); +} + +// CefPostData ---------------------------------------------------------------- + +// static +CefRefPtr CefPostData::Create() { + CefRefPtr postdata(new CefPostDataImpl()); + return postdata; +} + + +// CefPostDataImpl ------------------------------------------------------------ + +CefPostDataImpl::CefPostDataImpl() + : read_only_(false) { +} + +bool CefPostDataImpl::IsReadOnly() { + base::AutoLock lock_scope(lock_); + return read_only_; +} + +size_t CefPostDataImpl::GetElementCount() { + base::AutoLock lock_scope(lock_); + return elements_.size(); +} + +void CefPostDataImpl::GetElements(ElementVector& elements) { + base::AutoLock lock_scope(lock_); + elements = elements_; +} + +bool CefPostDataImpl::RemoveElement(CefRefPtr element) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN(false); + + ElementVector::iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + if (it->get() == element.get()) { + elements_.erase(it); + return true; + } + } + + return false; +} + +bool CefPostDataImpl::AddElement(CefRefPtr element) { + bool found = false; + + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN(false); + + // check that the element isn't already in the list before adding + ElementVector::const_iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + if (it->get() == element.get()) { + found = true; + break; + } + } + + if (!found) + elements_.push_back(element); + + return !found; +} + +void CefPostDataImpl::RemoveElements() { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + elements_.clear(); +} + +void CefPostDataImpl::Set(const net::UploadData& data) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + CefRefPtr postelem; + + const ScopedVector& elements = data.elements(); + ScopedVector::const_iterator it = elements.begin(); + for (; it != elements.end(); ++it) { + postelem = CefPostDataElement::Create(); + static_cast(postelem.get())->Set(**it); + AddElement(postelem); + } +} + +void CefPostDataImpl::Set(const net::UploadDataStream& data_stream) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + CefRefPtr postelem; + + const ScopedVector& elements = + data_stream.element_readers(); + ScopedVector::const_iterator it = elements.begin(); + for (; it != elements.end(); ++it) { + postelem = CefPostDataElement::Create(); + static_cast(postelem.get())->Set(**it); + AddElement(postelem); + } +} + +void CefPostDataImpl::Get(net::UploadData& data) { + base::AutoLock lock_scope(lock_); + + ScopedVector data_elements; + ElementVector::const_iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + net::UploadElement* element = new net::UploadElement(); + static_cast(it->get())->Get(*element); + data_elements.push_back(element); + } + data.swap_elements(&data_elements); +} + +net::UploadDataStream* CefPostDataImpl::Get() { + base::AutoLock lock_scope(lock_); + + ScopedVector element_readers; + ElementVector::const_iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + element_readers.push_back( + static_cast(it->get())->Get()); + } + + return new net::UploadDataStream(element_readers.Pass(), 0); +} + +void CefPostDataImpl::Set(const blink::WebHTTPBody& data) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + CefRefPtr postelem; + blink::WebHTTPBody::Element element; + size_t size = data.elementCount(); + for (size_t i = 0; i < size; ++i) { + if (data.elementAt(i, element)) { + postelem = CefPostDataElement::Create(); + static_cast(postelem.get())->Set(element); + AddElement(postelem); + } + } +} + +void CefPostDataImpl::Get(blink::WebHTTPBody& data) { + base::AutoLock lock_scope(lock_); + + blink::WebHTTPBody::Element element; + ElementVector::iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + static_cast(it->get())->Get(element); + if (element.type == blink::WebHTTPBody::Element::TypeData) { + data.appendData(element.data); + } else if (element.type == blink::WebHTTPBody::Element::TypeFile) { + data.appendFile(element.filePath); + } else { + NOTREACHED(); + } + } +} + +void CefPostDataImpl::SetReadOnly(bool read_only) { + base::AutoLock lock_scope(lock_); + if (read_only_ == read_only) + return; + + read_only_ = read_only; + + ElementVector::const_iterator it = elements_.begin(); + for (; it != elements_.end(); ++it) { + static_cast(it->get())->SetReadOnly(read_only); + } +} + +// CefPostDataElement --------------------------------------------------------- + +// static +CefRefPtr CefPostDataElement::Create() { + CefRefPtr element(new CefPostDataElementImpl()); + return element; +} + + +// CefPostDataElementImpl ----------------------------------------------------- + +CefPostDataElementImpl::CefPostDataElementImpl() + : type_(PDE_TYPE_EMPTY), + read_only_(false) { + memset(&data_, 0, sizeof(data_)); +} + +CefPostDataElementImpl::~CefPostDataElementImpl() { + Cleanup(); +} + +bool CefPostDataElementImpl::IsReadOnly() { + base::AutoLock lock_scope(lock_); + return read_only_; +} + +void CefPostDataElementImpl::SetToEmpty() { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + Cleanup(); +} + +void CefPostDataElementImpl::SetToFile(const CefString& fileName) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + // Clear any data currently in the element + Cleanup(); + + // Assign the new data + type_ = PDE_TYPE_FILE; + cef_string_copy(fileName.c_str(), fileName.length(), &data_.filename); +} + +void CefPostDataElementImpl::SetToBytes(size_t size, const void* bytes) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + // Clear any data currently in the element + Cleanup(); + + // Assign the new data + void* data = malloc(size); + DCHECK(data != NULL); + if (data == NULL) + return; + + memcpy(data, bytes, size); + + type_ = PDE_TYPE_BYTES; + data_.bytes.bytes = data; + data_.bytes.size = size; +} + +CefPostDataElement::Type CefPostDataElementImpl::GetType() { + base::AutoLock lock_scope(lock_); + return type_; +} + +CefString CefPostDataElementImpl::GetFile() { + base::AutoLock lock_scope(lock_); + DCHECK(type_ == PDE_TYPE_FILE); + CefString filename; + if (type_ == PDE_TYPE_FILE) + filename.FromString(data_.filename.str, data_.filename.length, false); + return filename; +} + +size_t CefPostDataElementImpl::GetBytesCount() { + base::AutoLock lock_scope(lock_); + DCHECK(type_ == PDE_TYPE_BYTES); + size_t size = 0; + if (type_ == PDE_TYPE_BYTES) + size = data_.bytes.size; + return size; +} + +size_t CefPostDataElementImpl::GetBytes(size_t size, void* bytes) { + base::AutoLock lock_scope(lock_); + DCHECK(type_ == PDE_TYPE_BYTES); + size_t rv = 0; + if (type_ == PDE_TYPE_BYTES) { + rv = (size < data_.bytes.size ? size : data_.bytes.size); + memcpy(bytes, data_.bytes.bytes, rv); + } + return rv; +} + +void CefPostDataElementImpl::Set(const net::UploadElement& element) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + if (element.type() == net::UploadElement::TYPE_BYTES) { + SetToBytes(element.bytes_length(), element.bytes()); + } else if (element.type() == net::UploadElement::TYPE_FILE) { + SetToFile(element.file_path().value()); + } else { + NOTREACHED(); + } +} + +void CefPostDataElementImpl::Set( + const net::UploadElementReader& element_reader) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + const net::UploadBytesElementReader* bytes_reader = + element_reader.AsBytesReader(); + if (bytes_reader) { + SetToBytes(bytes_reader->length(), bytes_reader->bytes()); + return; + } + + const net::UploadFileElementReader* file_reader = + element_reader.AsFileReader(); + if (file_reader) { + SetToFile(file_reader->path().value()); + return; + } + + NOTREACHED(); +} + +void CefPostDataElementImpl::Get(net::UploadElement& element) { + base::AutoLock lock_scope(lock_); + + if (type_ == PDE_TYPE_BYTES) { + element.SetToBytes(static_cast(data_.bytes.bytes), data_.bytes.size); + } else if (type_ == PDE_TYPE_FILE) { + base::FilePath path = base::FilePath(CefString(&data_.filename)); + element.SetToFilePath(path); + } else { + NOTREACHED(); + } +} + +net::UploadElementReader* CefPostDataElementImpl::Get() { + base::AutoLock lock_scope(lock_); + + if (type_ == PDE_TYPE_BYTES) { + net::UploadElement* element = new net::UploadElement(); + element->SetToBytes(static_cast(data_.bytes.bytes), + data_.bytes.size); + return new BytesElementReader(make_scoped_ptr(element)); + } else if (type_ == PDE_TYPE_FILE) { + net::UploadElement* element = new net::UploadElement(); + base::FilePath path = base::FilePath(CefString(&data_.filename)); + element->SetToFilePath(path); + return new FileElementReader(make_scoped_ptr(element)); + } else { + NOTREACHED(); + return NULL; + } +} + +void CefPostDataElementImpl::Set(const blink::WebHTTPBody::Element& element) { + { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + } + + if (element.type == blink::WebHTTPBody::Element::TypeData) { + SetToBytes(element.data.size(), + static_cast(element.data.data())); + } else if (element.type == blink::WebHTTPBody::Element::TypeFile) { + SetToFile(base::string16(element.filePath)); + } else { + NOTREACHED(); + } +} + +void CefPostDataElementImpl::Get(blink::WebHTTPBody::Element& element) { + base::AutoLock lock_scope(lock_); + + if (type_ == PDE_TYPE_BYTES) { + element.type = blink::WebHTTPBody::Element::TypeData; + element.data.assign( + static_cast(data_.bytes.bytes), data_.bytes.size); + } else if (type_ == PDE_TYPE_FILE) { + element.type = blink::WebHTTPBody::Element::TypeFile; + element.filePath.assign(base::string16(CefString(&data_.filename))); + } else { + NOTREACHED(); + } +} + +void CefPostDataElementImpl::SetReadOnly(bool read_only) { + base::AutoLock lock_scope(lock_); + if (read_only_ == read_only) + return; + + read_only_ = read_only; +} + +void CefPostDataElementImpl::Cleanup() { + if (type_ == PDE_TYPE_EMPTY) + return; + + if (type_ == PDE_TYPE_BYTES) + free(data_.bytes.bytes); + else if (type_ == PDE_TYPE_FILE) + cef_string_clear(&data_.filename); + type_ = PDE_TYPE_EMPTY; + memset(&data_, 0, sizeof(data_)); +} diff --git a/libcef/common/request_impl.h b/libcef/common/request_impl.h new file mode 100644 index 000000000..f9cfdfc46 --- /dev/null +++ b/libcef/common/request_impl.h @@ -0,0 +1,173 @@ +// 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_LIBCEF_COMMON_REQUEST_IMPL_H_ +#define CEF_LIBCEF_COMMON_REQUEST_IMPL_H_ +#pragma once + +#include "include/cef_request.h" + +#include "base/synchronization/lock.h" +#include "third_party/WebKit/public/platform/WebHTTPBody.h" + +namespace net { +class HttpRequestHeaders; +class UploadData; +class UploadDataStream; +class UploadElement; +class UploadElementReader; +class URLRequest; +}; + +namespace blink { +class WebURLRequest; +} + +// Implementation of CefRequest +class CefRequestImpl : public CefRequest { + public: + CefRequestImpl(); + ~CefRequestImpl() {} + + virtual bool IsReadOnly() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual void SetURL(const CefString& url) OVERRIDE; + virtual CefString GetMethod() OVERRIDE; + virtual void SetMethod(const CefString& method) OVERRIDE; + virtual CefRefPtr GetPostData() OVERRIDE; + virtual void SetPostData(CefRefPtr postData) OVERRIDE; + virtual void GetHeaderMap(HeaderMap& headerMap) OVERRIDE; + virtual void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE; + virtual void Set(const CefString& url, + const CefString& method, + CefRefPtr postData, + const HeaderMap& headerMap) OVERRIDE; + virtual int GetFlags() OVERRIDE; + virtual void SetFlags(int flags) OVERRIDE; + virtual CefString GetFirstPartyForCookies() OVERRIDE; + virtual void SetFirstPartyForCookies(const CefString& url) OVERRIDE; + virtual ResourceType GetResourceType() OVERRIDE; + virtual TransitionType GetTransitionType() OVERRIDE; + + // Populate this object from the URLRequest object. + void Set(net::URLRequest* request); + + // Populate the URLRequest object from this object. + void Get(net::URLRequest* request); + + // Populate this object from a WebURLRequest object. + void Set(const blink::WebURLRequest& request); + + // Populate the WebURLRequest object from this object. + void Get(blink::WebURLRequest& request); + + void SetReadOnly(bool read_only); + + static void GetHeaderMap(const net::HttpRequestHeaders& headers, + HeaderMap& map); + static void GetHeaderMap(const blink::WebURLRequest& request, + HeaderMap& map); + static void SetHeaderMap(const HeaderMap& map, + blink::WebURLRequest& request); + + protected: + CefString url_; + CefString method_; + CefRefPtr postdata_; + HeaderMap headermap_; + ResourceType resource_type_; + TransitionType transition_type_; + + // The below members are used by CefURLRequest. + int flags_; + CefString first_party_for_cookies_; + + // True if this object is read-only. + bool read_only_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefRequestImpl); +}; + +// Implementation of CefPostData +class CefPostDataImpl : public CefPostData { + public: + CefPostDataImpl(); + ~CefPostDataImpl() {} + + virtual bool IsReadOnly() OVERRIDE; + virtual size_t GetElementCount() OVERRIDE; + virtual void GetElements(ElementVector& elements) OVERRIDE; + virtual bool RemoveElement(CefRefPtr element) OVERRIDE; + virtual bool AddElement(CefRefPtr element) OVERRIDE; + virtual void RemoveElements(); + + void Set(const net::UploadData& data); + void Set(const net::UploadDataStream& data_stream); + void Get(net::UploadData& data); + net::UploadDataStream* Get(); + void Set(const blink::WebHTTPBody& data); + void Get(blink::WebHTTPBody& data); + + void SetReadOnly(bool read_only); + + protected: + ElementVector elements_; + + // True if this object is read-only. + bool read_only_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefPostDataImpl); +}; + +// Implementation of CefPostDataElement +class CefPostDataElementImpl : public CefPostDataElement { + public: + CefPostDataElementImpl(); + ~CefPostDataElementImpl(); + + virtual bool IsReadOnly() OVERRIDE; + virtual void SetToEmpty() OVERRIDE; + virtual void SetToFile(const CefString& fileName) OVERRIDE; + virtual void SetToBytes(size_t size, const void* bytes) OVERRIDE; + virtual Type GetType() OVERRIDE; + virtual CefString GetFile() OVERRIDE; + virtual size_t GetBytesCount() OVERRIDE; + virtual size_t GetBytes(size_t size, void* bytes) OVERRIDE; + + void* GetBytes() { return data_.bytes.bytes; } + + void Set(const net::UploadElement& element); + void Set(const net::UploadElementReader& element_reader); + void Get(net::UploadElement& element); + net::UploadElementReader* Get(); + void Set(const blink::WebHTTPBody::Element& element); + void Get(blink::WebHTTPBody::Element& element); + + void SetReadOnly(bool read_only); + + protected: + void Cleanup(); + + Type type_; + union { + struct { + void* bytes; + size_t size; + } bytes; + cef_string_t filename; + } data_; + + // True if this object is read-only. + bool read_only_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefPostDataElementImpl); +}; + +#endif // CEF_LIBCEF_COMMON_REQUEST_IMPL_H_ diff --git a/libcef/common/response_impl.cc b/libcef/common/response_impl.cc new file mode 100644 index 000000000..903f007bb --- /dev/null +++ b/libcef/common/response_impl.cc @@ -0,0 +1,205 @@ +// 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 "libcef/common/response_impl.h" + +#include + +#include "base/logging.h" +#include "base/strings/stringprintf.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_response_headers.h" +#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" + + +#define CHECK_READONLY_RETURN_VOID() \ + if (read_only_) { \ + NOTREACHED() << "object is read only"; \ + return; \ + } + + +// CefResponse ---------------------------------------------------------------- + +// static +CefRefPtr CefResponse::Create() { + CefRefPtr response(new CefResponseImpl()); + return response; +} + + +// CefResponseImpl ------------------------------------------------------------ + +CefResponseImpl::CefResponseImpl() + : status_code_(0), + read_only_(false) { +} + +bool CefResponseImpl::IsReadOnly() { + base::AutoLock lock_scope(lock_); + return read_only_; +} + +int CefResponseImpl::GetStatus() { + base::AutoLock lock_scope(lock_); + return status_code_; +} + +void CefResponseImpl::SetStatus(int status) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + status_code_ = status; +} + +CefString CefResponseImpl::GetStatusText() { + base::AutoLock lock_scope(lock_); + return status_text_; +} + +void CefResponseImpl::SetStatusText(const CefString& statusText) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + status_text_ = statusText; +} + +CefString CefResponseImpl::GetMimeType() { + base::AutoLock lock_scope(lock_); + return mime_type_; +} + +void CefResponseImpl::SetMimeType(const CefString& mimeType) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + mime_type_ = mimeType; +} + +CefString CefResponseImpl::GetHeader(const CefString& name) { + base::AutoLock lock_scope(lock_); + + CefString value; + + HeaderMap::const_iterator it = header_map_.find(name); + if (it != header_map_.end()) + value = it->second; + + return value; +} + +void CefResponseImpl::GetHeaderMap(HeaderMap& map) { + base::AutoLock lock_scope(lock_); + map = header_map_; +} + +void CefResponseImpl::SetHeaderMap(const HeaderMap& headerMap) { + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + header_map_ = headerMap; +} + +net::HttpResponseHeaders* CefResponseImpl::GetResponseHeaders() { + base::AutoLock lock_scope(lock_); + + std::string response; + std::string status_text; + bool has_content_type_header = false; + + if (!status_text_.empty()) + status_text = status_text_; + else + status_text = (status_code_ == 200)?"OK":"ERROR"; + + base::SStringPrintf(&response, "HTTP/1.1 %d %s", status_code_, + status_text.c_str()); + if (header_map_.size() > 0) { + for (HeaderMap::const_iterator header = header_map_.begin(); + header != header_map_.end(); + ++header) { + const CefString& key = header->first; + const CefString& value = header->second; + + if (!key.empty()) { + // Delimit with "\0" as required by net::HttpResponseHeaders. + std::string key_str(key); + std::string value_str(value); + base::StringAppendF(&response, "%c%s: %s", '\0', key_str.c_str(), + value_str.c_str()); + + if (!has_content_type_header && + key_str == net::HttpRequestHeaders::kContentType) { + has_content_type_header = true; + } + } + } + } + + if (!has_content_type_header) { + std::string mime_type; + if (!mime_type_.empty()) + mime_type = mime_type_; + else + mime_type = "text/html"; + + base::StringAppendF(&response, "%c%s: %s", '\0', + net::HttpRequestHeaders::kContentType, mime_type.c_str()); + } + + return new net::HttpResponseHeaders(response); +} + +void CefResponseImpl::SetResponseHeaders( + const net::HttpResponseHeaders& headers) { + base::AutoLock lock_scope(lock_); + + header_map_.empty(); + + void* iter = NULL; + std::string name, value; + while (headers.EnumerateHeaderLines(&iter, &name, &value)) + header_map_.insert(std::make_pair(name, value)); + + status_code_ = headers.response_code(); + status_text_ = headers.GetStatusText(); + + std::string mime_type; + if (headers.GetMimeType(&mime_type)) + mime_type_ = mime_type; +} + +void CefResponseImpl::Set(const blink::WebURLResponse& response) { + DCHECK(!response.isNull()); + + base::AutoLock lock_scope(lock_); + CHECK_READONLY_RETURN_VOID(); + + blink::WebString str; + status_code_ = response.httpStatusCode(); + str = response.httpStatusText(); + status_text_ = CefString(str); + str = response.mimeType(); + mime_type_ = CefString(str); + + class HeaderVisitor : public blink::WebHTTPHeaderVisitor { + public: + explicit HeaderVisitor(HeaderMap* map) : map_(map) {} + + virtual void visitHeader(const blink::WebString& name, + const blink::WebString& value) { + map_->insert(std::make_pair(base::string16(name), + base::string16(value))); + } + + private: + HeaderMap* map_; + }; + + HeaderVisitor visitor(&header_map_); + response.visitHTTPHeaderFields(&visitor); +} + +void CefResponseImpl::SetReadOnly(bool read_only) { + base::AutoLock lock_scope(lock_); + read_only_ = read_only; +} diff --git a/libcef/common/response_impl.h b/libcef/common/response_impl.h new file mode 100644 index 000000000..084cabce3 --- /dev/null +++ b/libcef/common/response_impl.h @@ -0,0 +1,58 @@ +// 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_LIBCEF_COMMON_RESPONSE_IMPL_H_ +#define CEF_LIBCEF_COMMON_RESPONSE_IMPL_H_ +#pragma once + +#include "include/cef_response.h" + +#include "base/synchronization/lock.h" + +namespace net { +class HttpResponseHeaders; +} + +namespace blink { +class WebURLResponse; +} + +// Implementation of CefResponse. +class CefResponseImpl : public CefResponse { + public: + CefResponseImpl(); + ~CefResponseImpl() {} + + // CefResponse methods. + virtual bool IsReadOnly() OVERRIDE; + virtual int GetStatus() OVERRIDE; + virtual void SetStatus(int status) OVERRIDE; + virtual CefString GetStatusText() OVERRIDE; + virtual void SetStatusText(const CefString& statusText) OVERRIDE; + virtual CefString GetMimeType() OVERRIDE; + virtual void SetMimeType(const CefString& mimeType) OVERRIDE; + virtual CefString GetHeader(const CefString& name) OVERRIDE; + virtual void GetHeaderMap(HeaderMap& headerMap) OVERRIDE; + virtual void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE; + + net::HttpResponseHeaders* GetResponseHeaders(); + void SetResponseHeaders(const net::HttpResponseHeaders& headers); + + void Set(const blink::WebURLResponse& response); + + void SetReadOnly(bool read_only); + + protected: + int status_code_; + CefString status_text_; + CefString mime_type_; + HeaderMap header_map_; + bool read_only_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefResponseImpl); +}; + +#endif // CEF_LIBCEF_COMMON_RESPONSE_IMPL_H_ diff --git a/libcef/common/response_manager.cc b/libcef/common/response_manager.cc new file mode 100644 index 000000000..b7f6efcb7 --- /dev/null +++ b/libcef/common/response_manager.cc @@ -0,0 +1,58 @@ +// 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 "libcef/common/response_manager.h" +#include "libcef/common/cef_messages.h" + +#include "base/logging.h" + +CefResponseManager::CefResponseManager() + : next_request_id_(0) { +} + +int CefResponseManager::GetNextRequestId() { + DCHECK(CalledOnValidThread()); + return ++next_request_id_; +} + +int CefResponseManager::RegisterHandler(CefRefPtr handler) { + DCHECK(CalledOnValidThread()); + int request_id = GetNextRequestId(); + TRACE_EVENT_ASYNC_BEGIN1("libcef", "CefResponseManager::Handler", request_id, "request_id", request_id); + handlers_.insert(std::make_pair(request_id, handler)); + return request_id; +} + +bool CefResponseManager::RunHandler(const Cef_Response_Params& params) { + DCHECK(CalledOnValidThread()); + DCHECK_GT(params.request_id, 0); + HandlerMap::iterator it = handlers_.find(params.request_id); + if (it != handlers_.end()) { + TRACE_EVENT0("libcef", "CefResponseManager::RunHandler"); + it->second->OnResponse(params); + handlers_.erase(it); + TRACE_EVENT_ASYNC_END1("libcef", "CefResponseManager::Handler", params.request_id, "success", 1); + return true; + } + TRACE_EVENT_ASYNC_END1("libcef", "CefResponseManager::Handler", params.request_id, "success", 0); + return false; +} + +void CefResponseManager::RegisterAckHandler(int request_id, + CefRefPtr handler) { + DCHECK(CalledOnValidThread()); + ack_handlers_.insert(std::make_pair(request_id, handler)); +} + +bool CefResponseManager::RunAckHandler(int request_id) { + DCHECK(CalledOnValidThread()); + DCHECK_GT(request_id, 0); + AckHandlerMap::iterator it = ack_handlers_.find(request_id); + if (it != ack_handlers_.end()) { + it->second->OnResponseAck(); + ack_handlers_.erase(it); + return true; + } + return false; +} diff --git a/libcef/common/response_manager.h b/libcef/common/response_manager.h new file mode 100644 index 000000000..ee383cc83 --- /dev/null +++ b/libcef/common/response_manager.h @@ -0,0 +1,62 @@ +// 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_LIBCEF_COMMON_RESPONSE_MANAGER_H_ +#define CEF_LIBCEF_COMMON_RESPONSE_MANAGER_H_ +#pragma once + +#include +#include "include/cef_base.h" +#include "base/threading/non_thread_safe.h" + +struct Cef_Response_Params; + +// This class is not thread-safe. +class CefResponseManager : base::NonThreadSafe { + public: + // Used for handling response messages. + class Handler : public virtual CefBase { + public: + virtual void OnResponse(const Cef_Response_Params& params) =0; + }; + + // Used for handling response ack messages. + class AckHandler : public virtual CefBase { + public: + virtual void OnResponseAck() =0; + }; + + CefResponseManager(); + + // Returns the next unique request id. + int GetNextRequestId(); + + // Register a response handler and return the unique request id. + int RegisterHandler(CefRefPtr handler); + + // Run the response handler for the specified request id. Returns true if a + // handler was run. + bool RunHandler(const Cef_Response_Params& params); + + // Register a response ack handler for the specified request id. + void RegisterAckHandler(int request_id, CefRefPtr handler); + + // Run the response ack handler for the specified request id. Returns true if + // a handler was run. + bool RunAckHandler(int request_id); + + private: + // Used for generating unique request ids. + int next_request_id_; + + // Map of unique request ids to Handler references. + typedef std::map > HandlerMap; + HandlerMap handlers_; + + // Map of unique request ids to AckHandler references. + typedef std::map > AckHandlerMap; + AckHandlerMap ack_handlers_; +}; + +#endif // CEF_LIBCEF_COMMON_RESPONSE_MANAGER_H_ diff --git a/libcef/common/scheme_registrar_impl.cc b/libcef/common/scheme_registrar_impl.cc new file mode 100644 index 000000000..26e841742 --- /dev/null +++ b/libcef/common/scheme_registrar_impl.cc @@ -0,0 +1,67 @@ +// 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 "libcef/common/scheme_registrar_impl.h" + +#include + +#include "libcef/common/content_client.h" + +#include "base/bind.h" +#include "base/logging.h" + +CefSchemeRegistrarImpl::CefSchemeRegistrarImpl() + : supported_thread_id_(base::PlatformThread::CurrentId()) { +} + +bool CefSchemeRegistrarImpl::AddCustomScheme( + const CefString& scheme_name, + bool is_standard, + bool is_local, + bool is_display_isolated) { + if (!VerifyContext()) + return false; + + const std::string& scheme = scheme_name; + + if (is_standard) + standard_schemes_.push_back(scheme); + + CefContentClient::SchemeInfo scheme_info = { + scheme, is_standard, is_local, is_display_isolated}; + CefContentClient::Get()->AddCustomScheme(scheme_info); + + return true; +} + +void CefSchemeRegistrarImpl::GetStandardSchemes( + std::vector* standard_schemes) { + if (!VerifyContext()) + return; + + if (standard_schemes_.empty()) + return; + + standard_schemes->insert(standard_schemes->end(), standard_schemes_.begin(), + standard_schemes_.end()); +} + +bool CefSchemeRegistrarImpl::VerifyRefCount() { + return HasOneRef(); +} + +void CefSchemeRegistrarImpl::Detach() { + if (VerifyContext()) + supported_thread_id_ = base::kInvalidThreadId; +} + +bool CefSchemeRegistrarImpl::VerifyContext() { + if (base::PlatformThread::CurrentId() != supported_thread_id_) { + // This object should only be accessed from the thread that created it. + NOTREACHED(); + return false; + } + + return true; +} diff --git a/libcef/common/scheme_registrar_impl.h b/libcef/common/scheme_registrar_impl.h new file mode 100644 index 000000000..ad7d01186 --- /dev/null +++ b/libcef/common/scheme_registrar_impl.h @@ -0,0 +1,46 @@ +// 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_LIBCEF_COMMON_SCHEME_REGISTRAR_IMPL_H_ +#define CEF_LIBCEF_COMMON_SCHEME_REGISTRAR_IMPL_H_ +#pragma once + +#include +#include + +#include "include/cef_scheme.h" + +#include "base/threading/platform_thread.h" + +class CefSchemeRegistrarImpl : public CefSchemeRegistrar { + public: + CefSchemeRegistrarImpl(); + + // CefSchemeRegistrar methods. + virtual bool AddCustomScheme(const CefString& scheme_name, + bool is_standard, + bool is_local, + bool is_display_isolated) OVERRIDE; + + void GetStandardSchemes(std::vector* standard_schemes); + + // Verify that only a single reference exists to all CefSchemeRegistrarImpl + // objects. + bool VerifyRefCount(); + + void Detach(); + + private: + // Verify that the object is being accessed from the correct thread. + bool VerifyContext(); + + base::PlatformThreadId supported_thread_id_; + + std::vector standard_schemes_; + + IMPLEMENT_REFCOUNTING(CefSchemeRegistrarImpl); + DISALLOW_COPY_AND_ASSIGN(CefSchemeRegistrarImpl); +}; + +#endif // CEF_LIBCEF_COMMON_SCHEME_REGISTRAR_IMPL_H_ diff --git a/libcef/common/scheme_registration.cc b/libcef/common/scheme_registration.cc new file mode 100644 index 000000000..fa505294e --- /dev/null +++ b/libcef/common/scheme_registration.cc @@ -0,0 +1,68 @@ +// 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 "libcef/common/scheme_registration.h" +#include "libcef/common/content_client.h" + +#include "content/public/common/url_constants.h" +#include "url/url_constants.h" + +namespace scheme { + +void AddInternalSchemes(std::vector* standard_schemes) { + static CefContentClient::SchemeInfo schemes[] = { + { content::kChromeUIScheme, true, true, true }, + { content::kChromeDevToolsScheme, true, false, true } + }; + + CefContentClient* client = CefContentClient::Get(); + for (size_t i = 0; i < sizeof(schemes) / sizeof(schemes[0]); ++i) { + if (schemes[0].is_standard) + standard_schemes->push_back(schemes[i].scheme_name); + client->AddCustomScheme(schemes[i]); + } +} + +bool IsInternalHandledScheme(const std::string& scheme) { + static const char* schemes[] = { + url::kBlobScheme, + content::kChromeDevToolsScheme, + content::kChromeUIScheme, + url::kDataScheme, + url::kFileScheme, + url::kFileSystemScheme, + }; + + for (size_t i = 0; i < sizeof(schemes) / sizeof(schemes[0]); ++i) { + if (scheme == schemes[i]) + return true; + } + + return false; +} + +bool IsInternalProtectedScheme(const std::string& scheme) { + // Some of these values originate from StoragePartitionImplMap::Get() in + // content/browser/storage_partition_impl_map.cc and are modified by + // InstallInternalProtectedHandlers(). + static const char* schemes[] = { + url::kBlobScheme, + content::kChromeUIScheme, + url::kDataScheme, + url::kFileScheme, + url::kFileSystemScheme, +#if !defined(DISABLE_FTP_SUPPORT) + url::kFtpScheme, +#endif + }; + + for (size_t i = 0; i < sizeof(schemes) / sizeof(schemes[0]); ++i) { + if (scheme == schemes[i]) + return true; + } + + return false; +} + +} // namespace scheme diff --git a/libcef/common/scheme_registration.h b/libcef/common/scheme_registration.h new file mode 100644 index 000000000..7252f24d8 --- /dev/null +++ b/libcef/common/scheme_registration.h @@ -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. + +#ifndef CEF_LIBCEF_COMMON_SCHEME_REGISTRATION_H_ +#define CEF_LIBCEF_COMMON_SCHEME_REGISTRATION_H_ +#pragma once + +#include +#include + +namespace scheme { + +// Add internal schemes. +void AddInternalSchemes(std::vector* standard_schemes); + +// Returns true if the specified |scheme| is handled internally. +bool IsInternalHandledScheme(const std::string& scheme); + +// Returns true if the specified |scheme| is handled internally and should not +// be explicitly registered or unregistered with the URLRequestJobFactory. A +// registered handler for one of these schemes (like "chrome") may still be +// triggered via chaining from an existing ProtocolHandler. |scheme| should +// always be a lower-case string. +bool IsInternalProtectedScheme(const std::string& scheme); + +} // namespace scheme + +#endif // CEF_LIBCEF_COMMON_SCHEME_REGISTRATION_H_ diff --git a/libcef/common/string_list_impl.cc b/libcef/common/string_list_impl.cc new file mode 100644 index 000000000..8db72cbeb --- /dev/null +++ b/libcef/common/string_list_impl.cc @@ -0,0 +1,57 @@ +// 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. + +#include +#include "include/internal/cef_string_list.h" +#include "base/logging.h" + +typedef std::vector StringList; + +CEF_EXPORT cef_string_list_t cef_string_list_alloc() { + return new StringList; +} + +CEF_EXPORT int cef_string_list_size(cef_string_list_t list) { + DCHECK(list); + StringList* impl = reinterpret_cast(list); + return impl->size(); +} + +CEF_EXPORT int cef_string_list_value(cef_string_list_t list, int index, + cef_string_t* value) { + DCHECK(list); + DCHECK(value); + StringList* impl = reinterpret_cast(list); + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast(impl->size())); + if (index < 0 || index >= static_cast(impl->size())) + return false; + const CefString& str = (*impl)[index]; + return cef_string_copy(str.c_str(), str.length(), value); +} + +CEF_EXPORT void cef_string_list_append(cef_string_list_t list, + const cef_string_t* value) { + DCHECK(list); + StringList* impl = reinterpret_cast(list); + impl->push_back(CefString(value)); +} + +CEF_EXPORT void cef_string_list_clear(cef_string_list_t list) { + DCHECK(list); + StringList* impl = reinterpret_cast(list); + impl->clear(); +} + +CEF_EXPORT void cef_string_list_free(cef_string_list_t list) { + DCHECK(list); + StringList* impl = reinterpret_cast(list); + delete impl; +} + +CEF_EXPORT cef_string_list_t cef_string_list_copy(cef_string_list_t list) { + DCHECK(list); + StringList* impl = reinterpret_cast(list); + return new StringList(*impl); +} diff --git a/libcef/common/string_map_impl.cc b/libcef/common/string_map_impl.cc new file mode 100644 index 000000000..9538ab05e --- /dev/null +++ b/libcef/common/string_map_impl.cc @@ -0,0 +1,92 @@ +// 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. + +#include +#include "include/internal/cef_string_map.h" +#include "base/logging.h" + +typedef std::map StringMap; + +CEF_EXPORT cef_string_map_t cef_string_map_alloc() { + return new StringMap; +} + +CEF_EXPORT int cef_string_map_size(cef_string_map_t map) { + DCHECK(map); + StringMap* impl = reinterpret_cast(map); + return impl->size(); +} + +CEF_EXPORT int cef_string_map_find(cef_string_map_t map, + const cef_string_t* key, + cef_string_t* value) { + DCHECK(map); + DCHECK(value); + StringMap* impl = reinterpret_cast(map); + StringMap::const_iterator it = impl->find(CefString(key)); + if (it == impl->end()) + return 0; + + const CefString& val = it->second; + return cef_string_set(val.c_str(), val.length(), value, true); +} + +CEF_EXPORT int cef_string_map_key(cef_string_map_t map, int index, + cef_string_t* key) { + DCHECK(map); + DCHECK(key); + StringMap* impl = reinterpret_cast(map); + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast(impl->size())); + if (index < 0 || index >= static_cast(impl->size())) + return 0; + + StringMap::const_iterator it = impl->begin(); + for (int ct = 0; it != impl->end(); ++it, ct++) { + if (ct == index) + return cef_string_set(it->first.c_str(), it->first.length(), key, true); + } + return 0; +} + +CEF_EXPORT int cef_string_map_value(cef_string_map_t map, int index, + cef_string_t* value) { + DCHECK(map); + DCHECK(value); + StringMap* impl = reinterpret_cast(map); + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast(impl->size())); + if (index < 0 || index >= static_cast(impl->size())) + return 0; + + StringMap::const_iterator it = impl->begin(); + for (int ct = 0; it != impl->end(); ++it, ct++) { + if (ct == index) { + return cef_string_set(it->second.c_str(), it->second.length(), value, + true); + } + } + return 0; +} + +CEF_EXPORT int cef_string_map_append(cef_string_map_t map, + const cef_string_t* key, + const cef_string_t* value) { + DCHECK(map); + StringMap* impl = reinterpret_cast(map); + impl->insert(std::make_pair(CefString(key), CefString(value))); + return 1; +} + +CEF_EXPORT void cef_string_map_clear(cef_string_map_t map) { + DCHECK(map); + StringMap* impl = reinterpret_cast(map); + impl->clear(); +} + +CEF_EXPORT void cef_string_map_free(cef_string_map_t map) { + DCHECK(map); + StringMap* impl = reinterpret_cast(map); + delete impl; +} diff --git a/libcef/common/string_multimap_impl.cc b/libcef/common/string_multimap_impl.cc new file mode 100644 index 000000000..594ca90dd --- /dev/null +++ b/libcef/common/string_multimap_impl.cc @@ -0,0 +1,116 @@ +// 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 +#include "include/internal/cef_string_multimap.h" +#include "base/logging.h" + +typedef std::multimap StringMultimap; + +CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc() { + return new StringMultimap; +} + +CEF_EXPORT int cef_string_multimap_size(cef_string_multimap_t map) { + DCHECK(map); + StringMultimap* impl = reinterpret_cast(map); + return impl->size(); +} + +CEF_EXPORT int cef_string_multimap_find_count(cef_string_multimap_t map, + const cef_string_t* key) { + DCHECK(map); + DCHECK(key); + StringMultimap* impl = reinterpret_cast(map); + return impl->count(CefString(key)); +} + +CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map, + const cef_string_t* key, + int value_index, + cef_string_t* value) { + DCHECK(map); + DCHECK(key); + DCHECK(value); + + StringMultimap* impl = reinterpret_cast(map); + CefString key_str(key); + + DCHECK_GE(value_index, 0); + DCHECK_LT(value_index, static_cast(impl->count(key_str))); + if (value_index < 0 || value_index >= static_cast(impl->count(key_str))) + return 0; + + std::pair range_it = + impl->equal_range(key_str); + + int count = value_index; + while (count-- && range_it.first != range_it.second) + range_it.first++; + + if (range_it.first == range_it.second) + return 0; + + const CefString& val = range_it.first->second; + return cef_string_set(val.c_str(), val.length(), value, true); +} + +CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map, int index, + cef_string_t* key) { + DCHECK(map); + DCHECK(key); + StringMultimap* impl = reinterpret_cast(map); + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast(impl->size())); + if (index < 0 || index >= static_cast(impl->size())) + return 0; + + StringMultimap::const_iterator it = impl->begin(); + for (int ct = 0; it != impl->end(); ++it, ct++) { + if (ct == index) + return cef_string_set(it->first.c_str(), it->first.length(), key, true); + } + return 0; +} + +CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map, int index, + cef_string_t* value) { + DCHECK(map); + DCHECK(value); + StringMultimap* impl = reinterpret_cast(map); + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast(impl->size())); + if (index < 0 || index >= static_cast(impl->size())) + return 0; + + StringMultimap::const_iterator it = impl->begin(); + for (int ct = 0; it != impl->end(); ++it, ct++) { + if (ct == index) { + return cef_string_set(it->second.c_str(), it->second.length(), value, + true); + } + } + return 0; +} + +CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map, + const cef_string_t* key, + const cef_string_t* value) { + DCHECK(map); + StringMultimap* impl = reinterpret_cast(map); + impl->insert(std::make_pair(CefString(key), CefString(value))); + return 1; +} + +CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map) { + DCHECK(map); + StringMultimap* impl = reinterpret_cast(map); + impl->clear(); +} + +CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map) { + DCHECK(map); + StringMultimap* impl = reinterpret_cast(map); + delete impl; +} diff --git a/libcef/common/string_types_impl.cc b/libcef/common/string_types_impl.cc new file mode 100644 index 000000000..f4de421e4 --- /dev/null +++ b/libcef/common/string_types_impl.cc @@ -0,0 +1,270 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "include/internal/cef_string_types.h" +#include +#include "base/logging.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" + +namespace { + +void string_wide_dtor(wchar_t* str) { + delete [] str; +} + +void string_utf8_dtor(char* str) { + delete [] str; +} + +void string_utf16_dtor(char16* str) { + delete [] str; +} + +} // namespace + +CEF_EXPORT int cef_string_wide_set(const wchar_t* src, size_t src_len, + cef_string_wide_t* output, int copy) { + cef_string_wide_clear(output); + + if (copy) { + if (src && src_len > 0) { + output->str = new wchar_t[src_len+1]; + if (!output->str) + return 0; + + memcpy(output->str, src, src_len * sizeof(wchar_t)); + output->str[src_len] = 0; + output->length = src_len; + output->dtor = string_wide_dtor; + } + } else { + output->str = const_cast(src); + output->length = src_len; + output->dtor = NULL; + } + return 1; +} + +CEF_EXPORT int cef_string_utf8_set(const char* src, size_t src_len, + cef_string_utf8_t* output, int copy) { + cef_string_utf8_clear(output); + if (copy) { + if (src && src_len > 0) { + output->str = new char[src_len+1]; + if (!output->str) + return 0; + + memcpy(output->str, src, src_len * sizeof(char)); + output->str[src_len] = 0; + output->length = src_len; + output->dtor = string_utf8_dtor; + } + } else { + output->str = const_cast(src); + output->length = src_len; + output->dtor = NULL; + } + return 1; +} + +CEF_EXPORT int cef_string_utf16_set(const char16* src, size_t src_len, + cef_string_utf16_t* output, int copy) { + cef_string_utf16_clear(output); + + if (copy) { + if (src && src_len > 0) { + output->str = new char16[src_len+1]; + if (!output->str) + return 0; + + memcpy(output->str, src, src_len * sizeof(char16)); + output->str[src_len] = 0; + output->length = src_len; + output->dtor = string_utf16_dtor; + } + } else { + output->str = const_cast(src); + output->length = src_len; + output->dtor = NULL; + } + return 1; +} + +CEF_EXPORT void cef_string_wide_clear(cef_string_wide_t* str) { + DCHECK(str != NULL); + if (str->dtor && str->str) + str->dtor(str->str); + + str->str = NULL; + str->length = 0; + str->dtor = NULL; +} + +CEF_EXPORT void cef_string_utf8_clear(cef_string_utf8_t* str) { + DCHECK(str != NULL); + if (str->dtor && str->str) + str->dtor(str->str); + + str->str = NULL; + str->length = 0; + str->dtor = NULL; +} + +CEF_EXPORT void cef_string_utf16_clear(cef_string_utf16_t* str) { + DCHECK(str != NULL); + if (str->dtor && str->str) + str->dtor(str->str); + + str->str = NULL; + str->length = 0; + str->dtor = NULL; +} + +CEF_EXPORT int cef_string_wide_cmp(const cef_string_wide_t* str1, + const cef_string_wide_t* str2) { + if (str1->length == 0 && str2->length == 0) + return 0; + int r = wcsncmp(str1->str, str2->str, std::min(str1->length, str2->length)); + if (r == 0) { + if (str1->length > str2->length) + return 1; + else if (str1->length < str2->length) + return -1; + } + return r; +} + +CEF_EXPORT int cef_string_utf8_cmp(const cef_string_utf8_t* str1, + const cef_string_utf8_t* str2) { + if (str1->length == 0 && str2->length == 0) + return 0; + int r = strncmp(str1->str, str2->str, std::min(str1->length, str2->length)); + if (r == 0) { + if (str1->length > str2->length) + return 1; + else if (str1->length < str2->length) + return -1; + } + return r; +} + +CEF_EXPORT int cef_string_utf16_cmp(const cef_string_utf16_t* str1, + const cef_string_utf16_t* str2) { + if (str1->length == 0 && str2->length == 0) + return 0; +#if defined(WCHAR_T_IS_UTF32) + int r = base::c16memcmp(str1->str, str2->str, std::min(str1->length, + str2->length)); +#else + int r = wcsncmp(str1->str, str2->str, std::min(str1->length, str2->length)); +#endif + if (r == 0) { + if (str1->length > str2->length) + return 1; + else if (str1->length < str2->length) + return -1; + } + return r; +} + +CEF_EXPORT int cef_string_wide_to_utf8(const wchar_t* src, size_t src_len, + cef_string_utf8_t* output) { + std::string str; + bool ret = base::WideToUTF8(src, src_len, &str); + if (!cef_string_utf8_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_utf8_to_wide(const char* src, size_t src_len, + cef_string_wide_t* output) { + std::wstring str; + bool ret = base::UTF8ToWide(src, src_len, &str); + if (!cef_string_wide_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_wide_to_utf16(const wchar_t* src, size_t src_len, + cef_string_utf16_t* output) { + base::string16 str; + bool ret = base::WideToUTF16(src, src_len, &str); + if (!cef_string_utf16_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_utf16_to_wide(const char16* src, size_t src_len, + cef_string_wide_t* output) { + std::wstring str; + bool ret = base::UTF16ToWide(src, src_len, &str); + if (!cef_string_wide_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_utf8_to_utf16(const char* src, size_t src_len, + cef_string_utf16_t* output) { + base::string16 str; + bool ret = base::UTF8ToUTF16(src, src_len, &str); + if (!cef_string_utf16_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_utf16_to_utf8(const char16* src, size_t src_len, + cef_string_utf8_t* output) { + std::string str; + bool ret = base::UTF16ToUTF8(src, src_len, &str); + if (!cef_string_utf8_set(str.c_str(), str.length(), output, true)) + return false; + return ret; +} + +CEF_EXPORT int cef_string_ascii_to_wide(const char* src, size_t src_len, + cef_string_wide_t* output) { + std::wstring str = base::ASCIIToWide(std::string(src, src_len)); + return cef_string_wide_set(str.c_str(), str.length(), output, true); +} + +CEF_EXPORT int cef_string_ascii_to_utf16(const char* src, size_t src_len, + cef_string_utf16_t* output) { + base::string16 str = base::ASCIIToUTF16(std::string(src, src_len)); + return cef_string_utf16_set(str.c_str(), str.length(), output, true); +} + +CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc() { + cef_string_wide_t* s = new cef_string_wide_t; + memset(s, 0, sizeof(cef_string_wide_t)); + return s; +} + +CEF_EXPORT cef_string_userfree_utf8_t cef_string_userfree_utf8_alloc() { + cef_string_utf8_t* s = new cef_string_utf8_t; + memset(s, 0, sizeof(cef_string_utf8_t)); + return s; +} + +CEF_EXPORT cef_string_userfree_utf16_t cef_string_userfree_utf16_alloc() { + cef_string_utf16_t* s = new cef_string_utf16_t; + memset(s, 0, sizeof(cef_string_utf16_t)); + return s; +} + +CEF_EXPORT void cef_string_userfree_wide_free(cef_string_userfree_wide_t str) { + cef_string_wide_clear(str); + delete str; +} + +CEF_EXPORT void cef_string_userfree_utf8_free(cef_string_userfree_utf8_t str) { + cef_string_utf8_clear(str); + delete str; +} + +CEF_EXPORT void cef_string_userfree_utf16_free( + cef_string_userfree_utf16_t str) { + cef_string_utf16_clear(str); + delete str; +} diff --git a/libcef/common/task_impl.cc b/libcef/common/task_impl.cc new file mode 100644 index 000000000..300ae8a43 --- /dev/null +++ b/libcef/common/task_impl.cc @@ -0,0 +1,38 @@ +// 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 "include/cef_task.h" +#include "libcef/common/task_runner_impl.h" + +#include "base/bind.h" +#include "base/location.h" + +bool CefCurrentlyOn(CefThreadId threadId) { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetTaskRunner(threadId); + if (task_runner.get()) + return task_runner->RunsTasksOnCurrentThread(); + return false; +} + +bool CefPostTask(CefThreadId threadId, CefRefPtr task) { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetTaskRunner(threadId); + if (task_runner.get()) { + return task_runner->PostTask(FROM_HERE, + base::Bind(&CefTask::Execute, task)); + } + return false; +} + +bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr task, int64 delay_ms) { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetTaskRunner(threadId); + if (task_runner.get()) { + return task_runner->PostDelayedTask(FROM_HERE, + base::Bind(&CefTask::Execute, task), + base::TimeDelta::FromMilliseconds(delay_ms)); + } + return false; +} diff --git a/libcef/common/task_runner_impl.cc b/libcef/common/task_runner_impl.cc new file mode 100644 index 000000000..771afae4a --- /dev/null +++ b/libcef/common/task_runner_impl.cc @@ -0,0 +1,147 @@ +// 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 "libcef/common/task_runner_impl.h" +#include "libcef/common/content_client.h" +#include "libcef/renderer/content_renderer_client.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_proxy.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; + +// CefTaskRunner + +// static +CefRefPtr CefTaskRunner::GetForCurrentThread() { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetCurrentTaskRunner(); + if (task_runner.get()) + return new CefTaskRunnerImpl(task_runner); + return NULL; +} + +// static +CefRefPtr CefTaskRunner::GetForThread(CefThreadId threadId) { + scoped_refptr task_runner = + CefTaskRunnerImpl::GetTaskRunner(threadId); + if (task_runner.get()) + return new CefTaskRunnerImpl(task_runner); + + LOG(WARNING) << "Invalid thread id " << threadId; + return NULL; +} + + +// CefTaskRunnerImpl + +CefTaskRunnerImpl::CefTaskRunnerImpl( + scoped_refptr task_runner) + : task_runner_(task_runner) { + DCHECK(task_runner_.get()); +} + +// static +scoped_refptr + CefTaskRunnerImpl::GetTaskRunner(CefThreadId threadId) { + // Render process. + if (threadId == TID_RENDERER) { + CefContentRendererClient* client = CefContentRendererClient::Get(); + if (client) + return client->render_task_runner(); + return NULL; + } + + // Browser process. + int id = -1; + switch (threadId) { + case TID_UI: + id = BrowserThread::UI; + break; + case TID_DB: + id = BrowserThread::DB; + break; + case TID_FILE: + id = BrowserThread::FILE; + break; + case TID_FILE_USER_BLOCKING: + id = BrowserThread::FILE_USER_BLOCKING; + break; + case TID_PROCESS_LAUNCHER: + id = BrowserThread::PROCESS_LAUNCHER; + break; + case TID_CACHE: + id = BrowserThread::CACHE; + break; + case TID_IO: + id = BrowserThread::IO; + break; + default: + break; + }; + + if (id >= 0 && CefContentClient::Get()->browser() && + BrowserThread::IsMessageLoopValid(static_cast(id))) { + // Don't use BrowserThread::GetMessageLoopProxyForThread because it returns + // a new MessageLoopProxy object for each call and makes pointer equality + // testing impossible. + base::MessageLoop* message_loop = + BrowserThread::UnsafeGetMessageLoopForThread( + static_cast(id)); + if (message_loop) + return message_loop->message_loop_proxy(); + } + + return NULL; +} + +// static +scoped_refptr + CefTaskRunnerImpl::GetCurrentTaskRunner() { + scoped_refptr task_runner; + + // Check for a MessageLoopProxy. This covers all of the named browser and + // render process threads, plus a few extra. + task_runner = base::MessageLoopProxy::current(); + + if (!task_runner.get()) { + // Check for a WebWorker thread. + CefContentRendererClient* client = CefContentRendererClient::Get(); + if (client) + task_runner = client->GetCurrentTaskRunner(); + } + + return task_runner; +} + +bool CefTaskRunnerImpl::IsSame(CefRefPtr that) { + CefTaskRunnerImpl* impl = static_cast(that.get()); + return (impl && task_runner_ == impl->task_runner_); +} + +bool CefTaskRunnerImpl::BelongsToCurrentThread() { + return task_runner_->RunsTasksOnCurrentThread(); +} + +bool CefTaskRunnerImpl::BelongsToThread(CefThreadId threadId) { + scoped_refptr task_runner = + GetTaskRunner(threadId); + return (task_runner_ == task_runner); +} + +bool CefTaskRunnerImpl::PostTask(CefRefPtr task) { + return task_runner_->PostTask(FROM_HERE, + base::Bind(&CefTask::Execute, task)); +} + +bool CefTaskRunnerImpl::PostDelayedTask(CefRefPtr task, + int64 delay_ms) { + return task_runner_->PostDelayedTask(FROM_HERE, + base::Bind(&CefTask::Execute, task), + base::TimeDelta::FromMilliseconds(delay_ms)); +} diff --git a/libcef/common/task_runner_impl.h b/libcef/common/task_runner_impl.h new file mode 100644 index 000000000..709476221 --- /dev/null +++ b/libcef/common/task_runner_impl.h @@ -0,0 +1,38 @@ +// 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_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_ +#define CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_ +#pragma once + +#include "include/cef_task.h" +#include "base/sequenced_task_runner.h" + +class CefTaskRunnerImpl : public CefTaskRunner { + public: + explicit CefTaskRunnerImpl( + scoped_refptr task_runner); + + // Returns the task runner associated with |threadId|. + static scoped_refptr + GetTaskRunner(CefThreadId threadId); + // Returns the current task runner. + static scoped_refptr GetCurrentTaskRunner(); + + // CefTaskRunner methods: + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool BelongsToCurrentThread() OVERRIDE; + virtual bool BelongsToThread(CefThreadId threadId) OVERRIDE; + virtual bool PostTask(CefRefPtr task) OVERRIDE; + virtual bool PostDelayedTask(CefRefPtr task, + int64 delay_ms) OVERRIDE; + + private: + scoped_refptr task_runner_; + + IMPLEMENT_REFCOUNTING(CefTaskRunnerImpl); + DISALLOW_COPY_AND_ASSIGN(CefTaskRunnerImpl); +}; + +#endif // CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_ diff --git a/libcef/common/time_impl.cc b/libcef/common/time_impl.cc new file mode 100644 index 000000000..68100b0b3 --- /dev/null +++ b/libcef/common/time_impl.cc @@ -0,0 +1,93 @@ +// 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 "libcef/common/time_util.h" + +void cef_time_to_basetime(const cef_time_t& cef_time, base::Time& time) { + base::Time::Exploded exploded; + exploded.year = cef_time.year; + exploded.month = cef_time.month; + exploded.day_of_week = cef_time.day_of_week; + exploded.day_of_month = cef_time.day_of_month; + exploded.hour = cef_time.hour; + exploded.minute = cef_time.minute; + exploded.second = cef_time.second; + exploded.millisecond = cef_time.millisecond; + time = base::Time::FromUTCExploded(exploded); +} + +void cef_time_from_basetime(const base::Time& time, cef_time_t& cef_time) { + base::Time::Exploded exploded; + time.UTCExplode(&exploded); + cef_time.year = exploded.year; + cef_time.month = exploded.month; + cef_time.day_of_week = exploded.day_of_week; + cef_time.day_of_month = exploded.day_of_month; + cef_time.hour = exploded.hour; + cef_time.minute = exploded.minute; + cef_time.second = exploded.second; + cef_time.millisecond = exploded.millisecond; +} + +CEF_EXPORT int cef_time_to_timet(const cef_time_t* cef_time, time_t* time) { + if (!cef_time || !time) + return 0; + + base::Time base_time; + cef_time_to_basetime(*cef_time, base_time); + *time = base_time.ToTimeT(); + return 1; +} + +CEF_EXPORT int cef_time_from_timet(time_t time, cef_time_t* cef_time) { + if (!cef_time) + return 0; + + base::Time base_time = base::Time::FromTimeT(time); + cef_time_from_basetime(base_time, *cef_time); + return 1; +} + +CEF_EXPORT int cef_time_to_doublet(const cef_time_t* cef_time, double* time) { + if (!cef_time || !time) + return 0; + + base::Time base_time; + cef_time_to_basetime(*cef_time, base_time); + *time = base_time.ToDoubleT(); + return 1; +} + +CEF_EXPORT int cef_time_from_doublet(double time, cef_time_t* cef_time) { + if (!cef_time) + return 0; + + base::Time base_time = base::Time::FromDoubleT(time); + cef_time_from_basetime(base_time, *cef_time); + return 1; +} + +CEF_EXPORT int cef_time_now(cef_time_t* cef_time) { + if (!cef_time) + return 0; + + base::Time base_time = base::Time::Now(); + cef_time_from_basetime(base_time, *cef_time); + return 1; +} + +CEF_EXPORT int cef_time_delta(const cef_time_t* cef_time1, + const cef_time_t* cef_time2, + long long* delta) { + if (!cef_time1 || !cef_time2 || !delta) + return 0; + + base::Time base_time1, base_time2; + cef_time_to_basetime(*cef_time1, base_time1); + cef_time_to_basetime(*cef_time2, base_time2); + + base::TimeDelta time_delta = base_time2 - base_time1; + *delta = time_delta.InMilliseconds(); + return 1; +} diff --git a/libcef/common/time_util.h b/libcef/common/time_util.h new file mode 100644 index 000000000..8d92da7ec --- /dev/null +++ b/libcef/common/time_util.h @@ -0,0 +1,16 @@ +// 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_LIBCEF_COMMON_TIME_UTIL_H_ +#define CEF_LIBCEF_COMMON_TIME_UTIL_H_ +#pragma once + +#include "include/internal/cef_time.h" +#include "base/time/time.h" + +// Converts cef_time_t to/from a base::Time object. +void cef_time_to_basetime(const cef_time_t& cef_time, base::Time& time); +void cef_time_from_basetime(const base::Time& time, cef_time_t& cef_time); + +#endif // CEF_LIBCEF_COMMON_TIME_UTIL_H_ diff --git a/libcef/common/tracker.cc b/libcef/common/tracker.cc new file mode 100644 index 000000000..0a94ddb10 --- /dev/null +++ b/libcef/common/tracker.cc @@ -0,0 +1,83 @@ +// 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 "libcef/common/tracker.h" + +// CefTrackNode implementation. + +CefTrackNode::CefTrackNode() + : track_next_(NULL), + track_prev_(NULL) { +} + +CefTrackNode::~CefTrackNode() { +} + +void CefTrackNode::InsertTrackPrev(CefTrackNode* object) { + if (track_prev_) + track_prev_->SetTrackNext(object); + object->SetTrackNext(this); + object->SetTrackPrev(track_prev_); + track_prev_ = object; +} + +void CefTrackNode::InsertTrackNext(CefTrackNode* object) { + if (track_next_) + track_next_->SetTrackPrev(object); + object->SetTrackPrev(this); + object->SetTrackNext(track_next_); + track_next_ = object; +} + +void CefTrackNode::RemoveTracking() { + if (track_next_) + track_next_->SetTrackPrev(track_prev_); + if (track_prev_) + track_prev_->SetTrackNext(track_next_); + track_next_ = NULL; + track_prev_ = NULL; +} + + +// CefTrackManager implementation. + +CefTrackManager::CefTrackManager() + : object_count_(0) { +} + +CefTrackManager::~CefTrackManager() { + DeleteAll(); +} + +void CefTrackManager::Add(CefTrackNode* object) { + base::AutoLock lock_scope(lock_); + if (!object->IsTracked()) { + tracker_.InsertTrackNext(object); + ++object_count_; + } +} + +bool CefTrackManager::Delete(CefTrackNode* object) { + base::AutoLock lock_scope(lock_); + if (object->IsTracked()) { + object->RemoveTracking(); + delete object; + --object_count_; + return true; + } + return false; +} + +void CefTrackManager::DeleteAll() { + base::AutoLock lock_scope(lock_); + CefTrackNode* next; + do { + next = tracker_.GetTrackNext(); + if (next) { + next->RemoveTracking(); + delete next; + } + } while (next != NULL); + object_count_ = 0; +} diff --git a/libcef/common/tracker.h b/libcef/common/tracker.h new file mode 100644 index 000000000..3491bb713 --- /dev/null +++ b/libcef/common/tracker.h @@ -0,0 +1,77 @@ +// 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_LIBCEF_COMMON_TRACKER_H_ +#define CEF_LIBCEF_COMMON_TRACKER_H_ +#pragma once + +#include "include/cef_base.h" + +#include "base/synchronization/lock.h" + +// Class extended by objects that must be tracked. After creating a tracked +// object you should add it to the appropriate track manager. +class CefTrackNode { + public: + CefTrackNode(); + virtual ~CefTrackNode(); + + // Returns true if the object is currently being tracked. + inline bool IsTracked() { return (track_prev_ || track_next_); } + + private: + inline CefTrackNode* GetTrackPrev() { return track_prev_; } + inline void SetTrackPrev(CefTrackNode* base) { track_prev_ = base; } + inline CefTrackNode* GetTrackNext() { return track_next_; } + inline void SetTrackNext(CefTrackNode* base) { track_next_ = base; } + + // Insert a new object into the tracking list before this object. + void InsertTrackPrev(CefTrackNode* object); + + // Insert a new object into the tracking list after this object. + void InsertTrackNext(CefTrackNode* object); + + // Remove this object from the tracking list. + void RemoveTracking(); + + private: + CefTrackNode* track_next_; + CefTrackNode* track_prev_; + + friend class CefTrackManager; +}; + +// Class used to manage tracked objects. A single instance of this class +// should be created for each intended usage. Any objects that have not been +// removed by explicit calls to the Destroy() method will be removed when the +// manager object is destroyed. A manager object can be created as either a +// member variable of another class or by using lazy initialization: +// base::LazyInstance g_singleton = LAZY_INSTANCE_INITIALIZER; +class CefTrackManager : public CefBase { + public: + CefTrackManager(); + virtual ~CefTrackManager(); + + // Add an object to be tracked by this manager. + void Add(CefTrackNode* object); + + // Delete an object tracked by this manager. + bool Delete(CefTrackNode* object); + + // Delete all objects tracked by this manager. + void DeleteAll(); + + // Returns the number of objects currently being tracked. + inline int GetCount() { return object_count_; } + + private: + CefTrackNode tracker_; + int object_count_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(CefTrackManager); +}; + +#endif // CEF_LIBCEF_COMMON_TRACKER_H_ diff --git a/libcef/common/upload_data.cc b/libcef/common/upload_data.cc new file mode 100644 index 000000000..9fd260a39 --- /dev/null +++ b/libcef/common/upload_data.cc @@ -0,0 +1,37 @@ +// 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 "cef/libcef/common/upload_data.h" + +#include "base/logging.h" + +namespace net { + +UploadData::UploadData() + : identifier_(0), + is_chunked_(false), + last_chunk_appended_(false) { +} + +void UploadData::AppendBytes(const char* bytes, int bytes_len) { + DCHECK(!is_chunked_); + if (bytes_len > 0) { + elements_.push_back(new UploadElement()); + elements_.back()->SetToBytes(bytes, bytes_len); + } +} + +void UploadData::AppendFileRange(const base::FilePath& file_path, + uint64 offset, uint64 length, + const base::Time& expected_modification_time) { + DCHECK(!is_chunked_); + elements_.push_back(new UploadElement()); + elements_.back()->SetToFilePathRange(file_path, offset, length, + expected_modification_time); +} + +UploadData::~UploadData() { +} + +} // namespace net diff --git a/libcef/common/upload_data.h b/libcef/common/upload_data.h new file mode 100644 index 000000000..2299f8d86 --- /dev/null +++ b/libcef/common/upload_data.h @@ -0,0 +1,83 @@ +// 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_LIBCEF_COMMON_UPLOAD_DATA_H_ +#define CEF_LIBCEF_COMMON_UPLOAD_DATA_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_vector.h" +#include "base/supports_user_data.h" +#include "net/base/net_export.h" +#include "net/base/upload_element.h" + +namespace base { +class FilePath; +class Time; +} // namespace base + +namespace net { + +//----------------------------------------------------------------------------- +// A very concrete class representing the data to be uploaded as part of a +// URLRequest. +// +// Until there is a more abstract class for this, this one derives from +// SupportsUserData to allow users to stash random data by +// key and ensure its destruction when UploadData is finally deleted. +class NET_EXPORT UploadData + : public base::RefCounted, + public base::SupportsUserData { + public: + UploadData(); + + void AppendBytes(const char* bytes, int bytes_len); + + void AppendFileRange(const base::FilePath& file_path, + uint64 offset, uint64 length, + const base::Time& expected_modification_time); + + // Initializes the object to send chunks of upload data over time rather + // than all at once. Chunked data may only contain bytes, not files. + void set_is_chunked(bool set) { is_chunked_ = set; } + bool is_chunked() const { return is_chunked_; } + + // set_last_chunk_appended() is only used for serialization. + void set_last_chunk_appended(bool set) { last_chunk_appended_ = set; } + bool last_chunk_appended() const { return last_chunk_appended_; } + + const ScopedVector& elements() const { + return elements_; + } + + ScopedVector* elements_mutable() { + return &elements_; + } + + void swap_elements(ScopedVector* elements) { + elements_.swap(*elements); + } + + // Identifies a particular upload instance, which is used by the cache to + // formulate a cache key. This value should be unique across browser + // sessions. A value of 0 is used to indicate an unspecified identifier. + void set_identifier(int64 id) { identifier_ = id; } + int64 identifier() const { return identifier_; } + + private: + friend class base::RefCounted; + + virtual ~UploadData(); + + ScopedVector elements_; + int64 identifier_; + bool is_chunked_; + bool last_chunk_appended_; + + DISALLOW_COPY_AND_ASSIGN(UploadData); +}; + +} // namespace net + +#endif // CEF_LIBCEF_COMMON_UPLOAD_DATA_H_ diff --git a/libcef/common/url_impl.cc b/libcef/common/url_impl.cc new file mode 100644 index 000000000..d2660fcf2 --- /dev/null +++ b/libcef/common/url_impl.cc @@ -0,0 +1,87 @@ +// 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 +#include "include/cef_url.h" +#include "net/base/mime_util.h" +#include "url/gurl.h" + +bool CefParseURL(const CefString& url, + CefURLParts& parts) { + GURL gurl(url.ToString()); + if (!gurl.is_valid()) + return false; + + CefString(&parts.spec).FromString(gurl.spec()); + CefString(&parts.scheme).FromString(gurl.scheme()); + CefString(&parts.username).FromString(gurl.username()); + CefString(&parts.password).FromString(gurl.password()); + CefString(&parts.host).FromString(gurl.host()); + CefString(&parts.origin).FromString(gurl.GetOrigin().spec()); + CefString(&parts.port).FromString(gurl.port()); + CefString(&parts.path).FromString(gurl.path()); + CefString(&parts.query).FromString(gurl.query()); + + return true; +} + +bool CefCreateURL(const CefURLParts& parts, + CefString& url) { + std::string spec = CefString(parts.spec.str, parts.spec.length, false); + std::string scheme = CefString(parts.scheme.str, parts.scheme.length, false); + std::string username = + CefString(parts.username.str, parts.username.length, false); + std::string password = + CefString(parts.password.str, parts.password.length, false); + std::string host = CefString(parts.host.str, parts.host.length, false); + std::string port = CefString(parts.port.str, parts.port.length, false); + std::string path = CefString(parts.path.str, parts.path.length, false); + std::string query = CefString(parts.query.str, parts.query.length, false); + + GURL gurl; + if (!spec.empty()) { + gurl = GURL(spec); + } else if (!scheme.empty() && !host.empty()) { + std::stringstream ss; + ss << scheme << "://"; + if (!username.empty()) { + ss << username; + if (!password.empty()) + ss << ":" << password; + ss << "@"; + } + ss << host; + if (!port.empty()) + ss << ":" << port; + if (!path.empty()) + ss << path; + if (!query.empty()) + ss << "?" << query; + gurl = GURL(ss.str()); + } + + if (gurl.is_valid()) { + url = gurl.spec(); + return true; + } + + return false; +} + +CefString CefGetMimeType(const CefString& extension) { + std::string mime_type; + net::GetMimeTypeFromExtension(extension, &mime_type); + return mime_type; +} + +void CefGetExtensionsForMimeType(const CefString& mime_type, + std::vector& extensions) { + typedef std::vector VectorType; + VectorType ext; + net::GetExtensionsForMimeType(mime_type, &ext); + VectorType::const_iterator it = ext.begin(); + for (; it != ext.end(); ++it) + extensions.push_back(*it); +} + diff --git a/libcef/common/urlrequest_impl.cc b/libcef/common/urlrequest_impl.cc new file mode 100644 index 000000000..958722fd4 --- /dev/null +++ b/libcef/common/urlrequest_impl.cc @@ -0,0 +1,46 @@ +// 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 "include/cef_urlrequest.h" +#include "libcef/browser/browser_urlrequest_impl.h" +#include "libcef/common/content_client.h" +#include "libcef/renderer/render_urlrequest_impl.h" + +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "content/public/common/content_client.h" + +// static +CefRefPtr CefURLRequest::Create( + CefRefPtr request, + CefRefPtr client) { + if (!request.get() || !client.get()) { + NOTREACHED() << "called with invalid parameters"; + return NULL; + } + + if (!base::MessageLoop::current()) { + NOTREACHED() << "called on invalid thread"; + return NULL; + } + + if (CefContentClient::Get()->browser()) { + // In the browser process. + CefRefPtr impl = + new CefBrowserURLRequest(request, client); + if (impl->Start()) + return impl.get(); + return NULL; + } else if (CefContentClient::Get()->renderer()) { + // In the render process. + CefRefPtr impl = + new CefRenderURLRequest(request, client); + if (impl->Start()) + return impl.get(); + return NULL; + } else { + NOTREACHED() << "called in unsupported process"; + return NULL; + } +} diff --git a/libcef/common/value_base.cc b/libcef/common/value_base.cc new file mode 100644 index 000000000..5ca561488 --- /dev/null +++ b/libcef/common/value_base.cc @@ -0,0 +1,201 @@ +// 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 "libcef/common/value_base.h" + + +CefValueController::CefValueController() + : owner_value_(NULL), + owner_object_(NULL) { +} + +CefValueController::~CefValueController() { + // Everything should already have been removed. + DCHECK(!owner_value_ && !owner_object_); + DCHECK(reference_map_.empty()); + DCHECK(dependency_map_.empty()); +} + +void CefValueController::SetOwner(void* value, Object* object) { + DCHECK(value && object); + + // Controller should already be locked. + DCHECK(locked()); + + // Owner should only be set once. + DCHECK(!owner_value_ && !owner_object_); + + owner_value_ = value; + owner_object_ = object; +} + +void CefValueController::AddReference(void* value, Object* object) { + DCHECK(value && object); + + // Controller should already be locked. + DCHECK(locked()); + + // Controller should currently have an owner. + DCHECK(owner_value_); + + // Values should only be added once. + DCHECK(reference_map_.find(value) == reference_map_.end()); + DCHECK(value != owner_value_); + + reference_map_.insert(std::make_pair(value, object)); +} + +void CefValueController::Remove(void* value, bool notify_object) { + DCHECK(value); + + // Controller should already be locked. + DCHECK(locked()); + + // Controller should currently have an owner. + DCHECK(owner_value_); + + if (value == owner_value_) { + // Should never notify when removing the owner object. + DCHECK(!notify_object); + + owner_value_ = NULL; + owner_object_ = NULL; + + // Remove all references. + if (reference_map_.size() > 0) { + ReferenceMap::iterator it = reference_map_.begin(); + for (; it != reference_map_.end(); ++it) + it->second->OnControlRemoved(); + reference_map_.clear(); + } + + // Remove all dependencies. + dependency_map_.clear(); + } else { + ReferenceMap::iterator it = reference_map_.find(value); + if (it != reference_map_.end()) { + // Remove the reference. + if (notify_object) + it->second->OnControlRemoved(); + reference_map_.erase(it); + } + } +} + +CefValueController::Object* CefValueController::Get(void* value) { + DCHECK(value); + + // Controller should already be locked. + DCHECK(locked()); + + if (value == owner_value_) { + return owner_object_; + } else { + ReferenceMap::iterator it = reference_map_.find(value); + if (it != reference_map_.end()) + return it->second; + return NULL; + } +} + +void CefValueController::AddDependency(void* parent, void* child) { + DCHECK(parent && child && parent != child); + + // Controller should already be locked. + DCHECK(locked()); + + DependencyMap::iterator it = dependency_map_.find(parent); + if (it == dependency_map_.end()) { + // New set. + DependencySet set; + set.insert(child); + dependency_map_.insert(std::make_pair(parent, set)); + } else if (it->second.find(child) == it->second.end()) { + // Update existing set. + it->second.insert(child); + } +} + +void CefValueController::RemoveDependencies(void* value) { + DCHECK(value); + + // Controller should already be locked. + DCHECK(locked()); + + if (dependency_map_.empty()) + return; + + DependencyMap::iterator it_dependency = dependency_map_.find(value); + if (it_dependency == dependency_map_.end()) + return; + + // Start with the set of dependencies for the current value. + DependencySet remove_set = it_dependency->second; + dependency_map_.erase(it_dependency); + + DependencySet::iterator it_value; + ReferenceMap::iterator it_reference; + + while (remove_set.size() > 0) { + it_value = remove_set.begin(); + value = *it_value; + remove_set.erase(it_value); + + // Does the current value have dependencies? + it_dependency = dependency_map_.find(value); + if (it_dependency != dependency_map_.end()) { + // Append the dependency set to the remove set. + remove_set.insert(it_dependency->second.begin(), + it_dependency->second.end()); + dependency_map_.erase(it_dependency); + } + + // Does the current value have a reference? + it_reference = reference_map_.find(value); + if (it_reference != reference_map_.end()) { + // Remove the reference. + it_reference->second->OnControlRemoved(); + reference_map_.erase(it_reference); + } + } +} + +void CefValueController::TakeFrom(CefValueController* other) { + DCHECK(other); + + // Both controllers should already be locked. + DCHECK(locked()); + DCHECK(other->locked()); + + if (!other->reference_map_.empty()) { + // Transfer references from the other to this. + ReferenceMap::iterator it = other->reference_map_.begin(); + for (; it != other->reference_map_.end(); ++it) { + // References should only be added once. + DCHECK(reference_map_.find(it->first) == reference_map_.end()); + reference_map_.insert(std::make_pair(it->first, it->second)); + } + other->reference_map_.empty(); + } + + if (!other->dependency_map_.empty()) { + // Transfer dependencies from the other to this. + DependencyMap::iterator it_other = other->dependency_map_.begin(); + for (; it_other != other->dependency_map_.end(); ++it_other) { + DependencyMap::iterator it_me = dependency_map_.find(it_other->first); + if (it_me == dependency_map_.end()) { + // All children are new. + dependency_map_.insert( + std::make_pair(it_other->first, it_other->second)); + } else { + // Evaluate each child. + DependencySet::iterator it_other_set = it_other->second.begin(); + for (; it_other_set != it_other->second.end(); ++it_other_set) { + if (it_me->second.find(*it_other_set) == it_me->second.end()) + it_me->second.insert(*it_other_set); + } + } + } + } +} diff --git a/libcef/common/value_base.h b/libcef/common/value_base.h new file mode 100644 index 000000000..f6f9f7a39 --- /dev/null +++ b/libcef/common/value_base.h @@ -0,0 +1,415 @@ +// 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_LIBCEF_COMMON_VALUE_BASE_H_ +#define CEF_LIBCEF_COMMON_VALUE_BASE_H_ +#pragma once + +#include +#include +#include "include/cef_base.h" + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "base/threading/platform_thread.h" + + +// Controller implementation base class. +class CefValueController + : public base::RefCountedThreadSafe { + public: + // Implemented by a class controlled using the access controller. + class Object { + public: + virtual ~Object() {} + + // Called when the value has been removed. + virtual void OnControlRemoved() =0; + }; + + // Encapsulates context locking and verification logic. + class AutoLock { + public: + explicit AutoLock(CefValueController* impl) + : impl_(impl), + verified_(impl && impl->VerifyThread()) { + DCHECK(impl); + if (verified_) + impl_->lock(); + } + virtual ~AutoLock() { + if (verified_) + impl_->unlock(); + } + + inline bool verified() { return verified_; } + + private: + scoped_refptr impl_; + bool verified_; + + DISALLOW_COPY_AND_ASSIGN(AutoLock); + }; + + CefValueController(); + virtual ~CefValueController(); + + // Returns true if this controller is thread safe. + virtual bool thread_safe() =0; + + // Returns true if the current thread is allowed to access this controller. + virtual bool on_correct_thread() =0; + + // Lock the controller. + virtual void lock() =0; + + // Unlock the controller. + virtual void unlock() =0; + + // Returns true if the controller is locked on the current thread. + virtual bool locked() =0; + + // Verify that the current thread is correct for accessing the controller. + inline bool VerifyThread() { + if (!thread_safe() && !on_correct_thread()) { + // This object should only be accessed from the thread that created it. + NOTREACHED() << "object accessed from incorrect thread."; + return false; + } + return true; + } + + // The controller must already be locked before calling the below methods. + + // Set the owner for this controller. + void SetOwner(void* value, Object* object); + + // Add a reference value and associated object. + void AddReference(void* value, Object* object); + + // Remove the value. If |notify_object| is true the removed object will be + // notified. If |value| is the owner all reference objects will be removed. + // If |value| has dependencies those objects will also be removed. + void Remove(void* value, bool notify_object); + + // Returns the object for the specified value. + Object* Get(void* value); + + // Add a dependency between |parent| and |child|. + void AddDependency(void* parent, void* child); + + // Recursively removes any dependent values. + void RemoveDependencies(void* value); + + // Takes ownership of all references and dependencies currently controlled by + // |other|. The |other| controller must already be locked. + void TakeFrom(CefValueController* other); + + private: + // Owner object. + void* owner_value_; + Object* owner_object_; + + // Map of reference objects. + typedef std::map ReferenceMap; + ReferenceMap reference_map_; + + // Map of dependency objects. + typedef std::set DependencySet; + typedef std::map DependencyMap; + DependencyMap dependency_map_; + + DISALLOW_COPY_AND_ASSIGN(CefValueController); +}; + +// Thread-safe access control implementation. +class CefValueControllerThreadSafe : public CefValueController { + public: + explicit CefValueControllerThreadSafe() + : locked_thread_id_(0) {} + + // CefValueController methods. + virtual bool thread_safe() OVERRIDE { return true; } + virtual bool on_correct_thread() OVERRIDE { return true; } + virtual void lock() OVERRIDE { + lock_.Acquire(); + locked_thread_id_ = base::PlatformThread::CurrentId(); + } + virtual void unlock() OVERRIDE { + locked_thread_id_ = 0; + lock_.Release(); + } + virtual bool locked() OVERRIDE { + return (locked_thread_id_ == base::PlatformThread::CurrentId()); + } + + private: + base::Lock lock_; + base::PlatformThreadId locked_thread_id_; + + DISALLOW_COPY_AND_ASSIGN(CefValueControllerThreadSafe); +}; + +// Non-thread-safe access control implementation. +class CefValueControllerNonThreadSafe : public CefValueController { + public: + explicit CefValueControllerNonThreadSafe() + : thread_id_(base::PlatformThread::CurrentId()) {} + + // CefValueController methods. + virtual bool thread_safe() OVERRIDE { return false; } + virtual bool on_correct_thread() OVERRIDE { + return (thread_id_ == base::PlatformThread::CurrentId()); + } + virtual void lock() OVERRIDE {} + virtual void unlock() OVERRIDE {} + virtual bool locked() OVERRIDE { return on_correct_thread(); } + + private: + base::PlatformThreadId thread_id_; + + DISALLOW_COPY_AND_ASSIGN(CefValueControllerNonThreadSafe); +}; + + +// Helper macros for verifying context. + +#define CEF_VALUE_VERIFY_RETURN_VOID_EX(object, modify) \ + if (!VerifyAttached()) \ + return; \ + AutoLock auto_lock(object, modify); \ + if (!auto_lock.verified()) \ + return; + +#define CEF_VALUE_VERIFY_RETURN_VOID(modify) \ + CEF_VALUE_VERIFY_RETURN_VOID_EX(this, modify) + +#define CEF_VALUE_VERIFY_RETURN_EX(object, modify, error_val) \ + if (!VerifyAttached()) \ + return error_val; \ + AutoLock auto_lock(object, modify); \ + if (!auto_lock.verified()) \ + return error_val; + +#define CEF_VALUE_VERIFY_RETURN(modify, error_val) \ + CEF_VALUE_VERIFY_RETURN_EX(this, modify, error_val) + + +// Template class for implementing CEF wrappers of other types. +template +class CefValueBase : public CefType, public CefValueController::Object { + public: + // Specifies how the value will be used. + enum ValueMode { + // A reference to a value managed by an existing controller. These values + // can be safely detached but ownership should not be transferred (make a + // copy of the value instead). + kReference, + + // The value has its own controller and will be deleted on destruction. + // These values can only be detached to another controller otherwise any + // references will not be properly managed. + kOwnerWillDelete, + + // The value has its own controller and will not be deleted on destruction. + // This should only be used for global values or scope-limited values that + // will be explicitly detached. + kOwnerNoDelete, + }; + + // Create a new object. + // If |read_only| is true mutable access will not be allowed. + // If |parent_value| is non-NULL and the value mode is kReference a dependency + // will be added. + CefValueBase(ValueType* value, + void* parent_value, + ValueMode value_mode, + bool read_only, + CefValueController* controller) + : value_(value), + value_mode_(value_mode), + read_only_(read_only), + controller_(controller) { + DCHECK(value_); + + // Specifying a parent value for a non-reference doesn't make sense. + DCHECK(!(!reference() && parent_value)); + + if (!reference() && !controller_) { + // For owned values default to using a new multi-threaded controller. + controller_ = new CefValueControllerThreadSafe(); + SetOwnsController(); + } + + // A controller is required. + DCHECK(controller_); + + if (reference()) { + // Register the reference with the controller. + controller_->AddReference(value_, this); + + // Add a dependency on the parent value. + if (parent_value) + controller_->AddDependency(parent_value, value_); + } + } + virtual ~CefValueBase() { + if (controller_ && value_) + Delete(); + } + + // True if the underlying value is referenced instead of owned. + inline bool reference() const { return (value_mode_ == kReference); } + + // True if the underlying value will be deleted. + inline bool will_delete() const { return (value_mode_ == kOwnerWillDelete); } + + // True if access to the underlying value is read-only. + inline bool read_only() const { return read_only_; } + + // True if the underlying value has been detached. + inline bool detached() { return (controller_ == NULL); } + + // Returns the controller. + inline CefValueController* controller() { return controller_; } + + // Deletes the underlying value. + void Delete() { + CEF_VALUE_VERIFY_RETURN_VOID(false); + + // Remove the object from the controller. If this is the owner object any + // references will be detached. + controller()->Remove(value_, false); + + if (will_delete()) { + // Remove any dependencies. + controller()->RemoveDependencies(value_); + + // Delete the value. + DeleteValue(value_); + } + + controller_ = NULL; + value_ = NULL; + } + + // Detaches the underlying value and returns a pointer to it. If this is an + // owner and a |new_controller| value is specified any existing references + // will be passed to the new controller. + ValueType* Detach(CefValueController* new_controller) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + // A |new_controller| value is required for mode kOwnerWillDelete. + DCHECK(!will_delete() || new_controller); + + if (new_controller && !reference()) { + // Pass any existing references and dependencies to the new controller. + // They will be removed from this controller. + new_controller->TakeFrom(controller()); + } + + // Remove the object from the controller. If this is the owner object any + // references will be detached. + controller()->Remove(value_, false); + controller_ = NULL; + + // Return the old value. + ValueType* old_val = value_; + value_ = NULL; + return old_val; + } + + // Verify that the value is attached. + inline bool VerifyAttached() { + if (detached()) { + // This object should not be accessed after being detached. + NOTREACHED() << "object accessed after being detached."; + return false; + } + return true; + } + + protected: + // CefValueController::Object methods. + virtual void OnControlRemoved() { + DCHECK(controller()->locked()); + + // Only references should be removed in this manner. + DCHECK(reference()); + + controller_ = NULL; + value_ = NULL; + } + + // Override to customize value deletion. + virtual void DeleteValue(ValueType* value) { delete value; } + + // Returns a mutable reference to the value. + inline ValueType* mutable_value() { + DCHECK(value_); + DCHECK(!read_only_); + DCHECK(controller()->locked()); + return value_; + } + // Returns a const reference to the value. + inline const ValueType& const_value() { + DCHECK(value_); + DCHECK(controller()->locked()); + return *value_; + } + + // Verify that the value can be accessed. + inline bool VerifyAccess(bool modify) { + // The controller must already be locked. + DCHECK(controller()->locked()); + + if (read_only() && modify) { + // This object cannot be modified. + NOTREACHED() << "mutation attempted on read-only object."; + return false; + } + + return true; + } + + // Used to indicate that this object owns the controller. + inline void SetOwnsController() { + CefValueController::AutoLock lock_scope(controller_); + if (lock_scope.verified()) + controller_->SetOwner(value_, this); + } + + // Encapsulates value locking and verification logic. + class AutoLock { + public: + explicit AutoLock(CefValueBase* impl, bool modify) + : auto_lock_(impl->controller()), + verified_(auto_lock_.verified() && impl->VerifyAccess(modify)) { + } + virtual ~AutoLock() {} + + inline bool verified() { return verified_; } + + private: + CefValueController::AutoLock auto_lock_; + bool verified_; + + DISALLOW_COPY_AND_ASSIGN(AutoLock); + }; + + private: + ValueType* value_; + ValueMode value_mode_; + bool read_only_; + scoped_refptr controller_; + + IMPLEMENT_REFCOUNTING(CefValueBase); + + DISALLOW_COPY_AND_ASSIGN(CefValueBase); +}; + + +#endif // CEF_LIBCEF_COMMON_VALUE_BASE_H_ diff --git a/libcef/common/values_impl.cc b/libcef/common/values_impl.cc new file mode 100644 index 000000000..647609b66 --- /dev/null +++ b/libcef/common/values_impl.cc @@ -0,0 +1,839 @@ +// 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 "libcef/common/values_impl.h" + +#include +#include + + +// CefBinaryValueImpl implementation. + +CefRefPtr CefBinaryValue::Create(const void* data, + size_t data_size) { + DCHECK(data); + DCHECK_GT(data_size, (size_t)0); + if (!data || data_size == 0) + return NULL; + + return new CefBinaryValueImpl(static_cast(const_cast(data)), + data_size, true); +} + +// static +CefRefPtr CefBinaryValueImpl::GetOrCreateRef( + base::BinaryValue* value, + void* parent_value, + CefValueController* controller) { + DCHECK(value); + DCHECK(parent_value); + DCHECK(controller); + + CefValueController::Object* object = controller->Get(value); + if (object) + return static_cast(object); + + return new CefBinaryValueImpl(value, parent_value, + CefBinaryValueImpl::kReference, controller); +} + +CefBinaryValueImpl::CefBinaryValueImpl(base::BinaryValue* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +base::BinaryValue* CefBinaryValueImpl::CopyValue() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return const_value().DeepCopy(); +} + +base::BinaryValue* CefBinaryValueImpl::CopyOrDetachValue( + CefValueController* new_controller) { + base::BinaryValue* new_value; + + if (!will_delete()) { + // Copy the value. + new_value = CopyValue(); + } else { + // Take ownership of the value. + new_value = Detach(new_controller); + } + + DCHECK(new_value); + return new_value; +} + +bool CefBinaryValueImpl::IsValid() { + return !detached(); +} + +bool CefBinaryValueImpl::IsOwned() { + return !will_delete(); +} + +CefRefPtr CefBinaryValueImpl::Copy() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return new CefBinaryValueImpl(const_value().DeepCopy(), NULL, + CefBinaryValueImpl::kOwnerWillDelete, NULL); +} + +size_t CefBinaryValueImpl::GetSize() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().GetSize(); +} + +size_t CefBinaryValueImpl::GetData(void* buffer, + size_t buffer_size, + size_t data_offset) { + DCHECK(buffer); + DCHECK_GT(buffer_size, (size_t)0); + if (!buffer || buffer_size == 0) + return 0; + + CEF_VALUE_VERIFY_RETURN(false, 0); + + size_t size = const_value().GetSize(); + DCHECK_LT(data_offset, size); + if (data_offset >= size) + return 0; + + size = std::min(buffer_size, size-data_offset); + const char* data = const_value().GetBuffer(); + memcpy(buffer, data+data_offset, size); + return size; +} + +CefBinaryValueImpl::CefBinaryValueImpl(base::BinaryValue* value, + void* parent_value, + ValueMode value_mode, + CefValueController* controller) + : CefValueBase( + value, parent_value, value_mode, true, controller) { +} + +CefBinaryValueImpl::CefBinaryValueImpl(char* data, + size_t data_size, + bool copy) + : CefValueBase( + copy ? base::BinaryValue::CreateWithCopiedBuffer(data, data_size) : + new base::BinaryValue(scoped_ptr(data), data_size), + NULL, kOwnerWillDelete, true, NULL) { +} + + +// CefDictionaryValueImpl implementation. + +// static +CefRefPtr CefDictionaryValue::Create() { + return new CefDictionaryValueImpl(new base::DictionaryValue(), + NULL, CefDictionaryValueImpl::kOwnerWillDelete, false, NULL); +} + +// static +CefRefPtr CefDictionaryValueImpl::GetOrCreateRef( + base::DictionaryValue* value, + void* parent_value, + bool read_only, + CefValueController* controller) { + CefValueController::Object* object = controller->Get(value); + if (object) + return static_cast(object); + + return new CefDictionaryValueImpl(value, parent_value, + CefDictionaryValueImpl::kReference, read_only, controller); +} + +CefDictionaryValueImpl::CefDictionaryValueImpl(base::DictionaryValue* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +base::DictionaryValue* CefDictionaryValueImpl::CopyValue() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return const_value().DeepCopy(); +} + +base::DictionaryValue* CefDictionaryValueImpl::CopyOrDetachValue( + CefValueController* new_controller) { + base::DictionaryValue* new_value; + + if (!will_delete()) { + // Copy the value. + new_value = CopyValue(); + } else { + // Take ownership of the value. + new_value = Detach(new_controller); + } + + DCHECK(new_value); + return new_value; +} + +bool CefDictionaryValueImpl::IsValid() { + return !detached(); +} + +bool CefDictionaryValueImpl::IsOwned() { + return !will_delete(); +} + +bool CefDictionaryValueImpl::IsReadOnly() { + return read_only(); +} + +CefRefPtr CefDictionaryValueImpl::Copy( + bool exclude_empty_children) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + base::DictionaryValue* value; + if (exclude_empty_children) { + value = const_cast( + const_value()).DeepCopyWithoutEmptyChildren(); + } else { + value = const_value().DeepCopy(); + } + + return new CefDictionaryValueImpl(value, NULL, + CefDictionaryValueImpl::kOwnerWillDelete, false, NULL); +} + +size_t CefDictionaryValueImpl::GetSize() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().size(); +} + +bool CefDictionaryValueImpl::Clear() { + CEF_VALUE_VERIFY_RETURN(true, false); + + // Detach any dependent values. + controller()->RemoveDependencies(mutable_value()); + + mutable_value()->Clear(); + return true; +} + +bool CefDictionaryValueImpl::HasKey(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().HasKey(key); +} + +bool CefDictionaryValueImpl::GetKeys(KeyList& keys) { + CEF_VALUE_VERIFY_RETURN(false, 0); + + for (base::DictionaryValue::Iterator i(const_value()); + !i.IsAtEnd(); i.Advance()) { + keys.push_back(i.key()); + } + + return true; +} + +bool CefDictionaryValueImpl::Remove(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(true, false); + return RemoveInternal(key); +} + +CefValueType CefDictionaryValueImpl::GetType(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID); + + const base::Value* out_value = NULL; + if (const_value().GetWithoutPathExpansion(key, &out_value)) { + switch (out_value->GetType()) { + case base::Value::TYPE_NULL: + return VTYPE_NULL; + case base::Value::TYPE_BOOLEAN: + return VTYPE_BOOL; + case base::Value::TYPE_INTEGER: + return VTYPE_INT; + case base::Value::TYPE_DOUBLE: + return VTYPE_DOUBLE; + case base::Value::TYPE_STRING: + return VTYPE_STRING; + case base::Value::TYPE_BINARY: + return VTYPE_BINARY; + case base::Value::TYPE_DICTIONARY: + return VTYPE_DICTIONARY; + case base::Value::TYPE_LIST: + return VTYPE_LIST; + } + } + + return VTYPE_INVALID; +} + +bool CefDictionaryValueImpl::GetBool(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, false); + + const base::Value* out_value = NULL; + bool ret_value = false; + + if (const_value().GetWithoutPathExpansion(key, &out_value)) + out_value->GetAsBoolean(&ret_value); + + return ret_value; +} + +int CefDictionaryValueImpl::GetInt(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, 0); + + const base::Value* out_value = NULL; + int ret_value = 0; + + if (const_value().GetWithoutPathExpansion(key, &out_value)) + out_value->GetAsInteger(&ret_value); + + return ret_value; +} + +double CefDictionaryValueImpl::GetDouble(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, 0); + + const base::Value* out_value = NULL; + double ret_value = 0; + + if (const_value().GetWithoutPathExpansion(key, &out_value)) + out_value->GetAsDouble(&ret_value); + + return ret_value; +} + +CefString CefDictionaryValueImpl::GetString(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + + const base::Value* out_value = NULL; + std::string ret_value; + + if (const_value().GetWithoutPathExpansion(key, &out_value)) + out_value->GetAsString(&ret_value); + + return ret_value; +} + +CefRefPtr CefDictionaryValueImpl::GetBinary( + const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().GetWithoutPathExpansion(key, &out_value) && + out_value->IsType(base::Value::TYPE_BINARY)) { + base::BinaryValue* binary_value = + static_cast(const_cast(out_value)); + return CefBinaryValueImpl::GetOrCreateRef(binary_value, + const_cast(&const_value()), controller()); + } + + return NULL; +} + +CefRefPtr CefDictionaryValueImpl::GetDictionary( + const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().GetWithoutPathExpansion(key, &out_value) && + out_value->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict_value = + static_cast( + const_cast(out_value)); + return CefDictionaryValueImpl::GetOrCreateRef( + dict_value, + const_cast(&const_value()), + read_only(), + controller()); + } + + return NULL; +} + +CefRefPtr CefDictionaryValueImpl::GetList(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().GetWithoutPathExpansion(key, &out_value) && + out_value->IsType(base::Value::TYPE_LIST)) { + base::ListValue* list_value = + static_cast(const_cast(out_value)); + return CefListValueImpl::GetOrCreateRef( + list_value, + const_cast(&const_value()), + read_only(), + controller()); + } + + return NULL; +} + +bool CefDictionaryValueImpl::SetNull(const CefString& key) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + mutable_value()->SetWithoutPathExpansion(key, base::Value::CreateNullValue()); + return true; +} + +bool CefDictionaryValueImpl::SetBool(const CefString& key, bool value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + mutable_value()->SetWithoutPathExpansion(key, + base::Value::CreateBooleanValue(value)); + return true; +} + +bool CefDictionaryValueImpl::SetInt(const CefString& key, int value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + mutable_value()->SetWithoutPathExpansion(key, + base::Value::CreateIntegerValue(value)); + return true; +} + +bool CefDictionaryValueImpl::SetDouble(const CefString& key, double value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + mutable_value()->SetWithoutPathExpansion(key, + base::Value::CreateDoubleValue(value)); + return true; +} + +bool CefDictionaryValueImpl::SetString(const CefString& key, + const CefString& value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + mutable_value()->SetWithoutPathExpansion(key, + base::Value::CreateStringValue(value.ToString())); + return true; +} + +bool CefDictionaryValueImpl::SetBinary(const CefString& key, + CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + + CefBinaryValueImpl* impl = static_cast(value.get()); + DCHECK(impl); + + mutable_value()->SetWithoutPathExpansion(key, + impl->CopyOrDetachValue(controller())); + return true; +} + +bool CefDictionaryValueImpl::SetDictionary( + const CefString& key, CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + + CefDictionaryValueImpl* impl = + static_cast(value.get()); + DCHECK(impl); + + mutable_value()->SetWithoutPathExpansion(key, + impl->CopyOrDetachValue(controller())); + return true; +} + +bool CefDictionaryValueImpl::SetList(const CefString& key, + CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + RemoveInternal(key); + + CefListValueImpl* impl = static_cast(value.get()); + DCHECK(impl); + + mutable_value()->SetWithoutPathExpansion(key, + impl->CopyOrDetachValue(controller())); + return true; +} + +bool CefDictionaryValueImpl::RemoveInternal(const CefString& key) { + scoped_ptr out_value; + if (!mutable_value()->RemoveWithoutPathExpansion(key, &out_value)) + return false; + + // Remove the value. + controller()->Remove(out_value.get(), true); + + // Only list and dictionary types may have dependencies. + if (out_value->IsType(base::Value::TYPE_LIST) || + out_value->IsType(base::Value::TYPE_DICTIONARY)) { + controller()->RemoveDependencies(out_value.get()); + } + + return true; +} + +CefDictionaryValueImpl::CefDictionaryValueImpl( + base::DictionaryValue* value, + void* parent_value, + ValueMode value_mode, + bool read_only, + CefValueController* controller) + : CefValueBase( + value, parent_value, value_mode, read_only, controller) { +} + + +// CefListValueImpl implementation. + +// static +CefRefPtr CefListValue::Create() { + return new CefListValueImpl(new base::ListValue(), + NULL, CefListValueImpl::kOwnerWillDelete, false, NULL); +} + +// static +CefRefPtr CefListValueImpl::GetOrCreateRef( + base::ListValue* value, + void* parent_value, + bool read_only, + CefValueController* controller) { + CefValueController::Object* object = controller->Get(value); + if (object) + return static_cast(object); + + return new CefListValueImpl(value, parent_value, + CefListValueImpl::kReference, read_only, controller); +} + +CefListValueImpl::CefListValueImpl(base::ListValue* value, + bool will_delete, + bool read_only) + : CefValueBase( + value, NULL, will_delete ? kOwnerWillDelete : kOwnerNoDelete, + read_only, NULL) { +} + +base::ListValue* CefListValueImpl::CopyValue() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + return const_value().DeepCopy(); +} + +base::ListValue* CefListValueImpl::CopyOrDetachValue( + CefValueController* new_controller) { + base::ListValue* new_value; + + if (!will_delete()) { + // Copy the value. + new_value = CopyValue(); + } else { + // Take ownership of the value. + new_value = Detach(new_controller); + } + + DCHECK(new_value); + return new_value; +} + +bool CefListValueImpl::IsValid() { + return !detached(); +} + +bool CefListValueImpl::IsOwned() { + return !will_delete(); +} + +bool CefListValueImpl::IsReadOnly() { + return read_only(); +} + +CefRefPtr CefListValueImpl::Copy() { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + return new CefListValueImpl(const_value().DeepCopy(), NULL, + CefListValueImpl::kOwnerWillDelete, false, NULL); +} + +bool CefListValueImpl::SetSize(size_t size) { + CEF_VALUE_VERIFY_RETURN(true, false); + + size_t current_size = const_value().GetSize(); + if (size < current_size) { + // Clean up any values above the requested size. + for (size_t i = current_size-1; i >= size; --i) + RemoveInternal(i); + } else if (size > 0) { + // Expand the list size. + mutable_value()->Set(size-1, base::Value::CreateNullValue()); + } + return true; +} + +size_t CefListValueImpl::GetSize() { + CEF_VALUE_VERIFY_RETURN(false, 0); + return const_value().GetSize(); +} + +bool CefListValueImpl::Clear() { + CEF_VALUE_VERIFY_RETURN(true, false); + + // Detach any dependent values. + controller()->RemoveDependencies(mutable_value()); + + mutable_value()->Clear(); + return true; +} + +bool CefListValueImpl::Remove(int index) { + CEF_VALUE_VERIFY_RETURN(true, false); + return RemoveInternal(index); +} + +CefValueType CefListValueImpl::GetType(int index) { + CEF_VALUE_VERIFY_RETURN(false, VTYPE_INVALID); + + const base::Value* out_value = NULL; + if (const_value().Get(index, &out_value)) { + switch (out_value->GetType()) { + case base::Value::TYPE_NULL: + return VTYPE_NULL; + case base::Value::TYPE_BOOLEAN: + return VTYPE_BOOL; + case base::Value::TYPE_INTEGER: + return VTYPE_INT; + case base::Value::TYPE_DOUBLE: + return VTYPE_DOUBLE; + case base::Value::TYPE_STRING: + return VTYPE_STRING; + case base::Value::TYPE_BINARY: + return VTYPE_BINARY; + case base::Value::TYPE_DICTIONARY: + return VTYPE_DICTIONARY; + case base::Value::TYPE_LIST: + return VTYPE_LIST; + } + } + + return VTYPE_INVALID; +} + +bool CefListValueImpl::GetBool(int index) { + CEF_VALUE_VERIFY_RETURN(false, false); + + const base::Value* out_value = NULL; + bool ret_value = false; + + if (const_value().Get(index, &out_value)) + out_value->GetAsBoolean(&ret_value); + + return ret_value; +} + +int CefListValueImpl::GetInt(int index) { + CEF_VALUE_VERIFY_RETURN(false, 0); + + const base::Value* out_value = NULL; + int ret_value = 0; + + if (const_value().Get(index, &out_value)) + out_value->GetAsInteger(&ret_value); + + return ret_value; +} + +double CefListValueImpl::GetDouble(int index) { + CEF_VALUE_VERIFY_RETURN(false, 0); + + const base::Value* out_value = NULL; + double ret_value = 0; + + if (const_value().Get(index, &out_value)) + out_value->GetAsDouble(&ret_value); + + return ret_value; +} + +CefString CefListValueImpl::GetString(int index) { + CEF_VALUE_VERIFY_RETURN(false, CefString()); + + const base::Value* out_value = NULL; + std::string ret_value; + + if (const_value().Get(index, &out_value)) + out_value->GetAsString(&ret_value); + + return ret_value; +} + +CefRefPtr CefListValueImpl::GetBinary(int index) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().Get(index, &out_value) && + out_value->IsType(base::Value::TYPE_BINARY)) { + base::BinaryValue* binary_value = + static_cast(const_cast(out_value)); + return CefBinaryValueImpl::GetOrCreateRef(binary_value, + const_cast(&const_value()), controller()); + } + + return NULL; +} + +CefRefPtr CefListValueImpl::GetDictionary(int index) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().Get(index, &out_value) && + out_value->IsType(base::Value::TYPE_DICTIONARY)) { + base::DictionaryValue* dict_value = + static_cast( + const_cast(out_value)); + return CefDictionaryValueImpl::GetOrCreateRef( + dict_value, + const_cast(&const_value()), + read_only(), + controller()); + } + + return NULL; +} + +CefRefPtr CefListValueImpl::GetList(int index) { + CEF_VALUE_VERIFY_RETURN(false, NULL); + + const base::Value* out_value = NULL; + + if (const_value().Get(index, &out_value) && + out_value->IsType(base::Value::TYPE_LIST)) { + base::ListValue* list_value = + static_cast(const_cast(out_value)); + return CefListValueImpl::GetOrCreateRef( + list_value, + const_cast(&const_value()), + read_only(), + controller()); + } + + return NULL; +} + +bool CefListValueImpl::SetNull(int index) { + CEF_VALUE_VERIFY_RETURN(true, false); + base::Value* new_value = base::Value::CreateNullValue(); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetBool(int index, bool value) { + CEF_VALUE_VERIFY_RETURN(true, false); + base::Value* new_value = base::Value::CreateBooleanValue(value); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetInt(int index, int value) { + CEF_VALUE_VERIFY_RETURN(true, false); + base::Value* new_value = base::Value::CreateIntegerValue(value); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetDouble(int index, double value) { + CEF_VALUE_VERIFY_RETURN(true, false); + base::Value* new_value = base::Value::CreateDoubleValue(value); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetString(int index, const CefString& value) { + CEF_VALUE_VERIFY_RETURN(true, false); + base::Value* new_value = base::Value::CreateStringValue(value.ToString()); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetBinary(int index, CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + + CefBinaryValueImpl* impl = static_cast(value.get()); + DCHECK(impl); + + base::Value* new_value = impl->CopyOrDetachValue(controller()); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetDictionary(int index, + CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + + CefDictionaryValueImpl* impl = + static_cast(value.get()); + DCHECK(impl); + + base::Value* new_value = impl->CopyOrDetachValue(controller()); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::SetList(int index, CefRefPtr value) { + CEF_VALUE_VERIFY_RETURN(true, false); + + CefListValueImpl* impl = static_cast(value.get()); + DCHECK(impl); + + base::Value* new_value = impl->CopyOrDetachValue(controller()); + if (RemoveInternal(index)) + mutable_value()->Insert(index, new_value); + else + mutable_value()->Set(index, new_value); + return true; +} + +bool CefListValueImpl::RemoveInternal(int index) { + scoped_ptr out_value; + if (!mutable_value()->Remove(index, &out_value)) + return false; + + // Remove the value. + controller()->Remove(out_value.get(), true); + + // Only list and dictionary types may have dependencies. + if (out_value->IsType(base::Value::TYPE_LIST) || + out_value->IsType(base::Value::TYPE_DICTIONARY)) { + controller()->RemoveDependencies(out_value.get()); + } + + return true; +} + +CefListValueImpl::CefListValueImpl( + base::ListValue* value, + void* parent_value, + ValueMode value_mode, + bool read_only, + CefValueController* controller) + : CefValueBase( + value, parent_value, value_mode, read_only, controller) { +} diff --git a/libcef/common/values_impl.h b/libcef/common/values_impl.h new file mode 100644 index 000000000..2148c1b13 --- /dev/null +++ b/libcef/common/values_impl.h @@ -0,0 +1,209 @@ +// 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_LIBCEF_COMMON_VALUES_IMPL_H_ +#define CEF_LIBCEF_COMMON_VALUES_IMPL_H_ +#pragma once + +#include + +#include "include/cef_values.h" +#include "libcef/common/value_base.h" + +#include "base/values.h" +#include "base/threading/platform_thread.h" + + +// CefBinaryValue implementation +class CefBinaryValueImpl + : public CefValueBase { + public: + // Get or create a reference value. + static CefRefPtr GetOrCreateRef( + base::BinaryValue* value, + void* parent_value, + CefValueController* controller); + + // Simple constructor for referencing existing value objects. + CefBinaryValueImpl(base::BinaryValue* value, + bool will_delete, + bool read_only); + + // Return a copy of the value. + base::BinaryValue* CopyValue(); + + // If a reference return a copy of the value otherwise detach the value to the + // specified |new_controller|. + base::BinaryValue* CopyOrDetachValue(CefValueController* new_controller); + + // CefBinaryValue methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual size_t GetData(void* buffer, + size_t buffer_size, + size_t data_offset) OVERRIDE; + + private: + // See the CefValueBase constructor for usage. Binary values are always + // read-only. + CefBinaryValueImpl(base::BinaryValue* value, + void* parent_value, + ValueMode value_mode, + CefValueController* controller); + // If |copy| is false this object will take ownership of the specified |data| + // buffer instead of copying it. + CefBinaryValueImpl(char* data, + size_t data_size, + bool copy); + + // For the Create() method. + friend class CefBinaryValue; + + DISALLOW_COPY_AND_ASSIGN(CefBinaryValueImpl); +}; + + +// CefDictionaryValue implementation +class CefDictionaryValueImpl + : public CefValueBase { + public: + // Get or create a reference value. + static CefRefPtr GetOrCreateRef( + base::DictionaryValue* value, + void* parent_value, + bool read_only, + CefValueController* controller); + + // Simple constructor for referencing existing value objects. + CefDictionaryValueImpl(base::DictionaryValue* value, + bool will_delete, + bool read_only); + + // Return a copy of the value. + base::DictionaryValue* CopyValue(); + + // If a reference return a copy of the value otherwise detach the value to the + // specified |new_controller|. + base::DictionaryValue* CopyOrDetachValue(CefValueController* new_controller); + + // CefDictionaryValue methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy( + bool exclude_empty_children) OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual bool Clear() OVERRIDE; + virtual bool HasKey(const CefString& key) OVERRIDE; + virtual bool GetKeys(KeyList& keys) OVERRIDE; + virtual bool Remove(const CefString& key) OVERRIDE; + virtual CefValueType GetType(const CefString& key) OVERRIDE; + virtual bool GetBool(const CefString& key) OVERRIDE; + virtual int GetInt(const CefString& key) OVERRIDE; + virtual double GetDouble(const CefString& key) OVERRIDE; + virtual CefString GetString(const CefString& key) OVERRIDE; + virtual CefRefPtr GetBinary(const CefString& key) OVERRIDE; + virtual CefRefPtr GetDictionary( + const CefString& key) OVERRIDE; + virtual CefRefPtr GetList(const CefString& key) OVERRIDE; + virtual bool SetNull(const CefString& key) OVERRIDE; + virtual bool SetBool(const CefString& key, bool value) OVERRIDE; + virtual bool SetInt(const CefString& key, int value) OVERRIDE; + virtual bool SetDouble(const CefString& key, double value) OVERRIDE; + virtual bool SetString(const CefString& key, + const CefString& value) OVERRIDE; + virtual bool SetBinary(const CefString& key, + CefRefPtr value) OVERRIDE; + virtual bool SetDictionary(const CefString& key, + CefRefPtr value) OVERRIDE; + virtual bool SetList(const CefString& key, + CefRefPtr value) OVERRIDE; + + private: + // See the CefValueBase constructor for usage. + CefDictionaryValueImpl(base::DictionaryValue* value, + void* parent_value, + ValueMode value_mode, + bool read_only, + CefValueController* controller); + + bool RemoveInternal(const CefString& key); + + // For the Create() method. + friend class CefDictionaryValue; + + DISALLOW_COPY_AND_ASSIGN(CefDictionaryValueImpl); +}; + + +// CefListValue implementation +class CefListValueImpl + : public CefValueBase { + public: + // Get or create a reference value. + static CefRefPtr GetOrCreateRef( + base::ListValue* value, + void* parent_value, + bool read_only, + CefValueController* controller); + + // Simple constructor for referencing existing value objects. + CefListValueImpl(base::ListValue* value, + bool will_delete, + bool read_only); + + // Return a copy of the value. + base::ListValue* CopyValue(); + + // If a reference return a copy of the value otherwise detach the value to the + // specified |new_controller|. + base::ListValue* CopyOrDetachValue(CefValueController* new_controller); + + /// CefListValue methods. + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual bool SetSize(size_t size) OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual bool Clear() OVERRIDE; + virtual bool Remove(int index) OVERRIDE; + virtual CefValueType GetType(int index) OVERRIDE; + virtual bool GetBool(int index) OVERRIDE; + virtual int GetInt(int index) OVERRIDE; + virtual double GetDouble(int index) OVERRIDE; + virtual CefString GetString(int index) OVERRIDE; + virtual CefRefPtr GetBinary(int index) OVERRIDE; + virtual CefRefPtr GetDictionary(int index) OVERRIDE; + virtual CefRefPtr GetList(int index) OVERRIDE; + virtual bool SetNull(int index) OVERRIDE; + virtual bool SetBool(int index, bool value) OVERRIDE; + virtual bool SetInt(int index, int value) OVERRIDE; + virtual bool SetDouble(int index, double value) OVERRIDE; + virtual bool SetString(int index, const CefString& value) OVERRIDE; + virtual bool SetBinary(int index, CefRefPtr value) OVERRIDE; + virtual bool SetDictionary(int index, + CefRefPtr value) OVERRIDE; + virtual bool SetList(int index, CefRefPtr value) OVERRIDE; + + private: + // See the CefValueBase constructor for usage. + CefListValueImpl(base::ListValue* value, + void* parent_value, + ValueMode value_mode, + bool read_only, + CefValueController* controller); + + bool RemoveInternal(int index); + + // For the Create() method. + friend class CefListValue; + + DISALLOW_COPY_AND_ASSIGN(CefListValueImpl); +}; + + +#endif // CEF_LIBCEF_COMMON_VALUES_IMPL_H_ diff --git a/libcef/renderer/browser_impl.cc b/libcef/renderer/browser_impl.cc new file mode 100644 index 000000000..035365844 --- /dev/null +++ b/libcef/renderer/browser_impl.cc @@ -0,0 +1,833 @@ +// Copyright (c) 2012 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 "libcef/renderer/browser_impl.h" + +#include +#include + +#include "libcef/common/cef_messages.h" +#include "libcef/common/content_client.h" +#include "libcef/common/process_message_impl.h" +#include "libcef/common/response_manager.h" +#include "libcef/renderer/content_renderer_client.h" +#include "libcef/renderer/dom_document_impl.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/renderer/webkit_glue.h" + +#include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/renderer/document_state.h" +#include "content/public/renderer/navigation_state.h" +#include "content/public/renderer/render_view.h" +#include "content/renderer/render_view_impl.h" +#include "net/http/http_util.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebURLError.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" +#include "third_party/WebKit/public/web/WebDataSource.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebNode.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" +#include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "third_party/WebKit/public/web/WebView.h" + +using blink::WebFrame; +using blink::WebScriptSource; +using blink::WebString; +using blink::WebURL; +using blink::WebView; + +namespace { + +blink::WebString FilePathStringToWebString( + const base::FilePath::StringType& str) { +#if defined(OS_POSIX) + return base::WideToUTF16(base::SysNativeMBToWide(str)); +#elif defined(OS_WIN) + return base::WideToUTF16(str); +#endif +} + +} // namespace + + +// CefBrowserImpl static methods. +// ----------------------------------------------------------------------------- + +// static +CefRefPtr CefBrowserImpl::GetBrowserForView( + content::RenderView* view) { + return CefContentRendererClient::Get()->GetBrowserForView(view); +} + +// static +CefRefPtr CefBrowserImpl::GetBrowserForMainFrame( + blink::WebFrame* frame) { + return CefContentRendererClient::Get()->GetBrowserForMainFrame(frame); +} + + +// CefBrowser methods. +// ----------------------------------------------------------------------------- + +CefRefPtr CefBrowserImpl::GetHost() { + NOTREACHED() << "GetHost cannot be called from the render process"; + return NULL; +} + +bool CefBrowserImpl::CanGoBack() { + CEF_REQUIRE_RT_RETURN(false); + + return webkit_glue::CanGoBack(render_view()->GetWebView()); +} + +void CefBrowserImpl::GoBack() { + CEF_REQUIRE_RT_RETURN_VOID(); + + webkit_glue::GoBack(render_view()->GetWebView()); +} + +bool CefBrowserImpl::CanGoForward() { + CEF_REQUIRE_RT_RETURN(false); + + return webkit_glue::CanGoForward(render_view()->GetWebView()); +} + +void CefBrowserImpl::GoForward() { + CEF_REQUIRE_RT_RETURN_VOID(); + + webkit_glue::GoForward(render_view()->GetWebView()); +} + +bool CefBrowserImpl::IsLoading() { + CEF_REQUIRE_RT_RETURN(false); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + return render_view()->GetWebView()->mainFrame()->isLoading(); + return false; +} + +void CefBrowserImpl::Reload() { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + render_view()->GetWebView()->mainFrame()->reload(false); +} + +void CefBrowserImpl::ReloadIgnoreCache() { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + render_view()->GetWebView()->mainFrame()->reload(true); +} + +void CefBrowserImpl::StopLoad() { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + render_view()->GetWebView()->mainFrame()->stopLoading(); +} + +int CefBrowserImpl::GetIdentifier() { + CEF_REQUIRE_RT_RETURN(0); + + return browser_id(); +} + +bool CefBrowserImpl::IsSame(CefRefPtr that) { + CEF_REQUIRE_RT_RETURN(false); + + CefBrowserImpl* impl = static_cast(that.get()); + return (impl == this); +} + +bool CefBrowserImpl::IsPopup() { + CEF_REQUIRE_RT_RETURN(false); + + return is_popup(); +} + +bool CefBrowserImpl::HasDocument() { + CEF_REQUIRE_RT_RETURN(false); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + return !render_view()->GetWebView()->mainFrame()->document().isNull(); + return false; +} + +CefRefPtr CefBrowserImpl::GetMainFrame() { + CEF_REQUIRE_RT_RETURN(NULL); + + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + return GetWebFrameImpl(render_view()->GetWebView()->mainFrame()).get(); + return NULL; +} + +CefRefPtr CefBrowserImpl::GetFocusedFrame() { + CEF_REQUIRE_RT_RETURN(NULL); + + if (render_view()->GetWebView() && + render_view()->GetWebView()->focusedFrame()) { + return GetWebFrameImpl(render_view()->GetWebView()->focusedFrame()).get(); + } + return NULL; +} + +CefRefPtr CefBrowserImpl::GetFrame(int64 identifier) { + CEF_REQUIRE_RT_RETURN(NULL); + + return GetWebFrameImpl(identifier).get(); +} + +CefRefPtr CefBrowserImpl::GetFrame(const CefString& name) { + CEF_REQUIRE_RT_RETURN(NULL); + + if (render_view()->GetWebView()) { + WebFrame* frame = + render_view()->GetWebView()->findFrameByName(name.ToString16()); + if (frame) + return GetWebFrameImpl(frame).get(); + } + + return NULL; +} + +size_t CefBrowserImpl::GetFrameCount() { + CEF_REQUIRE_RT_RETURN(0); + + int count = 0; + + if (render_view()->GetWebView()) { + WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); + if (main_frame) { + WebFrame* cur = main_frame; + do { + count++; + cur = cur->traverseNext(true); + } while (cur != main_frame); + } + } + + return count; +} + +void CefBrowserImpl::GetFrameIdentifiers(std::vector& identifiers) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (render_view()->GetWebView()) { + WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); + if (main_frame) { + WebFrame* cur = main_frame; + do { + identifiers.push_back(webkit_glue::GetIdentifier(cur)); + cur = cur->traverseNext(true); + } while (cur != main_frame); + } + } +} + +void CefBrowserImpl::GetFrameNames(std::vector& names) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (render_view()->GetWebView()) { + WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); + if (main_frame) { + WebFrame* cur = main_frame; + do { + names.push_back(CefString(cur->uniqueName().utf8())); + cur = cur->traverseNext(true); + } while (cur != main_frame); + } + } +} + +bool CefBrowserImpl::SendProcessMessage(CefProcessId target_process, + CefRefPtr message) { + Cef_Request_Params params; + CefProcessMessageImpl* impl = + static_cast(message.get()); + if (impl->CopyTo(params)) { + return SendProcessMessage(target_process, params.name, ¶ms.arguments, + true); + } + + return false; +} + + +// CefBrowserImpl public methods. +// ----------------------------------------------------------------------------- + +CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view, + int browser_id, + bool is_popup, + bool is_windowless) + : content::RenderViewObserver(render_view), + browser_id_(browser_id), + is_popup_(is_popup), + is_windowless_(is_windowless), + last_focused_frame_id_(webkit_glue::kInvalidFrameId) { + response_manager_.reset(new CefResponseManager); +} + +CefBrowserImpl::~CefBrowserImpl() { +} + +void CefBrowserImpl::LoadRequest(const CefMsg_LoadRequest_Params& params) { + CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); + if (!framePtr.get()) + return; + + WebFrame* web_frame = framePtr->web_frame(); + + blink::WebURLRequest request(params.url); + + // DidCreateDataSource checks for this value. + request.setRequestorID(-1); + + if (!params.method.empty()) + request.setHTTPMethod(base::ASCIIToUTF16(params.method)); + + if (params.referrer.is_valid()) { + WebString referrer = blink::WebSecurityPolicy::generateReferrerHeader( + static_cast(params.referrer_policy), + params.url, + WebString::fromUTF8(params.referrer.spec())); + if (!referrer.isEmpty()) + request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer); + } + + if (params.first_party_for_cookies.is_valid()) + request.setFirstPartyForCookies(params.first_party_for_cookies); + + if (!params.headers.empty()) { + for (net::HttpUtil::HeadersIterator i(params.headers.begin(), + params.headers.end(), "\n"); + i.GetNext(); ) { + request.addHTTPHeaderField(WebString::fromUTF8(i.name()), + WebString::fromUTF8(i.values())); + } + } + + if (params.upload_data.get()) { + base::string16 method = request.httpMethod(); + if (method == base::ASCIIToUTF16("GET") || + method == base::ASCIIToUTF16("HEAD")) { + request.setHTTPMethod(base::ASCIIToUTF16("POST")); + } + + if (request.httpHeaderField( + base::ASCIIToUTF16("Content-Type")).length() == 0) { + request.setHTTPHeaderField( + base::ASCIIToUTF16("Content-Type"), + base::ASCIIToUTF16("application/x-www-form-urlencoded")); + } + + blink::WebHTTPBody body; + body.initialize(); + + const ScopedVector& elements = + params.upload_data->elements(); + ScopedVector::const_iterator it = + elements.begin(); + for (; it != elements.end(); ++it) { + const net::UploadElement& element = **it; + if (element.type() == net::UploadElement::TYPE_BYTES) { + blink::WebData data; + data.assign(element.bytes(), element.bytes_length()); + body.appendData(data); + } else if (element.type() == net::UploadElement::TYPE_FILE) { + body.appendFile(FilePathStringToWebString(element.file_path().value())); + } else { + NOTREACHED(); + } + } + + request.setHTTPBody(body); + } + + web_frame->loadRequest(request); +} + +bool CefBrowserImpl::SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated) { + DCHECK_EQ(PID_BROWSER, target_process); + DCHECK(!name.empty()); + + Cef_Request_Params params; + params.name = name; + if (arguments) + params.arguments.Swap(arguments); + params.frame_id = -1; + params.user_initiated = user_initiated; + params.request_id = -1; + params.expect_response = false; + + return Send(new CefHostMsg_Request(routing_id(), params)); +} + +CefRefPtr CefBrowserImpl::GetWebFrameImpl( + blink::WebFrame* frame) { + DCHECK(frame); + int64 frame_id = webkit_glue::GetIdentifier(frame); + + // Frames are re-used between page loads. Only add the frame to the map once. + FrameMap::const_iterator it = frames_.find(frame_id); + if (it != frames_.end()) + return it->second; + + CefRefPtr framePtr(new CefFrameImpl(this, frame)); + frames_.insert(std::make_pair(frame_id, framePtr)); + + int64 parent_id = frame->parent() == NULL ? + webkit_glue::kInvalidFrameId : webkit_glue::GetIdentifier(frame->parent()); + base::string16 name = frame->uniqueName(); + + // Notify the browser that the frame has been identified. + Send(new CefHostMsg_FrameIdentified(routing_id(), frame_id, parent_id, name)); + + return framePtr; +} + +CefRefPtr CefBrowserImpl::GetWebFrameImpl(int64 frame_id) { + if (frame_id == webkit_glue::kInvalidFrameId) { + if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) + return GetWebFrameImpl(render_view()->GetWebView()->mainFrame()); + return NULL; + } + + // Check if we already know about the frame. + FrameMap::const_iterator it = frames_.find(frame_id); + if (it != frames_.end()) + return it->second; + + if (render_view()->GetWebView()) { + // Check if the frame exists but we don't know about it yet. + WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); + if (main_frame) { + WebFrame* cur = main_frame; + do { + if (webkit_glue::GetIdentifier(cur) == frame_id) + return GetWebFrameImpl(cur); + cur = cur->traverseNext(true); + } while (cur != main_frame); + } + } + + return NULL; +} + +void CefBrowserImpl::AddFrameObject(int64 frame_id, + CefTrackNode* tracked_object) { + CefRefPtr manager; + + if (!frame_objects_.empty()) { + FrameObjectMap::const_iterator it = frame_objects_.find(frame_id); + if (it != frame_objects_.end()) + manager = it->second; + } + + if (!manager.get()) { + manager = new CefTrackManager(); + frame_objects_.insert(std::make_pair(frame_id, manager)); + } + + manager->Add(tracked_object); +} + +bool CefBrowserImpl::is_swapped_out() const { + content::RenderViewImpl* render_view_impl = + static_cast(render_view()); + return (!render_view_impl || render_view_impl->is_swapped_out()); +} + + +// RenderViewObserver methods. +// ----------------------------------------------------------------------------- + +void CefBrowserImpl::OnDestruct() { + // Notify that the browser window has been destroyed. + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) + handler->OnBrowserDestroyed(this); + } + + response_manager_.reset(NULL); + + CefContentRendererClient::Get()->OnBrowserDestroyed(this); +} + +void CefBrowserImpl::DidStartLoading() { + OnLoadingStateChange(true); +} + +void CefBrowserImpl::DidStopLoading() { + OnLoadingStateChange(false); +} + +void CefBrowserImpl::DidFailLoad( + blink::WebLocalFrame* frame, + const blink::WebURLError& error) { + OnLoadError(frame, error); + OnLoadEnd(frame); +} + +void CefBrowserImpl::DidFinishLoad(blink::WebLocalFrame* frame) { + blink::WebDataSource* ds = frame->dataSource(); + Send(new CefHostMsg_DidFinishLoad(routing_id(), + webkit_glue::GetIdentifier(frame), + ds->request().url(), + !frame->parent(), + ds->response().httpStatusCode())); + OnLoadEnd(frame); +} + +void CefBrowserImpl::DidStartProvisionalLoad(blink::WebLocalFrame* frame) { + // Send the frame creation notification if necessary. + GetWebFrameImpl(frame); +} + +void CefBrowserImpl::DidFailProvisionalLoad( + blink::WebLocalFrame* frame, + const blink::WebURLError& error) { + OnLoadError(frame, error); +} + +void CefBrowserImpl::DidCommitProvisionalLoad(blink::WebLocalFrame* frame, + bool is_new_navigation) { + OnLoadStart(frame); +} + +void CefBrowserImpl::FrameDetached(WebFrame* frame) { + int64 frame_id = webkit_glue::GetIdentifier(frame); + + if (!frames_.empty()) { + // Remove the frame from the map. + FrameMap::iterator it = frames_.find(frame_id); + if (it != frames_.end()) { + it->second->Detach(); + frames_.erase(it); + } + } + + if (!frame_objects_.empty()) { + // Remove any tracked objects associated with the frame. + FrameObjectMap::iterator it = frame_objects_.find(frame_id); + if (it != frame_objects_.end()) + frame_objects_.erase(it); + } + + // Notify the browser that the frame has detached. + Send(new CefHostMsg_FrameDetached(routing_id(), frame_id)); +} + +void CefBrowserImpl::FocusedNodeChanged(const blink::WebNode& node) { + // Notify the handler. + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + if (node.isNull()) { + handler->OnFocusedNodeChanged(this, GetFocusedFrame(), NULL); + } else { + const blink::WebDocument& document = node.document(); + if (!document.isNull()) { + blink::WebFrame* frame = document.frame(); + CefRefPtr documentImpl = + new CefDOMDocumentImpl(this, frame); + handler->OnFocusedNodeChanged(this, + GetWebFrameImpl(frame).get(), + documentImpl->GetOrCreateNode(node)); + documentImpl->Detach(); + } + } + } + } + + // TODO(cef): This method is being used as a work-around for identifying frame + // focus changes. The ideal approach would be implementating delegation from + // ChromeClientImpl::focusedFrameChanged(). + + WebFrame* focused_frame = NULL; + + // Try to identify the focused frame from the node. + if (!node.isNull()) { + const blink::WebDocument& document = node.document(); + if (!document.isNull()) + focused_frame = document.frame(); + } + + if (focused_frame == NULL && render_view()->GetWebView()) { + // Try to identify the global focused frame. + focused_frame = render_view()->GetWebView()->focusedFrame(); + } + + int64 frame_id = webkit_glue::kInvalidFrameId; + if (focused_frame != NULL) + frame_id = webkit_glue::GetIdentifier(focused_frame); + + // Don't send a message if the focused frame has not changed. + if (frame_id == last_focused_frame_id_) + return; + + last_focused_frame_id_ = frame_id; + Send(new CefHostMsg_FrameFocusChange(routing_id(), frame_id)); +} + +void CefBrowserImpl::DidCreateDataSource(blink::WebLocalFrame* frame, + blink::WebDataSource* ds) { + const blink::WebURLRequest& request = ds->request(); + if (request.requestorID() == -1) { + // Mark the request as browser-initiated so + // RenderViewImpl::decidePolicyForNavigation won't attempt to fork it. + content::DocumentState* document_state = + content::DocumentState::FromDataSource(ds); + document_state->set_navigation_state( + content::NavigationState::CreateBrowserInitiated(-1, -1, false, + content::PAGE_TRANSITION_LINK)); + } + + if (frame->parent() == 0) { + GURL url = ds->request().url(); + if (!url.is_empty()) { + // Notify that the loading URL has changed. + Send(new CefHostMsg_LoadingURLChange(routing_id(), url)); + } + } +} + +bool CefBrowserImpl::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CefBrowserImpl, message) + IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest) + IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse) + IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck) + IPC_MESSAGE_HANDLER(CefMsg_LoadRequest, LoadRequest) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + + +// RenderViewObserver::OnMessageReceived message handlers. +// ----------------------------------------------------------------------------- + +void CefBrowserImpl::OnRequest(const Cef_Request_Params& params) { + bool success = false; + std::string response; + bool expect_response_ack = false; + + TRACE_EVENT2("libcef", "CefBrowserImpl::OnRequest", + "request_id", params.request_id, + "expect_response", params.expect_response ? 1 : 0); + + if (params.user_initiated) { + // Give the user a chance to handle the request. + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr message( + new CefProcessMessageImpl(const_cast(¶ms), + false, true)); + success = handler->OnProcessMessageReceived(this, PID_BROWSER, + message.get()); + message->Detach(NULL); + } + } + } else if (params.name == "execute-code") { + // Execute code. + CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); + if (framePtr.get()) { + WebFrame* web_frame = framePtr->web_frame(); + if (web_frame) { + DCHECK_EQ(params.arguments.GetSize(), (size_t)4); + + bool is_javascript = false; + std::string code, script_url; + int script_start_line = 0; + + params.arguments.GetBoolean(0, &is_javascript); + params.arguments.GetString(1, &code); + DCHECK(!code.empty()); + params.arguments.GetString(2, &script_url); + params.arguments.GetInteger(3, &script_start_line); + DCHECK_GE(script_start_line, 0); + + if (is_javascript) { + web_frame->executeScript( + WebScriptSource(base::UTF8ToUTF16(code), + GURL(script_url), + script_start_line)); + success = true; + } else { + // TODO(cef): implement support for CSS code. + NOTIMPLEMENTED(); + } + } + } + } else if (params.name == "execute-command") { + // Execute command. + CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); + if (framePtr.get()) { + WebFrame* web_frame = framePtr->web_frame(); + if (web_frame) { + DCHECK_EQ(params.arguments.GetSize(), (size_t)1); + + std::string command; + + params.arguments.GetString(0, &command); + DCHECK(!command.empty()); + + if (LowerCaseEqualsASCII(command, "getsource")) { + response = web_frame->contentAsMarkup().utf8(); + success = true; + } else if (LowerCaseEqualsASCII(command, "gettext")) { + response = webkit_glue::DumpDocumentText(web_frame); + success = true; + } else if (web_frame->executeCommand(base::UTF8ToUTF16(command))) { + success = true; + } + } + } + } else if (params.name == "load-string") { + // Load a string. + CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); + if (framePtr.get()) { + WebFrame* web_frame = framePtr->web_frame(); + if (web_frame) { + DCHECK_EQ(params.arguments.GetSize(), (size_t)2); + + std::string string, url; + + params.arguments.GetString(0, &string); + params.arguments.GetString(1, &url); + + web_frame->loadHTMLString(string, GURL(url)); + } + } + } else { + // Invalid request. + NOTREACHED(); + } + + if (params.expect_response) { + DCHECK_GE(params.request_id, 0); + + // Send a response to the browser. + Cef_Response_Params response_params; + response_params.request_id = params.request_id; + response_params.success = success; + response_params.response = response; + response_params.expect_response_ack = expect_response_ack; + Send(new CefHostMsg_Response(routing_id(), response_params)); + } +} + +void CefBrowserImpl::OnResponse(const Cef_Response_Params& params) { + response_manager_->RunHandler(params); + if (params.expect_response_ack) + Send(new CefHostMsg_ResponseAck(routing_id(), params.request_id)); +} + +void CefBrowserImpl::OnResponseAck(int request_id) { + response_manager_->RunAckHandler(request_id); +} + +void CefBrowserImpl::OnLoadingStateChange(bool isLoading) { + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + WebView* web_view = render_view()->GetWebView(); + const bool canGoBack = webkit_glue::CanGoBack(web_view); + const bool canGoForward = webkit_glue::CanGoForward(web_view); + + load_handler->OnLoadingStateChange(this, isLoading, canGoBack, + canGoForward); + } + } + } +} + +void CefBrowserImpl::OnLoadStart(blink::WebLocalFrame* frame) { + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + load_handler->OnLoadStart(this, cef_frame.get()); + } + } + } +} + +void CefBrowserImpl::OnLoadEnd(blink::WebLocalFrame* frame) { + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + int httpStatusCode = frame->dataSource()->response().httpStatusCode(); + load_handler->OnLoadEnd(this, cef_frame.get(), httpStatusCode); + } + } + } +} + +void CefBrowserImpl::OnLoadError(blink::WebLocalFrame* frame, + const blink::WebURLError& error) { + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + const cef_errorcode_t errorCode = + static_cast(error.reason); + const std::string& errorText = error.localizedDescription.utf8(); + const GURL& failedUrl = error.unreachableURL; + load_handler->OnLoadError(this, cef_frame.get(), errorCode, errorText, + failedUrl.spec()); + } + } + } +} diff --git a/libcef/renderer/browser_impl.h b/libcef/renderer/browser_impl.h new file mode 100644 index 000000000..fd3c26c55 --- /dev/null +++ b/libcef/renderer/browser_impl.h @@ -0,0 +1,163 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_RENDERER_BROWSER_IMPL_H_ +#define CEF_LIBCEF_RENDERER_BROWSER_IMPL_H_ +#pragma once + +#include +#include +#include + +#include "include/cef_browser.h" +#include "include/cef_client.h" +#include "libcef/common/tracker.h" +#include "libcef/renderer/frame_impl.h" + +#include "base/memory/scoped_ptr.h" +#include "content/public/renderer/render_view_observer.h" + +class GURL; +struct CefMsg_LoadRequest_Params; +struct Cef_Request_Params; +struct Cef_Response_Params; +class CefContentRendererClient; +class CefResponseManager; + +namespace base { +class ListValue; +} + +// Renderer plumbing for CEF features. There is a one-to-one relationship +// between RenderView on the renderer side and RenderViewHost on the browser +// side. +// +// RenderViewObserver: Interface for observing RenderView notifications and IPC +// messages. IPC messages received by the RenderView will be forwarded to this +// RenderViewObserver implementation. IPC messages sent using +// RenderViewObserver::Send() will be forwarded to the RenderView. Use +// RenderViewObserver::routing_id() when sending IPC messages. +class CefBrowserImpl : public CefBrowser, + public content::RenderViewObserver { + public: + // Returns the browser associated with the specified RenderView. + static CefRefPtr GetBrowserForView(content::RenderView* view); + // Returns the browser associated with the specified main WebFrame. + static CefRefPtr GetBrowserForMainFrame( + blink::WebFrame* frame); + + // CefBrowser methods. + virtual CefRefPtr GetHost() OVERRIDE; + virtual bool CanGoBack() OVERRIDE; + virtual void GoBack() OVERRIDE; + virtual bool CanGoForward() OVERRIDE; + virtual void GoForward() OVERRIDE; + virtual bool IsLoading() OVERRIDE; + virtual void Reload() OVERRIDE; + virtual void ReloadIgnoreCache() OVERRIDE; + virtual void StopLoad() OVERRIDE; + virtual int GetIdentifier() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool IsPopup() OVERRIDE; + virtual bool HasDocument() OVERRIDE; + virtual CefRefPtr GetMainFrame() OVERRIDE; + virtual CefRefPtr GetFocusedFrame() OVERRIDE; + virtual CefRefPtr GetFrame(int64 identifier) OVERRIDE; + virtual CefRefPtr GetFrame(const CefString& name) OVERRIDE; + virtual size_t GetFrameCount() OVERRIDE; + virtual void GetFrameIdentifiers(std::vector& identifiers) OVERRIDE; + virtual void GetFrameNames(std::vector& names) OVERRIDE; + virtual bool SendProcessMessage( + CefProcessId target_process, + CefRefPtr message) OVERRIDE; + + CefBrowserImpl(content::RenderView* render_view, + int browser_id, + bool is_popup, + bool is_windowless); + virtual ~CefBrowserImpl(); + + void LoadRequest(const CefMsg_LoadRequest_Params& params); + + // Avoids unnecessary string type conversions. + bool SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated); + + // Returns the matching CefFrameImpl reference or creates a new one. + CefRefPtr GetWebFrameImpl(blink::WebFrame* frame); + CefRefPtr GetWebFrameImpl(int64 frame_id); + + // Frame objects will be deleted immediately before the frame is closed. + void AddFrameObject(int64 frame_id, CefTrackNode* tracked_object); + + int browser_id() const { return browser_id_; } + bool is_popup() const { return is_popup_; } + bool is_windowless() const { return is_windowless_; } + content::RenderView* render_view() const { + return content::RenderViewObserver::render_view(); + } + + bool is_swapped_out() const; + + private: + // RenderViewObserver methods. + virtual void OnDestruct() OVERRIDE; + virtual void DidStartLoading() OVERRIDE; + virtual void DidStopLoading() OVERRIDE; + virtual void DidFailLoad(blink::WebLocalFrame* frame, + const blink::WebURLError& error) OVERRIDE; + virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE; + virtual void DidStartProvisionalLoad(blink::WebLocalFrame* frame) OVERRIDE; + virtual void DidFailProvisionalLoad( + blink::WebLocalFrame* frame, + const blink::WebURLError& error) OVERRIDE; + virtual void DidCommitProvisionalLoad(blink::WebLocalFrame* frame, + bool is_new_navigation) OVERRIDE; + virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE; + virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE; + virtual void DidCreateDataSource(blink::WebLocalFrame* frame, + blink::WebDataSource* ds) OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // RenderViewObserver::OnMessageReceived message handlers. + void OnRequest(const Cef_Request_Params& params); + void OnResponse(const Cef_Response_Params& params); + void OnResponseAck(int request_id); + + void OnLoadingStateChange(bool isLoading); + void OnLoadStart(blink::WebLocalFrame* frame); + void OnLoadEnd(blink::WebLocalFrame* frame); + void OnLoadError(blink::WebLocalFrame* frame, + const blink::WebURLError& error); + + // ID of the browser that this RenderView is associated with. During loading + // of cross-origin requests multiple RenderViews may be associated with the + // same browser ID. + int browser_id_; + bool is_popup_; + bool is_windowless_; + + // Id of the last frame that had focus. + int64 last_focused_frame_id_; + + // Map of unique frame ids to CefFrameImpl references. + typedef std::map > FrameMap; + FrameMap frames_; + + // Map of unique frame ids to CefTrackManager objects that need to be cleaned + // up when the frame is deleted. + typedef std::map > FrameObjectMap; + FrameObjectMap frame_objects_; + + // Manages response registrations. + scoped_ptr response_manager_; + + IMPLEMENT_REFCOUNTING(CefBrowserImpl); + DISALLOW_COPY_AND_ASSIGN(CefBrowserImpl); +}; + +#endif // CEF_LIBCEF_RENDERER_BROWSER_IMPL_H_ diff --git a/libcef/renderer/content_renderer_client.cc b/libcef/renderer/content_renderer_client.cc new file mode 100644 index 000000000..4f0cfc36c --- /dev/null +++ b/libcef/renderer/content_renderer_client.cc @@ -0,0 +1,788 @@ +// Copyright (c) 2013 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 "base/compiler_specific.h" + +#include "config.h" +MSVC_PUSH_WARNING_LEVEL(0); +#include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8RecursionScope.h" +MSVC_POP_WARNING(); +#undef ceil +#undef FROM_HERE +#undef LOG + +#include "libcef/renderer/content_renderer_client.h" + +#include "libcef/browser/context.h" +#include "libcef/common/cef_messages.h" +#include "libcef/common/cef_switches.h" +#include "libcef/common/content_client.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/values_impl.h" +#include "libcef/renderer/browser_impl.h" +#include "libcef/renderer/render_frame_observer.h" +#include "libcef/renderer/render_message_filter.h" +#include "libcef/renderer/render_process_observer.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/renderer/v8_impl.h" +#include "libcef/renderer/webkit_glue.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/renderer/loadtimes_extension_bindings.h" +#include "chrome/renderer/pepper/ppb_pdf_impl.h" +#include "chrome/renderer/printing/print_web_view_helper.h" +#include "content/child/child_thread.h" +#include "content/child/worker_task_runner.h" +#include "content/common/frame_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/content_constants.h" +#include "content/public/common/content_paths.h" +#include "content/public/renderer/render_thread.h" +#include "content/public/renderer/render_view.h" +#include "content/renderer/render_frame_impl.h" +#include "ipc/ipc_sync_channel.h" +#include "media/base/media.h" +#include "ppapi/c/private/ppb_pdf.h" +#include "third_party/WebKit/public/platform/WebPrerenderingSupport.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebWorkerRunLoop.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebPluginParams.h" +#include "third_party/WebKit/public/web/WebPrerendererClient.h" +#include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/WebKit/public/web/WebWorkerInfo.h" +#include "v8/include/v8.h" + +#if defined(OS_WIN) +#include "base/win/iat_patch_function.h" +#endif + +namespace { + +// Stub implementation of blink::WebPrerenderingSupport. +class CefPrerenderingSupport : public blink::WebPrerenderingSupport { + public: + virtual ~CefPrerenderingSupport() {} + + private: + virtual void add(const blink::WebPrerender& prerender) OVERRIDE {} + virtual void cancel(const blink::WebPrerender& prerender) OVERRIDE {} + virtual void abandon(const blink::WebPrerender& prerender) OVERRIDE {} +}; + +// Stub implementation of blink::WebPrerendererClient. +class CefPrerendererClient : public content::RenderViewObserver, + public blink::WebPrerendererClient { + public: + explicit CefPrerendererClient(content::RenderView* render_view) + : content::RenderViewObserver(render_view) { + DCHECK(render_view); + render_view->GetWebView()->setPrerendererClient(this); + } + + private: + virtual ~CefPrerendererClient() {} + + virtual void willAddPrerender(blink::WebPrerender* prerender) OVERRIDE {} +}; + +// Implementation of SequencedTaskRunner for WebWorker threads. +class CefWebWorkerTaskRunner : public base::SequencedTaskRunner, + public content::WorkerTaskRunner::Observer { + public: + CefWebWorkerTaskRunner(content::WorkerTaskRunner* runner, + int worker_id) + : runner_(runner), + worker_id_(worker_id) { + DCHECK(runner_); + DCHECK_GT(worker_id_, 0); + DCHECK(RunsTasksOnCurrentThread()); + + // Adds an observer for the current thread. + runner_->AddStopObserver(this); + } + + // SequencedTaskRunner methods: + virtual bool PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) OVERRIDE { + return PostDelayedTask(from_here, task, delay); + } + + // TaskRunner methods: + virtual bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) OVERRIDE { + if (delay != base::TimeDelta()) + LOG(WARNING) << "Delayed tasks are not supported on WebWorker threads"; + runner_->PostTask(worker_id_, task); + return true; + } + + virtual bool RunsTasksOnCurrentThread() const OVERRIDE { + return (runner_->CurrentWorkerId() == worker_id_); + } + + // WorkerTaskRunner::Observer methods: + virtual void OnWorkerRunLoopStopped() OVERRIDE { + CefContentRendererClient::Get()->RemoveWorkerTaskRunner(worker_id_); + } + + private: + content::WorkerTaskRunner* runner_; + int worker_id_; +}; + +#if defined(OS_WIN) +static base::win::IATPatchFunction g_iat_patch_createdca; +HDC WINAPI CreateDCAPatch(LPCSTR driver_name, + LPCSTR device_name, + LPCSTR output, + const void* init_data) { + DCHECK(std::string("DISPLAY") == std::string(driver_name)); + DCHECK(!device_name); + DCHECK(!output); + DCHECK(!init_data); + + // CreateDC fails behind the sandbox, but not CreateCompatibleDC. + return CreateCompatibleDC(NULL); +} + +static base::win::IATPatchFunction g_iat_patch_get_font_data; +DWORD WINAPI GetFontDataPatch(HDC hdc, + DWORD table, + DWORD offset, + LPVOID buffer, + DWORD length) { + int rv = GetFontData(hdc, table, offset, buffer, length); + if (rv == GDI_ERROR && hdc) { + HFONT font = static_cast(GetCurrentObject(hdc, OBJ_FONT)); + + LOGFONT logfont; + if (GetObject(font, sizeof(LOGFONT), &logfont)) { + std::vector font_data; + content::RenderThread::Get()->PreCacheFont(logfont); + rv = GetFontData(hdc, table, offset, buffer, length); + content::RenderThread::Get()->ReleaseCachedFonts(); + } + } + return rv; +} +#endif // OS_WIN + +} // namespace + +CefContentRendererClient::CefContentRendererClient() + : devtools_agent_count_(0), + uncaught_exception_stack_size_(0), + single_process_cleanup_complete_(false) { +} + +CefContentRendererClient::~CefContentRendererClient() { +} + +// static +CefContentRendererClient* CefContentRendererClient::Get() { + return static_cast( + CefContentClient::Get()->renderer()); +} + +CefRefPtr CefContentRendererClient::GetBrowserForView( + content::RenderView* view) { + CEF_REQUIRE_RT_RETURN(NULL); + + BrowserMap::const_iterator it = browsers_.find(view); + if (it != browsers_.end()) + return it->second; + return NULL; +} + +CefRefPtr CefContentRendererClient::GetBrowserForMainFrame( + blink::WebFrame* frame) { + CEF_REQUIRE_RT_RETURN(NULL); + + BrowserMap::const_iterator it = browsers_.begin(); + for (; it != browsers_.end(); ++it) { + content::RenderView* render_view = it->second->render_view(); + if (render_view && render_view->GetWebView() && + render_view->GetWebView()->mainFrame() == frame) { + return it->second; + } + } + + return NULL; +} + +void CefContentRendererClient::OnBrowserDestroyed(CefBrowserImpl* browser) { + BrowserMap::iterator it = browsers_.begin(); + for (; it != browsers_.end(); ++it) { + if (it->second.get() == browser) { + browsers_.erase(it); + return; + } + } + + // No browser was found in the map. + NOTREACHED(); +} + +void CefContentRendererClient::WebKitInitialized() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + // Create global objects associated with the default Isolate. + CefV8IsolateCreated(); + + blink::WebRuntimeFeatures::enableMediaPlayer( + media::IsMediaLibraryInitialized()); + + // TODO(cef): Enable these once the implementation supports it. + blink::WebRuntimeFeatures::enableNotifications(false); + + blink::WebRuntimeFeatures::enableMediaStream( + command_line.HasSwitch(switches::kEnableMediaStream)); + +#if defined(OS_WIN) + // Need to patch a few functions for font loading to work correctly. + // From chrome/renderer/chrome_render_process_observer.cc. + base::FilePath pdf; + if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) && + base::PathExists(pdf)) { + g_iat_patch_createdca.Patch( + pdf.value().c_str(), "gdi32.dll", "CreateDCA", CreateDCAPatch); + g_iat_patch_get_font_data.Patch( + pdf.value().c_str(), "gdi32.dll", "GetFontData", GetFontDataPatch); + } +#endif // defined(OS_WIN) + + const CefContentClient::SchemeInfoList* schemes = + CefContentClient::Get()->GetCustomSchemes(); + if (!schemes->empty()) { + // Register the custom schemes. + CefContentClient::SchemeInfoList::const_iterator it = schemes->begin(); + for (; it != schemes->end(); ++it) { + const CefContentClient::SchemeInfo& info = *it; + const blink::WebString& scheme = + blink::WebString::fromUTF8(info.scheme_name); + if (info.is_standard) { + // Standard schemes must also be registered as CORS enabled to support + // CORS-restricted requests (for example, XMLHttpRequest redirects). + blink::WebSecurityPolicy::registerURLSchemeAsCORSEnabled(scheme); + } + if (info.is_local) + blink::WebSecurityPolicy::registerURLSchemeAsLocal(scheme); + if (info.is_display_isolated) + blink::WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(scheme); + } + } + + if (!cross_origin_whitelist_entries_.empty()) { + // Add the cross-origin white list entries. + for (size_t i = 0; i < cross_origin_whitelist_entries_.size(); ++i) { + const Cef_CrossOriginWhiteListEntry_Params& entry = + cross_origin_whitelist_entries_[i]; + GURL gurl = GURL(entry.source_origin); + blink::WebSecurityPolicy::addOriginAccessWhitelistEntry( + gurl, + blink::WebString::fromUTF8(entry.target_protocol), + blink::WebString::fromUTF8(entry.target_domain), + entry.allow_target_subdomains); + } + cross_origin_whitelist_entries_.clear(); + } + + // The number of stack trace frames to capture for uncaught exceptions. + if (command_line.HasSwitch(switches::kUncaughtExceptionStackSize)) { + int uncaught_exception_stack_size = 0; + base::StringToInt( + command_line.GetSwitchValueASCII(switches::kUncaughtExceptionStackSize), + &uncaught_exception_stack_size); + + if (uncaught_exception_stack_size > 0) { + uncaught_exception_stack_size_ = uncaught_exception_stack_size; + CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_); + } + } + + // Notify the render process handler. + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) + handler->OnWebKitInitialized(); + } +} + +void CefContentRendererClient::OnRenderProcessShutdown() { + // Destroy global objects associated with the default Isolate. + CefV8IsolateDestroyed(); +} + +void CefContentRendererClient::DevToolsAgentAttached() { + CEF_REQUIRE_RT(); + ++devtools_agent_count_; +} + +void CefContentRendererClient::DevToolsAgentDetached() { + CEF_REQUIRE_RT(); + --devtools_agent_count_; + if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) { + // When the last DevToolsAgent is detached the stack size is set to 0. + // Restore the user-specified stack size here. + CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_); + + // And do the same for any WebWorker threads. + WorkerTaskRunnerMap map_copy; + + { + base::AutoLock lock_scope(worker_task_runner_lock_); + map_copy = worker_task_runner_map_; + } + + WorkerTaskRunnerMap::const_iterator it = map_copy.begin(); + for (; it != map_copy.end(); ++it) { + it->second->PostTask(FROM_HERE, + base::Bind(CefV8SetUncaughtExceptionStackSize, + uncaught_exception_stack_size_)); + } + } +} + +scoped_refptr + CefContentRendererClient::GetCurrentTaskRunner() { + // Check if currently on the render thread. + if (CEF_CURRENTLY_ON_RT()) + return render_task_runner_; + + // Check if a WebWorker exists for the current thread. + content::WorkerTaskRunner* worker_runner = + content::WorkerTaskRunner::Instance(); + int worker_id = worker_runner->CurrentWorkerId(); + if (worker_id > 0) { + base::AutoLock lock_scope(worker_task_runner_lock_); + WorkerTaskRunnerMap::const_iterator it = + worker_task_runner_map_.find(worker_id); + if (it != worker_task_runner_map_.end()) + return it->second; + + scoped_refptr task_runner = + new CefWebWorkerTaskRunner(worker_runner, worker_id); + worker_task_runner_map_[worker_id] = task_runner; + return task_runner; + } + + return NULL; +} + +scoped_refptr + CefContentRendererClient::GetWorkerTaskRunner(int worker_id) { + base::AutoLock lock_scope(worker_task_runner_lock_); + WorkerTaskRunnerMap::const_iterator it = + worker_task_runner_map_.find(worker_id); + if (it != worker_task_runner_map_.end()) + return it->second; + + return NULL; +} + +void CefContentRendererClient::RemoveWorkerTaskRunner(int worker_id) { + base::AutoLock lock_scope(worker_task_runner_lock_); + WorkerTaskRunnerMap::iterator it = worker_task_runner_map_.find(worker_id); + if (it != worker_task_runner_map_.end()) + worker_task_runner_map_.erase(it); +} + +void CefContentRendererClient::RunSingleProcessCleanup() { + DCHECK(content::RenderProcessHost::run_renderer_in_process()); + + // Make sure the render thread was actually started. + if (!render_task_runner_) + return; + + if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { + RunSingleProcessCleanupOnUIThread(); + } else { + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&CefContentRendererClient::RunSingleProcessCleanupOnUIThread, + base::Unretained(this))); + } + + // Wait for the render thread cleanup to complete. Spin instead of using + // base::WaitableEvent because calling Wait() is not allowed on the UI + // thread. + bool complete = false; + do { + { + base::AutoLock lock_scope(single_process_cleanup_lock_); + complete = single_process_cleanup_complete_; + } + if (!complete) + base::PlatformThread::YieldCurrentThread(); + } while (!complete); +} + +void CefContentRendererClient::RenderThreadStarted() { + render_task_runner_ = base::MessageLoopProxy::current(); + observer_.reset(new CefRenderProcessObserver()); + + content::RenderThread* thread = content::RenderThread::Get(); + thread->AddObserver(observer_.get()); + thread->GetChannel()->AddFilter(new CefRenderMessageFilter); + thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); + + if (content::RenderProcessHost::run_renderer_in_process()) { + // When running in single-process mode register as a destruction observer + // on the render thread's MessageLoop. + base::MessageLoop::current()->AddDestructionObserver(this); + } + + // Note that under Linux, the media library will normally already have + // been initialized by the Zygote before this instance became a Renderer. + base::FilePath media_path; + PathService::Get(content::DIR_MEDIA_LIBS, &media_path); + if (!media_path.empty()) + media::InitializeMediaLibrary(media_path); + + blink::WebPrerenderingSupport::initialize(new CefPrerenderingSupport()); + + // Retrieve the new render thread information synchronously. + CefProcessHostMsg_GetNewRenderThreadInfo_Params params; + thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(¶ms)); + + // Cross-origin entries need to be added after WebKit is initialized. + cross_origin_whitelist_entries_ = params.cross_origin_whitelist_entries; + + // Notify the render process handler. + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr listValuePtr( + new CefListValueImpl(¶ms.extra_info, false, true)); + handler->OnRenderThreadCreated(listValuePtr.get()); + listValuePtr->Detach(NULL); + } + } +} + +void CefContentRendererClient::RenderFrameCreated( + content::RenderFrame* render_frame) { + new CefRenderFrameObserver(render_frame); + BrowserCreated(render_frame->GetRenderView(), render_frame); +} + +void CefContentRendererClient::RenderViewCreated( + content::RenderView* render_view) { + BrowserCreated(render_view, render_view->GetMainRenderFrame()); +} + +bool CefContentRendererClient::OverrideCreatePlugin( + content::RenderFrame* render_frame, + blink::WebLocalFrame* frame, + const blink::WebPluginParams& params, + blink::WebPlugin** plugin) { + CefRefPtr browser = + CefBrowserImpl::GetBrowserForMainFrame(frame->top()); + if (!browser || !browser->is_windowless()) + return false; + +#if defined(ENABLE_PLUGINS) + if (base::UTF16ToASCII(params.mimeType) == content::kBrowserPluginMimeType) + return false; + + content::RenderFrameImpl* render_frame_impl = + static_cast(render_frame); + + content::WebPluginInfo info; + std::string mime_type; + bool found = false; + render_frame_impl->Send( + new FrameHostMsg_GetPluginInfo( + render_frame_impl->GetRoutingID(), + params.url, + frame->top()->document().url(), + params.mimeType.utf8(), + &found, + &info, + &mime_type)); + if (!found) + return false; + + bool flash = LowerCaseEqualsASCII(mime_type, + "application/x-shockwave-flash"); + bool silverlight = StartsWithASCII(mime_type, + "application/x-silverlight", false); + + if (flash) { + // "wmode" values of "opaque" or "transparent" are allowed. + size_t size = params.attributeNames.size(); + for (size_t i = 0; i < size; ++i) { + std::string name = params.attributeNames[i].utf8(); + if (name == "wmode") { + std::string value = params.attributeValues[i].utf8(); + if (value == "opaque" || value == "transparent") + flash = false; + break; + } + } + } + + if (flash || silverlight) { + // Force Flash and Silverlight plugins to use windowless mode. + blink::WebPluginParams params_to_use = params; + params_to_use.mimeType = blink::WebString::fromUTF8(mime_type); + + size_t size = params.attributeNames.size(); + blink::WebVector new_names(size+1), + new_values(size+1); + + for (size_t i = 0; i < size; ++i) { + new_names[i] = params.attributeNames[i]; + new_values[i] = params.attributeValues[i]; + } + + if (flash) { + new_names[size] = "wmode"; + new_values[size] = "opaque"; + } else if (silverlight) { + new_names[size] = "windowless"; + new_values[size] = "true"; + } + + params_to_use.attributeNames.swap(new_names); + params_to_use.attributeValues.swap(new_values); + + *plugin = render_frame_impl->CreatePlugin(frame, info, params_to_use); + return true; + } +#endif // defined(ENABLE_PLUGINS) + + return false; +} + +bool CefContentRendererClient::HandleNavigation( + content::RenderFrame* render_frame, + content::DocumentState* document_state, + int opener_id, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, + bool is_redirect) { + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr browserPtr = + CefBrowserImpl::GetBrowserForMainFrame(frame->top()); + DCHECK(browserPtr.get()); + if (browserPtr.get()) { + CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); + CefRefPtr requestPtr(CefRequest::Create()); + CefRequestImpl* requestImpl = + static_cast(requestPtr.get()); + requestImpl->Set(request); + requestImpl->SetReadOnly(true); + + cef_navigation_type_t navigation_type = NAVIGATION_OTHER; + switch (type) { + case blink::WebNavigationTypeLinkClicked: + navigation_type = NAVIGATION_LINK_CLICKED; + break; + case blink::WebNavigationTypeFormSubmitted: + navigation_type = NAVIGATION_FORM_SUBMITTED; + break; + case blink::WebNavigationTypeBackForward: + navigation_type = NAVIGATION_BACK_FORWARD; + break; + case blink::WebNavigationTypeReload: + navigation_type = NAVIGATION_RELOAD; + break; + case blink::WebNavigationTypeFormResubmitted: + navigation_type = NAVIGATION_FORM_RESUBMITTED; + break; + case blink::WebNavigationTypeOther: + navigation_type = NAVIGATION_OTHER; + break; + } + + if (handler->OnBeforeNavigation(browserPtr.get(), framePtr.get(), + requestPtr.get(), navigation_type, + is_redirect)) { + return true; + } + } + } + } + + return false; +} + +void CefContentRendererClient::DidCreateScriptContext( + blink::WebFrame* frame, v8::Handle context, + int extension_group, int world_id) { + CefRefPtr browserPtr = + CefBrowserImpl::GetBrowserForMainFrame(frame->top()); + DCHECK(browserPtr.get()); + if (!browserPtr.get()) + return; + + CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); + + v8::Isolate* isolate = blink::mainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope scope(context); + WebCore::V8RecursionScope recursion_scope( + isolate, + WebCore::toExecutionContext(context)); + + CefRefPtr contextPtr(new CefV8ContextImpl(isolate, context)); + + // Notify the render process handler. + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) + handler->OnContextCreated(browserPtr.get(), framePtr.get(), contextPtr); + } +} + +const void* CefContentRendererClient::CreatePPAPIInterface( + const std::string& interface_name) { +#if defined(ENABLE_PLUGINS) + // Used for in-process PDF plugin. + if (interface_name == PPB_PDF_INTERFACE) + return PPB_PDF_Impl::GetInterface(); +#endif + return NULL; +} + +void CefContentRendererClient::WillReleaseScriptContext( + blink::WebFrame* frame, v8::Handle context, int world_id) { + // Notify the render process handler. + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr browserPtr = + CefBrowserImpl::GetBrowserForMainFrame(frame->top()); + DCHECK(browserPtr.get()); + if (browserPtr.get()) { + CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); + + v8::Isolate* isolate = blink::mainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope scope(context); + WebCore::V8RecursionScope recursion_scope( + isolate, + WebCore::toExecutionContext(context)); + + CefRefPtr contextPtr( + new CefV8ContextImpl(isolate, context)); + + handler->OnContextReleased(browserPtr.get(), framePtr.get(), + contextPtr); + } + } + } + + CefV8ReleaseContext(context); +} + +void CefContentRendererClient::WillDestroyCurrentMessageLoop() { + base::AutoLock lock_scope(single_process_cleanup_lock_); + single_process_cleanup_complete_ = true; +} + +void CefContentRendererClient::BrowserCreated( + content::RenderView* render_view, + content::RenderFrame* render_frame) { + // Retrieve the browser information synchronously. This will also register + // the routing ids with the browser info object in the browser process. + CefProcessHostMsg_GetNewBrowserInfo_Params params; + content::RenderThread::Get()->Send( + new CefProcessHostMsg_GetNewBrowserInfo( + render_view->GetRoutingID(), + render_frame->GetRoutingID(), + ¶ms)); + DCHECK_GT(params.browser_id, 0); + + // Don't create another browser object if one already exists for the view. + if (GetBrowserForView(render_view)) + return; + +#if defined(OS_MACOSX) + // FIXME: It would be better if this API would be a callback from the + // WebKit layer, or if it would be exposed as an WebView instance method; the + // current implementation uses a static variable, and WebKit needs to be + // patched in order to make it work for each WebView instance + render_view->GetWebView()->setUseExternalPopupMenusThisInstance( + !params.is_windowless); +#endif + + CefRefPtr browser = + new CefBrowserImpl(render_view, params.browser_id, params.is_popup, + params.is_windowless); + browsers_.insert(std::make_pair(render_view, browser)); + + new CefPrerendererClient(render_view); + new printing::PrintWebViewHelper(render_view); + + // Notify the render process handler. + CefRefPtr application = CefContentClient::Get()->application(); + if (application.get()) { + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (handler.get()) + handler->OnBrowserCreated(browser.get()); + } +} + +void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + // Clean up the single existing RenderProcessHost. + content::RenderProcessHost* host = NULL; + content::RenderProcessHost::iterator iterator( + content::RenderProcessHost::AllHostsIterator()); + if (!iterator.IsAtEnd()) { + host = iterator.GetCurrentValue(); + host->Cleanup(); + iterator.Advance(); + DCHECK(iterator.IsAtEnd()); + } + DCHECK(host); + + // Clear the run_renderer_in_process() flag to avoid a DCHECK in the + // RenderProcessHost destructor. + content::RenderProcessHost::SetRunRendererInProcess(false); + + // Deletion of the RenderProcessHost object will stop the render thread and + // result in a call to WillDestroyCurrentMessageLoop. + // Cleanup() will cause deletion to be posted as a task on the UI thread but + // this task will only execute when running in multi-threaded message loop + // mode (because otherwise the UI message loop has already stopped). Therefore + // we need to explicitly delete the object when not running in this mode. + if (!CefContext::Get()->settings().multi_threaded_message_loop) + delete host; +} diff --git a/libcef/renderer/content_renderer_client.h b/libcef/renderer/content_renderer_client.h new file mode 100644 index 000000000..62f9398a8 --- /dev/null +++ b/libcef/renderer/content_renderer_client.h @@ -0,0 +1,140 @@ +// 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. + +#ifndef CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_ +#define CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_ +#pragma once + +#include +#include +#include +#include + +#include "libcef/renderer/browser_impl.h" + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/sequenced_task_runner.h" +#include "content/public/renderer/content_renderer_client.h" + +class CefRenderProcessObserver; +struct Cef_CrossOriginWhiteListEntry_Params; + +class CefContentRendererClient : public content::ContentRendererClient, + public base::MessageLoop::DestructionObserver { + public: + CefContentRendererClient(); + virtual ~CefContentRendererClient(); + + // Returns the singleton CefContentRendererClient instance. + static CefContentRendererClient* Get(); + + // Returns the browser associated with the specified RenderView. + CefRefPtr GetBrowserForView(content::RenderView* view); + + // Returns the browser associated with the specified main WebFrame. + CefRefPtr GetBrowserForMainFrame(blink::WebFrame* frame); + + // Called from CefBrowserImpl::OnDestruct(). + void OnBrowserDestroyed(CefBrowserImpl* browser); + + // Render thread task runner. + base::SequencedTaskRunner* render_task_runner() const { + return render_task_runner_.get(); + } + + int uncaught_exception_stack_size() const { + return uncaught_exception_stack_size_; + } + + void WebKitInitialized(); + void OnRenderProcessShutdown(); + + void DevToolsAgentAttached(); + void DevToolsAgentDetached(); + + // Returns the task runner for the current thread. If this is a WebWorker + // thread and the task runner does not already exist it will be created. + // Returns NULL if the current thread is not a valid render process thread. + scoped_refptr GetCurrentTaskRunner(); + + // Returns the task runner for the specified worker ID or NULL if the + // specified worker ID is not valid. + scoped_refptr GetWorkerTaskRunner(int worker_id); + + // Remove the task runner associated with the specified worker ID. + void RemoveWorkerTaskRunner(int worker_id); + + // Perform cleanup work that needs to occur before shutdown when running in + // single-process mode. Blocks until cleanup is complete. + void RunSingleProcessCleanup(); + + // ContentRendererClient implementation. + virtual void RenderThreadStarted() OVERRIDE; + virtual void RenderFrameCreated(content::RenderFrame* render_frame) OVERRIDE; + virtual void RenderViewCreated(content::RenderView* render_view) OVERRIDE; + virtual bool OverrideCreatePlugin( + content::RenderFrame* render_frame, + blink::WebLocalFrame* frame, + const blink::WebPluginParams& params, + blink::WebPlugin** plugin) OVERRIDE; + virtual bool HandleNavigation(content::RenderFrame* render_frame, + content::DocumentState* document_state, + int opener_id, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, + bool is_redirect) OVERRIDE; + virtual void DidCreateScriptContext(blink::WebFrame* frame, + v8::Handle context, + int extension_group, + int world_id) OVERRIDE; + virtual const void* CreatePPAPIInterface( + const std::string& interface_name) OVERRIDE; + + void WillReleaseScriptContext(blink::WebFrame* frame, + v8::Handle context, + int world_id); + + // MessageLoop::DestructionObserver implementation. + virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + + private: + void BrowserCreated(content::RenderView* render_view, + content::RenderFrame* render_frame); + + // Perform cleanup work for single-process mode. + void RunSingleProcessCleanupOnUIThread(); + + scoped_refptr render_task_runner_; + scoped_ptr observer_; + + // Map of RenderView pointers to CefBrowserImpl references. + typedef std::map > BrowserMap; + BrowserMap browsers_; + + // Cross-origin white list entries that need to be registered with WebKit. + typedef std::vector CrossOriginList; + CrossOriginList cross_origin_whitelist_entries_; + + int devtools_agent_count_; + int uncaught_exception_stack_size_; + + // Map of worker thread IDs to task runners. Access must be protected by + // |worker_task_runner_lock_|. + typedef std::map > + WorkerTaskRunnerMap; + WorkerTaskRunnerMap worker_task_runner_map_; + base::Lock worker_task_runner_lock_; + + // Used in single-process mode to test when cleanup is complete. + // Access must be protected by |single_process_cleanup_lock_|. + bool single_process_cleanup_complete_; + base::Lock single_process_cleanup_lock_; +}; + +#endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_ diff --git a/libcef/renderer/dom_document_impl.cc b/libcef/renderer/dom_document_impl.cc new file mode 100644 index 000000000..6357c6952 --- /dev/null +++ b/libcef/renderer/dom_document_impl.cc @@ -0,0 +1,262 @@ +// 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 "libcef/renderer/dom_document_impl.h" +#include "libcef/renderer/dom_node_impl.h" +#include "libcef/renderer/thread_util.h" + +#include "base/logging.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebNode.h" +#include "third_party/WebKit/public/web/WebRange.h" + +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebNode; +using blink::WebRange; +using blink::WebString; +using blink::WebURL; + + +CefDOMDocumentImpl::CefDOMDocumentImpl(CefBrowserImpl* browser, + WebFrame* frame) + : browser_(browser), + frame_(frame) { + const WebDocument& document = frame_->document(); + DCHECK(!document.isNull()); +} + +CefDOMDocumentImpl::~CefDOMDocumentImpl() { + CEF_REQUIRE_RT(); + + // Verify that the Detach() method has been called. + DCHECK(frame_ == NULL); +} + +CefDOMDocumentImpl::Type CefDOMDocumentImpl::GetType() { + if (!VerifyContext()) + return DOM_DOCUMENT_TYPE_UNKNOWN; + + const WebDocument& document = frame_->document(); + if (document.isHTMLDocument()) + return DOM_DOCUMENT_TYPE_HTML; + if (document.isXHTMLDocument()) + return DOM_DOCUMENT_TYPE_XHTML; + if (document.isPluginDocument()) + return DOM_DOCUMENT_TYPE_PLUGIN; + return DOM_DOCUMENT_TYPE_UNKNOWN; +} + +CefRefPtr CefDOMDocumentImpl::GetDocument() { + const WebDocument& document = frame_->document(); + return GetOrCreateNode(document.document()); +} + +CefRefPtr CefDOMDocumentImpl::GetBody() { + const WebDocument& document = frame_->document(); + return GetOrCreateNode(document.body()); +} + +CefRefPtr CefDOMDocumentImpl::GetHead() { + WebDocument document = frame_->document(); + return GetOrCreateNode(document.head()); +} + +CefString CefDOMDocumentImpl::GetTitle() { + CefString str; + if (!VerifyContext()) + return str; + + const WebDocument& document = frame_->document(); + const WebString& title = document.title(); + if (!title.isNull()) + str = title; + + return str; +} + +CefRefPtr CefDOMDocumentImpl::GetElementById(const CefString& id) { + const WebDocument& document = frame_->document(); + return GetOrCreateNode(document.getElementById(base::string16(id))); +} + +CefRefPtr CefDOMDocumentImpl::GetFocusedNode() { + const WebDocument& document = frame_->document(); + return GetOrCreateNode(document.focusedElement()); +} + +bool CefDOMDocumentImpl::HasSelection() { + if (!VerifyContext()) + return false; + + return frame_->hasSelection(); +} + +CefRefPtr CefDOMDocumentImpl::GetSelectionStartNode() { + if (!VerifyContext() || !frame_->hasSelection()) + return NULL; + + const WebRange& range = frame_->selectionRange(); + if (range.isNull()) + return NULL; + + int exceptionCode; + return GetOrCreateNode(range.startContainer(exceptionCode)); +} + +int CefDOMDocumentImpl::GetSelectionStartOffset() { + if (!VerifyContext() || !frame_->hasSelection()) + return 0; + + const WebRange& range = frame_->selectionRange(); + if (range.isNull()) + return 0; + + return range.startOffset(); +} + +CefRefPtr CefDOMDocumentImpl::GetSelectionEndNode() { + if (!VerifyContext() || !frame_->hasSelection()) + return NULL; + + const WebRange& range = frame_->selectionRange(); + if (range.isNull()) + return NULL; + + int exceptionCode; + return GetOrCreateNode(range.endContainer(exceptionCode)); +} + +int CefDOMDocumentImpl::GetSelectionEndOffset() { + if (!VerifyContext() || !frame_->hasSelection()) + return 0; + + const WebRange& range = frame_->selectionRange(); + if (range.isNull()) + return 0; + + return range.endOffset(); +} + +CefString CefDOMDocumentImpl::GetSelectionAsMarkup() { + CefString str; + if (!VerifyContext() || !frame_->hasSelection()) + return str; + + const WebString& markup = frame_->selectionAsMarkup(); + if (!markup.isNull()) + str = markup; + + return str; +} + +CefString CefDOMDocumentImpl::GetSelectionAsText() { + CefString str; + if (!VerifyContext() || !frame_->hasSelection()) + return str; + + const WebString& text = frame_->selectionAsText(); + if (!text.isNull()) + str = text; + + return str; +} + +CefString CefDOMDocumentImpl::GetBaseURL() { + CefString str; + if (!VerifyContext()) + return str; + + const WebDocument& document = frame_->document(); + const WebURL& url = document.baseURL(); + if (!url.isNull()) { + GURL gurl = url; + str = gurl.spec(); + } + + return str; +} + +CefString CefDOMDocumentImpl::GetCompleteURL(const CefString& partialURL) { + CefString str; + if (!VerifyContext()) + return str; + + const WebDocument& document = frame_->document(); + const WebURL& url = document.completeURL(base::string16(partialURL)); + if (!url.isNull()) { + GURL gurl = url; + str = gurl.spec(); + } + + return str; +} + +CefRefPtr CefDOMDocumentImpl::GetOrCreateNode( + const blink::WebNode& node) { + if (!VerifyContext()) + return NULL; + + // Nodes may potentially be null. + if (node.isNull()) + return NULL; + + if (!node_map_.empty()) { + // Locate the existing node, if any. + NodeMap::const_iterator it = node_map_.find(node); + if (it != node_map_.end()) + return it->second; + } + + // Create the new node object. + CefRefPtr nodeImpl(new CefDOMNodeImpl(this, node)); + node_map_.insert(std::make_pair(node, nodeImpl)); + return nodeImpl; +} + +void CefDOMDocumentImpl::RemoveNode(const blink::WebNode& node) { + if (!VerifyContext()) + return; + + if (!node_map_.empty()) { + NodeMap::iterator it = node_map_.find(node); + if (it != node_map_.end()) + node_map_.erase(it); + } +} + +void CefDOMDocumentImpl::Detach() { + if (!VerifyContext()) + return; + + // If you hit this assert it means that you are keeping references to node + // objects beyond the valid scope. + DCHECK(node_map_.empty()); + + // If you hit this assert it means that you are keeping references to this + // document object beyond the valid scope. + DCHECK(HasOneRef()); + + if (!node_map_.empty()) { + NodeMap::const_iterator it = node_map_.begin(); + for (; it != node_map_.end(); ++it) + static_cast(it->second)->Detach(); + node_map_.clear(); + } + + frame_ = NULL; +} + +bool CefDOMDocumentImpl::VerifyContext() { + if (!CEF_CURRENTLY_ON_RT() || frame_ == NULL) { + NOTREACHED(); + return false; + } + return true; +} diff --git a/libcef/renderer/dom_document_impl.h b/libcef/renderer/dom_document_impl.h new file mode 100644 index 000000000..5aa7356ae --- /dev/null +++ b/libcef/renderer/dom_document_impl.h @@ -0,0 +1,66 @@ +// 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_LIBCEF_DOM_DOCUMENT_IMPL_H_ +#define CEF_LIBCEF_DOM_DOCUMENT_IMPL_H_ +#pragma once + +#include +#include "include/cef_dom.h" + +namespace blink { +class WebFrame; +class WebNode; +}; + +class CefBrowserImpl; + +class CefDOMDocumentImpl : public CefDOMDocument { + public: + CefDOMDocumentImpl(CefBrowserImpl* browser, + blink::WebFrame* frame); + virtual ~CefDOMDocumentImpl(); + + // CefDOMDocument methods. + virtual Type GetType() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetBody() OVERRIDE; + virtual CefRefPtr GetHead() OVERRIDE; + virtual CefString GetTitle() OVERRIDE; + virtual CefRefPtr GetElementById(const CefString& id) OVERRIDE; + virtual CefRefPtr GetFocusedNode() OVERRIDE; + virtual bool HasSelection() OVERRIDE; + virtual CefRefPtr GetSelectionStartNode() OVERRIDE; + virtual int GetSelectionStartOffset() OVERRIDE; + virtual CefRefPtr GetSelectionEndNode() OVERRIDE; + virtual int GetSelectionEndOffset() OVERRIDE; + virtual CefString GetSelectionAsMarkup() OVERRIDE; + virtual CefString GetSelectionAsText() OVERRIDE; + virtual CefString GetBaseURL() OVERRIDE; + virtual CefString GetCompleteURL(const CefString& partialURL) OVERRIDE; + + CefBrowserImpl* GetBrowser() { return browser_; } + blink::WebFrame* GetFrame() { return frame_; } + + // The document maintains a map of all existing node objects. + CefRefPtr GetOrCreateNode(const blink::WebNode& node); + void RemoveNode(const blink::WebNode& node); + + // Must be called before the object is destroyed. + void Detach(); + + // Verify that the object exists and is being accessed on the UI thread. + bool VerifyContext(); + + protected: + CefBrowserImpl* browser_; + blink::WebFrame* frame_; + + typedef std::map NodeMap; + NodeMap node_map_; + + IMPLEMENT_REFCOUNTING(CefDOMDocumentImpl); +}; + +#endif // CEF_LIBCEF_DOM_DOCUMENT_IMPL_H_ diff --git a/libcef/renderer/dom_event_impl.cc b/libcef/renderer/dom_event_impl.cc new file mode 100644 index 000000000..e19232f23 --- /dev/null +++ b/libcef/renderer/dom_event_impl.cc @@ -0,0 +1,154 @@ +// 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 "libcef/renderer/dom_event_impl.h" +#include "libcef/renderer/dom_document_impl.h" +#include "libcef/renderer/thread_util.h" + +#include "base/logging.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebDOMEvent.h" + +using blink::WebDOMEvent; +using blink::WebString; + + +CefDOMEventImpl::CefDOMEventImpl(CefRefPtr document, + const blink::WebDOMEvent& event) + : document_(document), + event_(event) { + DCHECK(!event_.isNull()); +} + +CefDOMEventImpl::~CefDOMEventImpl() { + CEF_REQUIRE_RT(); + DCHECK(event_.isNull()); +} + +CefString CefDOMEventImpl::GetType() { + CefString str; + if (!VerifyContext()) + return str; + + const WebString& type = event_.type(); + if (!type.isNull()) + str = type; + + return str; +} + +CefDOMEventImpl::Category CefDOMEventImpl::GetCategory() { + if (!VerifyContext()) + return DOM_EVENT_CATEGORY_UNKNOWN; + + int flags = 0; + if (event_.isUIEvent()) + flags |= DOM_EVENT_CATEGORY_UI; + if (event_.isMouseEvent()) + flags |= DOM_EVENT_CATEGORY_MOUSE; + if (event_.isMutationEvent()) + flags |= DOM_EVENT_CATEGORY_MUTATION; + if (event_.isKeyboardEvent()) + flags |= DOM_EVENT_CATEGORY_KEYBOARD; + if (event_.isTextEvent()) + flags |= DOM_EVENT_CATEGORY_TEXT; + if (event_.isCompositionEvent()) + flags |= DOM_EVENT_CATEGORY_COMPOSITION; + if (event_.isDragEvent()) + flags |= DOM_EVENT_CATEGORY_DRAG; + if (event_.isClipboardEvent()) + flags |= DOM_EVENT_CATEGORY_CLIPBOARD; + if (event_.isMessageEvent()) + flags |= DOM_EVENT_CATEGORY_MESSAGE; + if (event_.isWheelEvent()) + flags |= DOM_EVENT_CATEGORY_WHEEL; + if (event_.isBeforeTextInsertedEvent()) + flags |= DOM_EVENT_CATEGORY_BEFORE_TEXT_INSERTED; + if (event_.isOverflowEvent()) + flags |= DOM_EVENT_CATEGORY_OVERFLOW; + if (event_.isPageTransitionEvent()) + flags |= DOM_EVENT_CATEGORY_PAGE_TRANSITION; + if (event_.isPopStateEvent()) + flags |= DOM_EVENT_CATEGORY_POPSTATE; + if (event_.isProgressEvent()) + flags |= DOM_EVENT_CATEGORY_PROGRESS; + if (event_.isXMLHttpRequestProgressEvent()) + flags |= DOM_EVENT_CATEGORY_XMLHTTPREQUEST_PROGRESS; + + return static_cast(flags); +} + +CefDOMEventImpl::Phase CefDOMEventImpl::GetPhase() { + if (!VerifyContext()) + return DOM_EVENT_PHASE_UNKNOWN; + + switch (event_.eventPhase()) { + case WebDOMEvent::CapturingPhase: + return DOM_EVENT_PHASE_CAPTURING; + case WebDOMEvent::AtTarget: + return DOM_EVENT_PHASE_AT_TARGET; + case WebDOMEvent::BubblingPhase: + return DOM_EVENT_PHASE_BUBBLING; + } + + return DOM_EVENT_PHASE_UNKNOWN; +} + +bool CefDOMEventImpl::CanBubble() { + if (!VerifyContext()) + return false; + + return event_.bubbles(); +} + +bool CefDOMEventImpl::CanCancel() { + if (!VerifyContext()) + return false; + + return event_.cancelable(); +} + +CefRefPtr CefDOMEventImpl::GetDocument() { + if (!VerifyContext()) + return NULL; + + return document_.get(); +} + +CefRefPtr CefDOMEventImpl::GetTarget() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(event_.target()); +} + +CefRefPtr CefDOMEventImpl::GetCurrentTarget() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(event_.currentTarget()); +} + +void CefDOMEventImpl::Detach() { + // If you hit this assert it means that you are keeping references to this + // event object beyond the valid scope. + DCHECK(HasOneRef()); + + document_ = NULL; + event_.assign(WebDOMEvent()); +} + +bool CefDOMEventImpl::VerifyContext() { + if (!document_.get()) { + NOTREACHED(); + return false; + } + if (!document_->VerifyContext()) + return false; + if (event_.isNull()) { + NOTREACHED(); + return false; + } + return true; +} diff --git a/libcef/renderer/dom_event_impl.h b/libcef/renderer/dom_event_impl.h new file mode 100644 index 000000000..fd5c1c008 --- /dev/null +++ b/libcef/renderer/dom_event_impl.h @@ -0,0 +1,43 @@ +// 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_LIBCEF_DOM_EVENT_IMPL_H_ +#define CEF_LIBCEF_DOM_EVENT_IMPL_H_ +#pragma once + +#include "include/cef_dom.h" +#include "third_party/WebKit/public/web/WebDOMEvent.h" + +class CefDOMDocumentImpl; + +class CefDOMEventImpl : public CefDOMEvent { + public: + CefDOMEventImpl(CefRefPtr document, + const blink::WebDOMEvent& event); + virtual ~CefDOMEventImpl(); + + // CefDOMEvent methods. + virtual CefString GetType() OVERRIDE; + virtual Category GetCategory() OVERRIDE; + virtual Phase GetPhase() OVERRIDE; + virtual bool CanBubble() OVERRIDE; + virtual bool CanCancel() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetTarget() OVERRIDE; + virtual CefRefPtr GetCurrentTarget() OVERRIDE; + + // Will be called from CefDOMEventListenerWrapper::handleEvent(). + void Detach(); + + // Verify that the object exists and is being accessed on the UI thread. + bool VerifyContext(); + + protected: + CefRefPtr document_; + blink::WebDOMEvent event_; + + IMPLEMENT_REFCOUNTING(CefDOMEventImpl); +}; + +#endif // CEF_LIBCEF_DOM_EVENT_IMPL_H_ diff --git a/libcef/renderer/dom_node_impl.cc b/libcef/renderer/dom_node_impl.cc new file mode 100644 index 000000000..359855bec --- /dev/null +++ b/libcef/renderer/dom_node_impl.cc @@ -0,0 +1,479 @@ +// 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 "libcef/renderer/dom_node_impl.h" +#include "libcef/common/tracker.h" +#include "libcef/renderer/browser_impl.h" +#include "libcef/renderer/dom_document_impl.h" +#include "libcef/renderer/dom_event_impl.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/renderer/webkit_glue.h" + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebDOMEvent.h" +#include "third_party/WebKit/public/web/WebDOMEventListener.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebFormControlElement.h" +#include "third_party/WebKit/public/web/WebInputElement.h" +#include "third_party/WebKit/public/web/WebNode.h" +#include "third_party/WebKit/public/web/WebSelectElement.h" + +using blink::WebDocument; +using blink::WebDOMEvent; +using blink::WebDOMEventListener; +using blink::WebElement; +using blink::WebFrame; +using blink::WebFormControlElement; +using blink::WebInputElement; +using blink::WebNode; +using blink::WebSelectElement; +using blink::WebString; + +namespace { + +// Wrapper implementation for WebDOMEventListener. +class CefDOMEventListenerWrapper : public WebDOMEventListener, + public CefTrackNode { + public: + CefDOMEventListenerWrapper(CefBrowserImpl* browser, WebFrame* frame, + CefRefPtr listener) + : browser_(browser), + frame_(frame), + listener_(listener) { + // Cause this object to be deleted immediately before the frame is closed. + browser->AddFrameObject(webkit_glue::GetIdentifier(frame), this); + } + virtual ~CefDOMEventListenerWrapper() { + CEF_REQUIRE_RT(); + } + + virtual void handleEvent(const WebDOMEvent& event) { + CefRefPtr documentImpl; + CefRefPtr eventImpl; + + if (!event.isNull()) { + // Create CefDOMDocumentImpl and CefDOMEventImpl objects that are valid + // only for the scope of this method. + const WebDocument& document = frame_->document(); + if (!document.isNull()) { + documentImpl = new CefDOMDocumentImpl(browser_, frame_); + eventImpl = new CefDOMEventImpl(documentImpl, event); + } + } + + listener_->HandleEvent(eventImpl.get()); + + if (eventImpl.get()) + eventImpl->Detach(); + if (documentImpl.get()) + documentImpl->Detach(); + } + + protected: + CefBrowserImpl* browser_; + WebFrame* frame_; + CefRefPtr listener_; +}; + +} // namespace + + +CefDOMNodeImpl::CefDOMNodeImpl(CefRefPtr document, + const blink::WebNode& node) + : document_(document), + node_(node) { +} + +CefDOMNodeImpl::~CefDOMNodeImpl() { + CEF_REQUIRE_RT(); + + if (document_.get() && !node_.isNull()) { + // Remove the node from the document. + document_->RemoveNode(node_); + } +} + +CefDOMNodeImpl::Type CefDOMNodeImpl::GetType() { + if (!VerifyContext()) + return DOM_NODE_TYPE_UNSUPPORTED; + + switch (node_.nodeType()) { + case WebNode::ElementNode: + return DOM_NODE_TYPE_ELEMENT; + case WebNode::AttributeNode: + return DOM_NODE_TYPE_ATTRIBUTE; + case WebNode::TextNode: + return DOM_NODE_TYPE_TEXT; + case WebNode::CDataSectionNode: + return DOM_NODE_TYPE_CDATA_SECTION; + case WebNode::ProcessingInstructionsNode: + return DOM_NODE_TYPE_PROCESSING_INSTRUCTIONS; + case WebNode::CommentNode: + return DOM_NODE_TYPE_COMMENT; + case WebNode::DocumentNode: + return DOM_NODE_TYPE_DOCUMENT; + case WebNode::DocumentTypeNode: + return DOM_NODE_TYPE_DOCUMENT_TYPE; + case WebNode::DocumentFragmentNode: + return DOM_NODE_TYPE_DOCUMENT_FRAGMENT; + default: + return DOM_NODE_TYPE_UNSUPPORTED; + } +} + +bool CefDOMNodeImpl::IsText() { + if (!VerifyContext()) + return false; + + return node_.isTextNode(); +} + +bool CefDOMNodeImpl::IsElement() { + if (!VerifyContext()) + return false; + + return node_.isElementNode(); +} + +// Logic copied from RenderViewImpl::IsEditableNode. +bool CefDOMNodeImpl::IsEditable() { + if (!VerifyContext()) + return false; + + if (node_.isContentEditable()) + return true; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + if (element.isTextFormControlElement()) + return true; + + // Also return true if it has an ARIA role of 'textbox'. + for (unsigned i = 0; i < element.attributeCount(); ++i) { + if (LowerCaseEqualsASCII(element.attributeLocalName(i), "role")) { + if (LowerCaseEqualsASCII(element.attributeValue(i), "textbox")) + return true; + break; + } + } + } + + return false; +} + +bool CefDOMNodeImpl::IsFormControlElement() { + if (!VerifyContext()) + return false; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + return element.isFormControlElement(); + } + + return false; +} + +CefString CefDOMNodeImpl::GetFormControlElementType() { + CefString str; + if (!VerifyContext()) + return str; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + if (element.isFormControlElement()) { + // Retrieve the type from the form control element. + const WebFormControlElement& formElement = + node_.toConst(); + + const base::string16& form_control_type = formElement.formControlType(); + str = form_control_type; + } + } + + return str; +} + +bool CefDOMNodeImpl::IsSame(CefRefPtr that) { + if (!VerifyContext()) + return false; + + CefDOMNodeImpl* impl = static_cast(that.get()); + if (!impl || !impl->VerifyContext()) + return false; + + return node_.equals(impl->node_); +} + +CefString CefDOMNodeImpl::GetName() { + CefString str; + if (!VerifyContext()) + return str; + + const WebString& name = node_.nodeName(); + if (!name.isNull()) + str = name; + + return str; +} + +CefString CefDOMNodeImpl::GetValue() { + CefString str; + if (!VerifyContext()) + return str; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + if (element.isFormControlElement()) { + // Retrieve the value from the form control element. + const WebFormControlElement& formElement = + node_.toConst(); + + base::string16 value; + const base::string16& form_control_type = formElement.formControlType(); + if (form_control_type == base::ASCIIToUTF16("text")) { + const WebInputElement& input_element = + formElement.toConst(); + value = input_element.value(); + } else if (form_control_type == base::ASCIIToUTF16("select-one")) { + const WebSelectElement& select_element = + formElement.toConst(); + value = select_element.value(); + } + + base::TrimWhitespace(value, base::TRIM_LEADING, &value); + str = value; + } + } + + if (str.empty()) { + const WebString& value = node_.nodeValue(); + if (!value.isNull()) + str = value; + } + + return str; +} + +bool CefDOMNodeImpl::SetValue(const CefString& value) { + if (!VerifyContext()) + return false; + + if (node_.isElementNode()) + return false; + + return webkit_glue::SetNodeValue(node_, base::string16(value)); +} + +CefString CefDOMNodeImpl::GetAsMarkup() { + CefString str; + if (!VerifyContext()) + return str; + + const WebString& markup = node_.createMarkup(); + if (!markup.isNull()) + str = markup; + + return str; +} + +CefRefPtr CefDOMNodeImpl::GetDocument() { + if (!VerifyContext()) + return NULL; + + return document_.get(); +} + +CefRefPtr CefDOMNodeImpl::GetParent() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(node_.parentNode()); +} + +CefRefPtr CefDOMNodeImpl::GetPreviousSibling() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(node_.previousSibling()); +} + +CefRefPtr CefDOMNodeImpl::GetNextSibling() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(node_.nextSibling()); +} + +bool CefDOMNodeImpl::HasChildren() { + if (!VerifyContext()) + return false; + + return node_.hasChildNodes(); +} + +CefRefPtr CefDOMNodeImpl::GetFirstChild() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(node_.firstChild()); +} + +CefRefPtr CefDOMNodeImpl::GetLastChild() { + if (!VerifyContext()) + return NULL; + + return document_->GetOrCreateNode(node_.lastChild()); +} + +void CefDOMNodeImpl::AddEventListener(const CefString& eventType, + CefRefPtr listener, + bool useCapture) { + if (!VerifyContext()) + return; + + node_.addEventListener(base::string16(eventType), + new CefDOMEventListenerWrapper(document_->GetBrowser(), + document_->GetFrame(), listener), + useCapture); +} + +CefString CefDOMNodeImpl::GetElementTagName() { + CefString str; + if (!VerifyContext()) + return str; + + if (!node_.isElementNode()) { + NOTREACHED(); + return str; + } + + const WebElement& element = node_.toConst(); + const WebString& tagname = element.tagName(); + if (!tagname.isNull()) + str = tagname; + + return str; +} + +bool CefDOMNodeImpl::HasElementAttributes() { + if (!VerifyContext()) + return false; + + if (!node_.isElementNode()) { + NOTREACHED(); + return false; + } + + const WebElement& element = node_.toConst(); + return (element.attributeCount() > 0); +} + +bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName) { + if (!VerifyContext()) + return false; + + if (!node_.isElementNode()) { + NOTREACHED(); + return false; + } + + const WebElement& element = node_.toConst(); + return element.hasAttribute(base::string16(attrName)); +} + +CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName) { + CefString str; + if (!VerifyContext()) + return str; + + if (!node_.isElementNode()) { + NOTREACHED(); + return str; + } + + const WebElement& element = node_.toConst(); + const WebString& attr = element.getAttribute(base::string16(attrName)); + if (!attr.isNull()) + str = attr; + + return str; +} + +void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap) { + if (!VerifyContext()) + return; + + if (!node_.isElementNode()) { + NOTREACHED(); + return; + } + + const WebElement& element = node_.toConst(); + unsigned int len = element.attributeCount(); + if (len == 0) + return; + + for (unsigned int i = 0; i < len; ++i) { + base::string16 name = element.attributeLocalName(i); + base::string16 value = element.attributeValue(i); + attrMap.insert(std::make_pair(name, value)); + } +} + +bool CefDOMNodeImpl::SetElementAttribute(const CefString& attrName, + const CefString& value) { + if (!VerifyContext()) + return false; + + if (!node_.isElementNode()) { + NOTREACHED(); + return false; + } + + WebElement element = node_.to(); + return element.setAttribute(base::string16(attrName), + base::string16(value)); +} + +CefString CefDOMNodeImpl::GetElementInnerText() { + CefString str; + if (!VerifyContext()) + return str; + + if (!node_.isElementNode()) { + NOTREACHED(); + return str; + } + + WebElement element = node_.to(); + const WebString& text = element.innerText(); + if (!text.isNull()) + str = text; + + return str; +} + +void CefDOMNodeImpl::Detach() { + document_ = NULL; + node_.assign(WebNode()); +} + +bool CefDOMNodeImpl::VerifyContext() { + if (!document_.get()) { + NOTREACHED(); + return false; + } + if (!document_->VerifyContext()) + return false; + if (node_.isNull()) { + NOTREACHED(); + return false; + } + return true; +} diff --git a/libcef/renderer/dom_node_impl.h b/libcef/renderer/dom_node_impl.h new file mode 100644 index 000000000..2cab762a4 --- /dev/null +++ b/libcef/renderer/dom_node_impl.h @@ -0,0 +1,64 @@ +// 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_LIBCEF_DOM_NODE_IMPL_H_ +#define CEF_LIBCEF_DOM_NODE_IMPL_H_ +#pragma once + +#include "include/cef_dom.h" +#include "third_party/WebKit/public/web/WebNode.h" + +class CefDOMDocumentImpl; + +class CefDOMNodeImpl : public CefDOMNode { + public: + CefDOMNodeImpl(CefRefPtr document, + const blink::WebNode& node); + virtual ~CefDOMNodeImpl(); + + // CefDOMNode methods. + virtual Type GetType() OVERRIDE; + virtual bool IsText() OVERRIDE; + virtual bool IsElement() OVERRIDE; + virtual bool IsEditable() OVERRIDE; + virtual bool IsFormControlElement() OVERRIDE; + virtual CefString GetFormControlElementType() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual CefString GetValue() OVERRIDE; + virtual bool SetValue(const CefString& value) OVERRIDE; + virtual CefString GetAsMarkup() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetParent() OVERRIDE; + virtual CefRefPtr GetPreviousSibling() OVERRIDE; + virtual CefRefPtr GetNextSibling() OVERRIDE; + virtual bool HasChildren() OVERRIDE; + virtual CefRefPtr GetFirstChild() OVERRIDE; + virtual CefRefPtr GetLastChild() OVERRIDE; + virtual void AddEventListener(const CefString& eventType, + CefRefPtr listener, + bool useCapture) OVERRIDE; + virtual CefString GetElementTagName() OVERRIDE; + virtual bool HasElementAttributes() OVERRIDE; + virtual bool HasElementAttribute(const CefString& attrName) OVERRIDE; + virtual CefString GetElementAttribute(const CefString& attrName) OVERRIDE; + virtual void GetElementAttributes(AttributeMap& attrMap) OVERRIDE; + virtual bool SetElementAttribute(const CefString& attrName, + const CefString& value) OVERRIDE; + virtual CefString GetElementInnerText() OVERRIDE; + + // Will be called from CefDOMDocumentImpl::Detach(). + void Detach(); + + // Verify that the object exists and is being accessed on the UI thread. + bool VerifyContext(); + + protected: + CefRefPtr document_; + blink::WebNode node_; + + IMPLEMENT_REFCOUNTING(CefDOMNodeImpl); +}; + +#endif // CEF_LIBCEF_DOM_NODE_IMPL_H_ diff --git a/libcef/renderer/frame_impl.cc b/libcef/renderer/frame_impl.cc new file mode 100644 index 000000000..64bc37739 --- /dev/null +++ b/libcef/renderer/frame_impl.cc @@ -0,0 +1,272 @@ +// 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 "libcef/renderer/frame_impl.h" + +#include "libcef/common/cef_messages.h" +#include "libcef/common/http_header_utils.h" +#include "libcef/common/request_impl.h" +#include "libcef/renderer/browser_impl.h" +#include "libcef/renderer/dom_document_impl.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/renderer/v8_impl.h" +#include "libcef/renderer/webkit_glue.h" + +#include "third_party/WebKit/public/platform/WebData.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "third_party/WebKit/public/web/WebScriptSource.h" + +using blink::WebString; + +CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser, + blink::WebFrame* frame) + : browser_(browser), + frame_(frame), + frame_id_(webkit_glue::GetIdentifier(frame)) { +} + +CefFrameImpl::~CefFrameImpl() { +} + +bool CefFrameImpl::IsValid() { + CEF_REQUIRE_RT_RETURN(false); + + return (frame_ != NULL); +} + +void CefFrameImpl::Undo() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Undo")); +} + +void CefFrameImpl::Redo() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Redo")); +} + +void CefFrameImpl::Cut() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Cut")); +} + +void CefFrameImpl::Copy() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Copy")); +} + +void CefFrameImpl::Paste() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Paste")); +} + +void CefFrameImpl::Delete() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("Delete")); +} + +void CefFrameImpl::SelectAll() { + CEF_REQUIRE_RT_RETURN_VOID(); + if (frame_) + frame_->executeCommand(WebString::fromUTF8("SelectAll")); +} + +void CefFrameImpl::ViewSource() { + NOTREACHED() << "ViewSource cannot be called from the renderer process"; +} + +void CefFrameImpl::GetSource(CefRefPtr visitor) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (frame_) { + CefString content = std::string(frame_->contentAsMarkup().utf8()); + visitor->Visit(content); + } +} + +void CefFrameImpl::GetText(CefRefPtr visitor) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (frame_) { + CefString content = webkit_glue::DumpDocumentText(frame_); + visitor->Visit(content); + } +} + +void CefFrameImpl::LoadRequest(CefRefPtr request) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (!browser_) + return; + + CefMsg_LoadRequest_Params params; + params.url = GURL(std::string(request->GetURL())); + params.method = request->GetMethod(); + params.frame_id = frame_id_; + params.first_party_for_cookies = + GURL(std::string(request->GetFirstPartyForCookies())); + + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + if (!headerMap.empty()) + params.headers = HttpHeaderUtils::GenerateHeaders(headerMap); + + CefRefPtr postData = request->GetPostData(); + if (postData.get()) { + CefPostDataImpl* impl = static_cast(postData.get()); + params.upload_data = new net::UploadData(); + impl->Get(*params.upload_data.get()); + } + + params.load_flags = request->GetFlags(); + + browser_->LoadRequest(params); +} + +void CefFrameImpl::LoadURL(const CefString& url) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (!browser_) + return; + + CefMsg_LoadRequest_Params params; + params.url = GURL(url.ToString()); + params.method = "GET"; + params.frame_id = frame_id_; + + browser_->LoadRequest(params); +} + +void CefFrameImpl::LoadString(const CefString& string, + const CefString& url) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (frame_) { + GURL gurl = GURL(url.ToString()); + frame_->loadHTMLString(string.ToString(), gurl); + } +} + +void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode, + const CefString& scriptUrl, + int startLine) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (jsCode.empty()) + return; + if (startLine < 0) + startLine = 0; + + if (frame_) { + GURL gurl = GURL(scriptUrl.ToString()); + frame_->executeScript( + blink::WebScriptSource(jsCode.ToString16(), gurl, startLine)); + } +} + +bool CefFrameImpl::IsMain() { + CEF_REQUIRE_RT_RETURN(false); + + if (frame_) + return (frame_->parent() == NULL); + return false; +} + +bool CefFrameImpl::IsFocused() { + CEF_REQUIRE_RT_RETURN(false); + + if (frame_ && frame_->view()) + return (frame_->view()->focusedFrame() == frame_); + return false; +} + +CefString CefFrameImpl::GetName() { + CefString name; + CEF_REQUIRE_RT_RETURN(name); + + if (frame_) + name = frame_->uniqueName(); + return name; +} + +int64 CefFrameImpl::GetIdentifier() { + CEF_REQUIRE_RT_RETURN(0); + + return frame_id_; +} + +CefRefPtr CefFrameImpl::GetParent() { + CEF_REQUIRE_RT_RETURN(NULL); + + if (frame_) { + blink::WebFrame* parent = frame_->parent(); + if (parent) + return browser_->GetWebFrameImpl(parent).get(); + } + + return NULL; +} + +CefString CefFrameImpl::GetURL() { + CefString url; + CEF_REQUIRE_RT_RETURN(url); + + if (frame_) { + GURL gurl = frame_->document().url(); + url = gurl.spec(); + } + return url; +} + +CefRefPtr CefFrameImpl::GetBrowser() { + CEF_REQUIRE_RT_RETURN(NULL); + + return browser_; +} + +CefRefPtr CefFrameImpl::GetV8Context() { + CEF_REQUIRE_RT_RETURN(NULL); + + if (frame_) { + v8::Isolate* isolate = blink::mainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + return new CefV8ContextImpl(isolate, frame_->mainWorldScriptContext()); + } else { + return NULL; + } +} + +void CefFrameImpl::VisitDOM(CefRefPtr visitor) { + CEF_REQUIRE_RT_RETURN_VOID(); + + if (!frame_) + return; + + // Create a CefDOMDocumentImpl object that is valid only for the scope of this + // method. + CefRefPtr documentImpl; + const blink::WebDocument& document = frame_->document(); + if (!document.isNull()) + documentImpl = new CefDOMDocumentImpl(browser_, frame_); + + visitor->Visit(documentImpl.get()); + + if (documentImpl.get()) + documentImpl->Detach(); +} + +void CefFrameImpl::Detach() { + browser_ = NULL; + frame_ = NULL; +} diff --git a/libcef/renderer/frame_impl.h b/libcef/renderer/frame_impl.h new file mode 100644 index 000000000..414561bb0 --- /dev/null +++ b/libcef/renderer/frame_impl.h @@ -0,0 +1,70 @@ +// 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_LIBCEF_RENDERER_FRAME_IMPL_H_ +#define CEF_LIBCEF_RENDERER_FRAME_IMPL_H_ +#pragma once + +#include +#include "include/cef_frame.h" +#include "include/cef_v8.h" + +class CefBrowserImpl; + +namespace blink { +class WebFrame; +} + +// Implementation of CefFrame. CefFrameImpl objects are owned by the +// CefBrowerImpl and will be detached when the browser is notified that the +// associated renderer WebFrame will close. +class CefFrameImpl : public CefFrame { + public: + CefFrameImpl(CefBrowserImpl* browser, + blink::WebFrame* frame); + virtual ~CefFrameImpl(); + + // CefFrame implementation. + virtual bool IsValid() OVERRIDE; + virtual void Undo() OVERRIDE; + virtual void Redo() OVERRIDE; + virtual void Cut() OVERRIDE; + virtual void Copy() OVERRIDE; + virtual void Paste() OVERRIDE; + virtual void Delete() OVERRIDE; + virtual void SelectAll() OVERRIDE; + virtual void ViewSource() OVERRIDE; + virtual void GetSource(CefRefPtr visitor) OVERRIDE; + virtual void GetText(CefRefPtr visitor) OVERRIDE; + virtual void LoadRequest(CefRefPtr request) OVERRIDE; + virtual void LoadURL(const CefString& url) OVERRIDE; + virtual void LoadString(const CefString& string, + const CefString& url) OVERRIDE; + virtual void ExecuteJavaScript(const CefString& jsCode, + const CefString& scriptUrl, + int startLine) OVERRIDE; + virtual bool IsMain() OVERRIDE; + virtual bool IsFocused() OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual int64 GetIdentifier() OVERRIDE; + virtual CefRefPtr GetParent() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual CefRefPtr GetV8Context() OVERRIDE; + virtual void VisitDOM(CefRefPtr visitor) OVERRIDE; + + void Detach(); + + blink::WebFrame* web_frame() const { return frame_; } + + protected: + CefBrowserImpl* browser_; + blink::WebFrame* frame_; + int64 frame_id_; + + IMPLEMENT_REFCOUNTING(CefFrameImpl); + DISALLOW_EVIL_CONSTRUCTORS(CefFrameImpl); +}; + +#endif // CEF_LIBCEF_RENDERER_FRAME_IMPL_H_ diff --git a/libcef/renderer/render_frame_observer.cc b/libcef/renderer/render_frame_observer.cc new file mode 100644 index 000000000..d76462ed1 --- /dev/null +++ b/libcef/renderer/render_frame_observer.cc @@ -0,0 +1,24 @@ +// Copyright 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 "libcef/renderer/render_frame_observer.h" + +#include "libcef/renderer/content_renderer_client.h" + +#include "content/public/renderer/render_frame.h" + +CefRenderFrameObserver::CefRenderFrameObserver( + content::RenderFrame* render_frame) + : content::RenderFrameObserver(render_frame) { +} + +CefRenderFrameObserver::~CefRenderFrameObserver() { +} + +void CefRenderFrameObserver::WillReleaseScriptContext( + v8::Handle context, + int world_id) { + CefContentRendererClient::Get()->WillReleaseScriptContext( + render_frame()->GetWebFrame(), context, world_id); +} diff --git a/libcef/renderer/render_frame_observer.h b/libcef/renderer/render_frame_observer.h new file mode 100644 index 000000000..f18d1b9f3 --- /dev/null +++ b/libcef/renderer/render_frame_observer.h @@ -0,0 +1,26 @@ +// Copyright 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 LIBCEF_RENDERER_RENDER_FRAME_OBSERVER_H_ +#define LIBCEF_RENDERER_RENDER_FRAME_OBSERVER_H_ + +#include "content/public/renderer/render_frame_observer.h" + +namespace content { +class RenderFrame; +} + +class CefRenderFrameObserver : public content::RenderFrameObserver { + public: + explicit CefRenderFrameObserver(content::RenderFrame* render_frame); + virtual ~CefRenderFrameObserver(); + + virtual void WillReleaseScriptContext(v8::Handle context, + int world_id) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(CefRenderFrameObserver); +}; + +#endif // LIBCEF_RENDERER_RENDER_FRAME_OBSERVER_H_ diff --git a/libcef/renderer/render_message_filter.cc b/libcef/renderer/render_message_filter.cc new file mode 100644 index 000000000..676b37ff0 --- /dev/null +++ b/libcef/renderer/render_message_filter.cc @@ -0,0 +1,75 @@ +/// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions (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 "libcef/renderer/render_message_filter.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/common/cef_messages.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "content/common/devtools_messages.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "url/gurl.h" +#include "url/url_util.h" + +CefRenderMessageFilter::CefRenderMessageFilter() + : sender_(NULL) { +} + +CefRenderMessageFilter::~CefRenderMessageFilter() { +} + +void CefRenderMessageFilter::OnFilterAdded(IPC::Sender* sender) { + sender_ = sender; +} + +void CefRenderMessageFilter::OnFilterRemoved() { +} + +bool CefRenderMessageFilter::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + if (message.type() == DevToolsAgentMsg_Attach::ID || + message.type() == DevToolsAgentMsg_Detach::ID) { + // Observe the DevTools messages but don't handle them. + handled = false; + } + + IPC_BEGIN_MESSAGE_MAP(CefRenderMessageFilter, message) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Attach, OnDevToolsAgentAttach) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDevToolsAgentDetach) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void CefRenderMessageFilter::OnDevToolsAgentAttach( + const std::string& host_id) { + CEF_POST_TASK_RT( + base::Bind(&CefRenderMessageFilter::OnDevToolsAgentAttach_RT, this)); +} + +void CefRenderMessageFilter::OnDevToolsAgentDetach() { + // CefContentRendererClient::DevToolsAgentDetached() needs to be called after + // the IPC message has been handled by DevToolsAgent. A workaround for this is + // to first post to the IO thread and then post to the renderer thread. + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&CefRenderMessageFilter::OnDevToolsAgentDetach_IOT, this)); +} + +void CefRenderMessageFilter::OnDevToolsAgentAttach_RT() { + CEF_REQUIRE_RT(); + CefContentRendererClient::Get()->DevToolsAgentAttached(); +} + +void CefRenderMessageFilter::OnDevToolsAgentDetach_IOT() { + CEF_POST_TASK_RT( + base::Bind(&CefRenderMessageFilter::OnDevToolsAgentDetach_RT, this)); +} + +void CefRenderMessageFilter::OnDevToolsAgentDetach_RT() { + CEF_REQUIRE_RT(); + CefContentRendererClient::Get()->DevToolsAgentDetached(); +} diff --git a/libcef/renderer/render_message_filter.h b/libcef/renderer/render_message_filter.h new file mode 100644 index 000000000..7dbd67bd1 --- /dev/null +++ b/libcef/renderer/render_message_filter.h @@ -0,0 +1,39 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_ +#define CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_ + +#include +#include "ipc/ipc_channel_proxy.h" +#include "ipc/message_filter.h" + +// This class sends and receives control messages on the renderer process. +class CefRenderMessageFilter : public IPC::MessageFilter { + public: + CefRenderMessageFilter(); + virtual ~CefRenderMessageFilter(); + + // IPC::ChannelProxy::MessageFilter implementation. + virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE; + virtual void OnFilterRemoved() OVERRIDE; + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + private: + // Message handlers called on the IO thread. + void OnDevToolsAgentAttach(const std::string& host_id); + void OnDevToolsAgentDetach(); + + void OnDevToolsAgentAttach_RT(); + void OnDevToolsAgentDetach_IOT(); + void OnDevToolsAgentDetach_RT(); + + IPC::Sender* sender_; + + DISALLOW_COPY_AND_ASSIGN(CefRenderMessageFilter); +}; + + +#endif // CEF_LIBCEF_RENDERER_RENDER_MESSAGE_FILTER_H_ diff --git a/libcef/renderer/render_process_observer.cc b/libcef/renderer/render_process_observer.cc new file mode 100644 index 000000000..b0b21400b --- /dev/null +++ b/libcef/renderer/render_process_observer.cc @@ -0,0 +1,65 @@ +/// Copyright (c) 2013 The Chromium Embedded Framework Authors. +// Portions (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 "libcef/renderer/render_process_observer.h" +#include "libcef/common/cef_messages.h" +#include "libcef/common/net_resource_provider.h" +#include "libcef/renderer/content_renderer_client.h" + +#include "net/base/net_module.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/web/WebSecurityPolicy.h" + +CefRenderProcessObserver::CefRenderProcessObserver() { + net::NetModule::SetResourceProvider(NetResourceProvider); +} + +CefRenderProcessObserver::~CefRenderProcessObserver() { +} + +bool CefRenderProcessObserver::OnControlMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CefRenderProcessObserver, message) + IPC_MESSAGE_HANDLER(CefProcessMsg_ModifyCrossOriginWhitelistEntry, + OnModifyCrossOriginWhitelistEntry) + IPC_MESSAGE_HANDLER(CefProcessMsg_ClearCrossOriginWhitelist, + OnClearCrossOriginWhitelist) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void CefRenderProcessObserver::WebKitInitialized() { + CefContentRendererClient::Get()->WebKitInitialized(); +} + +void CefRenderProcessObserver::OnRenderProcessShutdown() { + CefContentRendererClient::Get()->OnRenderProcessShutdown(); +} + +void CefRenderProcessObserver::OnModifyCrossOriginWhitelistEntry( + bool add, + const Cef_CrossOriginWhiteListEntry_Params& params) { + GURL gurl = GURL(params.source_origin); + if (add) { + blink::WebSecurityPolicy::addOriginAccessWhitelistEntry( + gurl, + blink::WebString::fromUTF8(params.target_protocol), + blink::WebString::fromUTF8(params.target_domain), + params.allow_target_subdomains); + } else { + blink::WebSecurityPolicy::removeOriginAccessWhitelistEntry( + gurl, + blink::WebString::fromUTF8(params.target_protocol), + blink::WebString::fromUTF8(params.target_domain), + params.allow_target_subdomains); + } +} + +void CefRenderProcessObserver::OnClearCrossOriginWhitelist() { + blink::WebSecurityPolicy::resetOriginAccessWhitelists(); +} diff --git a/libcef/renderer/render_process_observer.h b/libcef/renderer/render_process_observer.h new file mode 100644 index 000000000..b29c16674 --- /dev/null +++ b/libcef/renderer/render_process_observer.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. + +#ifndef CEF_LIBCEF_RENDERER_RENDER_PROCESS_OBSERVER_H_ +#define CEF_LIBCEF_RENDERER_RENDER_PROCESS_OBSERVER_H_ + +#include "base/compiler_specific.h" +#include "content/public/renderer/render_process_observer.h" + +struct Cef_CrossOriginWhiteListEntry_Params; + +// This class sends and receives control messages on the renderer process. +class CefRenderProcessObserver : public content::RenderProcessObserver { + public: + CefRenderProcessObserver(); + virtual ~CefRenderProcessObserver(); + + // RenderProcessObserver implementation. + virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; + virtual void WebKitInitialized() OVERRIDE; + virtual void OnRenderProcessShutdown() OVERRIDE; + + private: + // Message handlers called on the render thread. + void OnModifyCrossOriginWhitelistEntry( + bool add, + const Cef_CrossOriginWhiteListEntry_Params& params); + void OnClearCrossOriginWhitelist(); + + DISALLOW_COPY_AND_ASSIGN(CefRenderProcessObserver); +}; + +#endif // CEF_LIBCEF_RENDERER_RENDER_PROCESS_OBSERVER_H_ diff --git a/libcef/renderer/render_urlrequest_impl.cc b/libcef/renderer/render_urlrequest_impl.cc new file mode 100644 index 000000000..74f102f7e --- /dev/null +++ b/libcef/renderer/render_urlrequest_impl.cc @@ -0,0 +1,378 @@ +// 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 "libcef/renderer/render_urlrequest_impl.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/response_impl.h" + +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "third_party/WebKit/public/platform/Platform.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebURLError.h" +#include "third_party/WebKit/public/platform/WebURLLoader.h" +#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" + +using blink::WebString; +using blink::WebURL; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLRequest; +using blink::WebURLResponse; + + +namespace { + +class CefWebURLLoaderClient : public blink::WebURLLoaderClient { + public: + CefWebURLLoaderClient(CefRenderURLRequest::Context* context, + int request_flags); + virtual ~CefWebURLLoaderClient(); + + // blink::WebURLLoaderClient methods. + virtual void willSendRequest( + WebURLLoader* loader, + WebURLRequest& newRequest, + const WebURLResponse& redirectResponse) OVERRIDE; + virtual void didSendData( + WebURLLoader* loader, + unsigned long long bytesSent, + unsigned long long totalBytesToBeSent) OVERRIDE; + virtual void didReceiveResponse( + WebURLLoader* loader, + const WebURLResponse& response) OVERRIDE; + virtual void didDownloadData(WebURLLoader* loader, + int dataLength, + int encodedDataLength) OVERRIDE; + virtual void didReceiveData(WebURLLoader* loader, + const char* data, + int dataLength, + int encodedDataLength) OVERRIDE; + virtual void didReceiveCachedMetadata(WebURLLoader* loader, + const char* data, + int dataLength) OVERRIDE; + virtual void didFinishLoading(WebURLLoader* loader, + double finishTime, + int64_t totalEncodedDataLength) OVERRIDE; + virtual void didFail(WebURLLoader* loader, + const WebURLError& error) OVERRIDE; + + protected: + // The context_ pointer will outlive this object. + CefRenderURLRequest::Context* context_; + int request_flags_; +}; + +} // namespace + + +// CefRenderURLRequest::Context ----------------------------------------------- + +class CefRenderURLRequest::Context + : public base::RefCountedThreadSafe { + public: + Context(CefRefPtr url_request, + CefRefPtr request, + CefRefPtr client) + : url_request_(url_request), + request_(request), + client_(client), + message_loop_proxy_(base::MessageLoop::current()->message_loop_proxy()), + status_(UR_IO_PENDING), + error_code_(ERR_NONE), + upload_data_size_(0), + got_upload_progress_complete_(false), + download_data_received_(0), + download_data_total_(-1) { + // Mark the request as read-only. + static_cast(request_.get())->SetReadOnly(true); + } + + virtual ~Context() { + } + + inline bool CalledOnValidThread() { + return message_loop_proxy_->BelongsToCurrentThread(); + } + + bool Start() { + DCHECK(CalledOnValidThread()); + + GURL url = GURL(request_->GetURL().ToString()); + if (!url.is_valid()) + return false; + + loader_.reset(blink::Platform::current()->createURLLoader()); + url_client_.reset(new CefWebURLLoaderClient(this, request_->GetFlags())); + + WebURLRequest urlRequest; + static_cast(request_.get())->Get(urlRequest); + + if (urlRequest.reportUploadProgress()) { + // Attempt to determine the upload data size. + CefRefPtr post_data = request_->GetPostData(); + if (post_data.get()) { + CefPostData::ElementVector elements; + post_data->GetElements(elements); + if (elements.size() == 1 && elements[0]->GetType() == PDE_TYPE_BYTES) { + CefPostDataElementImpl* impl = + static_cast(elements[0].get()); + upload_data_size_ = impl->GetBytesCount(); + } + } + } + + loader_->loadAsynchronously(urlRequest, url_client_.get()); + return true; + } + + void Cancel() { + DCHECK(CalledOnValidThread()); + + // The request may already be complete. + if (!loader_.get() || status_ != UR_IO_PENDING) + return; + + status_ = UR_CANCELED; + error_code_ = ERR_ABORTED; + + // Will result in a call to OnError(). + loader_->cancel(); + } + + void OnResponse(const WebURLResponse& response) { + DCHECK(CalledOnValidThread()); + + response_ = CefResponse::Create(); + CefResponseImpl* responseImpl = + static_cast(response_.get()); + responseImpl->Set(response); + responseImpl->SetReadOnly(true); + + download_data_total_ = response.expectedContentLength(); + } + + void OnError(const WebURLError& error) { + DCHECK(CalledOnValidThread()); + + if (status_ == UR_IO_PENDING) { + status_ = UR_FAILED; + error_code_ = static_cast(error.reason); + } + + OnComplete(); + } + + void OnComplete() { + DCHECK(CalledOnValidThread()); + + if (status_ == UR_IO_PENDING) { + status_ = UR_SUCCESS; + NotifyUploadProgressIfNecessary(); + } + + if (loader_.get()) + loader_.reset(NULL); + + DCHECK(url_request_.get()); + client_->OnRequestComplete(url_request_.get()); + + // This may result in the Context object being deleted. + url_request_ = NULL; + } + + void OnDownloadProgress(int64 current) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + + NotifyUploadProgressIfNecessary(); + + download_data_received_ += current; + client_->OnDownloadProgress(url_request_.get(), download_data_received_, + download_data_total_); + } + + void OnDownloadData(const char* data, int dataLength) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + client_->OnDownloadData(url_request_.get(), data, dataLength); + } + + void OnUploadProgress(int64 current, int64 total) { + DCHECK(CalledOnValidThread()); + DCHECK(url_request_.get()); + if (current == total) + got_upload_progress_complete_ = true; + client_->OnUploadProgress(url_request_.get(), current, total); + } + + CefRefPtr request() { return request_; } + CefRefPtr client() { return client_; } + CefURLRequest::Status status() { return status_; } + CefURLRequest::ErrorCode error_code() { return error_code_; } + CefRefPtr response() { return response_; } + + private: + void NotifyUploadProgressIfNecessary() { + if (!got_upload_progress_complete_ && upload_data_size_ > 0) { + // URLFetcher sends upload notifications using a timer and will not send + // a notification if the request completes too quickly. We therefore + // send the notification here if necessary. + client_->OnUploadProgress(url_request_.get(), upload_data_size_, + upload_data_size_); + got_upload_progress_complete_ = true; + } + } + + // Members only accessed on the initialization thread. + CefRefPtr url_request_; + CefRefPtr request_; + CefRefPtr client_; + scoped_refptr message_loop_proxy_; + CefURLRequest::Status status_; + CefURLRequest::ErrorCode error_code_; + CefRefPtr response_; + scoped_ptr loader_; + scoped_ptr url_client_; + int64 upload_data_size_; + bool got_upload_progress_complete_; + int64 download_data_received_; + int64 download_data_total_; +}; + + +// CefWebURLLoaderClient -------------------------------------------------- + +namespace { + +CefWebURLLoaderClient::CefWebURLLoaderClient( + CefRenderURLRequest::Context* context, + int request_flags) + : context_(context), + request_flags_(request_flags) { +} + +CefWebURLLoaderClient::~CefWebURLLoaderClient() { +} + +void CefWebURLLoaderClient::willSendRequest( + WebURLLoader* loader, + WebURLRequest& newRequest, + const WebURLResponse& redirectResponse) { +} + +void CefWebURLLoaderClient::didSendData( + WebURLLoader* loader, + unsigned long long bytesSent, + unsigned long long totalBytesToBeSent) { + if (request_flags_ & UR_FLAG_REPORT_UPLOAD_PROGRESS) + context_->OnUploadProgress(bytesSent, totalBytesToBeSent); +} + +void CefWebURLLoaderClient::didReceiveResponse( + WebURLLoader* loader, + const WebURLResponse& response) { + context_->OnResponse(response); +} + +void CefWebURLLoaderClient::didDownloadData(WebURLLoader* loader, + int dataLength, + int encodedDataLength) { +} + +void CefWebURLLoaderClient::didReceiveData(WebURLLoader* loader, + const char* data, + int dataLength, + int encodedDataLength) { + context_->OnDownloadProgress(dataLength); + + if (!(request_flags_ & UR_FLAG_NO_DOWNLOAD_DATA)) + context_->OnDownloadData(data, dataLength); +} + +void CefWebURLLoaderClient::didReceiveCachedMetadata(WebURLLoader* loader, + const char* data, + int dataLength) { +} + +void CefWebURLLoaderClient::didFinishLoading(WebURLLoader* loader, + double finishTime, + int64_t totalEncodedDataLength) { + context_->OnComplete(); +} + +void CefWebURLLoaderClient::didFail(WebURLLoader* loader, + const WebURLError& error) { + context_->OnError(error); +} + + +} // namespace + + +// CefRenderURLRequest -------------------------------------------------------- + +CefRenderURLRequest::CefRenderURLRequest( + CefRefPtr request, + CefRefPtr client) { + context_ = new Context(this, request, client); +} + +CefRenderURLRequest::~CefRenderURLRequest() { +} + +bool CefRenderURLRequest::Start() { + if (!VerifyContext()) + return false; + return context_->Start(); +} + +CefRefPtr CefRenderURLRequest::GetRequest() { + if (!VerifyContext()) + return NULL; + return context_->request(); +} + +CefRefPtr CefRenderURLRequest::GetClient() { + if (!VerifyContext()) + return NULL; + return context_->client(); +} + +CefURLRequest::Status CefRenderURLRequest::GetRequestStatus() { + if (!VerifyContext()) + return UR_UNKNOWN; + return context_->status(); +} + +CefURLRequest::ErrorCode CefRenderURLRequest::GetRequestError() { + if (!VerifyContext()) + return ERR_NONE; + return context_->error_code(); +} + +CefRefPtr CefRenderURLRequest::GetResponse() { + if (!VerifyContext()) + return NULL; + return context_->response(); +} + +void CefRenderURLRequest::Cancel() { + if (!VerifyContext()) + return; + return context_->Cancel(); +} + +bool CefRenderURLRequest::VerifyContext() { + DCHECK(context_.get()); + if (!context_->CalledOnValidThread()) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + return true; +} diff --git a/libcef/renderer/render_urlrequest_impl.h b/libcef/renderer/render_urlrequest_impl.h new file mode 100644 index 000000000..50d894caf --- /dev/null +++ b/libcef/renderer/render_urlrequest_impl.h @@ -0,0 +1,37 @@ +// 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_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_ +#define CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_ + +#include "include/cef_urlrequest.h" +#include "base/memory/ref_counted.h" + +class CefRenderURLRequest : public CefURLRequest { + public: + class Context; + + CefRenderURLRequest(CefRefPtr request, + CefRefPtr client); + virtual ~CefRenderURLRequest(); + + bool Start(); + + // CefURLRequest methods. + virtual CefRefPtr GetRequest() OVERRIDE; + virtual CefRefPtr GetClient() OVERRIDE; + virtual Status GetRequestStatus() OVERRIDE; + virtual ErrorCode GetRequestError() OVERRIDE; + virtual CefRefPtr GetResponse() OVERRIDE; + virtual void Cancel() OVERRIDE; + + private: + bool VerifyContext(); + + scoped_refptr context_; + + IMPLEMENT_REFCOUNTING(CefRenderURLRequest); +}; + +#endif // CEF_LIBCEF_RENDERER_RENDER_URLREQUEST_IMPL_H_ diff --git a/libcef/renderer/thread_util.h b/libcef/renderer/thread_util.h new file mode 100644 index 000000000..1867ef607 --- /dev/null +++ b/libcef/renderer/thread_util.h @@ -0,0 +1,59 @@ +// 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_LIBCEF_RENDERER_THREAD_UTIL_H_ +#define CEF_LIBCEF_RENDERER_THREAD_UTIL_H_ +#pragma once + +#include "libcef/renderer/content_renderer_client.h" + +#include "base/location.h" +#include "base/logging.h" +#include "content/public/renderer/render_thread.h" + +#define CEF_CURRENTLY_ON_RT() (!!content::RenderThread::Get()) + +#define CEF_REQUIRE_RT() DCHECK(CEF_CURRENTLY_ON_RT()) + +#define CEF_REQUIRE_RT_RETURN(var) \ + if (!CEF_CURRENTLY_ON_RT()) { \ + NOTREACHED() << "called on invalid thread"; \ + return var; \ + } + +#define CEF_REQUIRE_RT_RETURN_VOID() \ + if (!CEF_CURRENTLY_ON_RT()) { \ + NOTREACHED() << "called on invalid thread"; \ + return; \ + } + +#define CEF_RENDER_LOOP() \ + (CefContentRendererClient::Get()->render_task_runner()) + +#define CEF_POST_TASK_RT(task) \ + CEF_RENDER_LOOP()->PostTask(FROM_HERE, task) +#define CEF_POST_DELAYED_TASK_RT(task, delay_ms) \ + CEF_RENDER_LOOP()->PostDelayedTask(FROM_HERE, task, \ + base::TimeDelta::FromMilliseconds(delay_ms)) + +// Use this template in conjuction with RefCountedThreadSafe when you want to +// ensure that an object is deleted on the render thread. +struct CefDeleteOnRenderThread { + template + static void Destruct(const T* x) { + if (CEF_CURRENTLY_ON_RT()) { + delete x; + } else { + if (!CEF_RENDER_LOOP()->DeleteSoon(FROM_HERE, x)) { +#if defined(UNIT_TEST) + // Only logged under unit testing because leaks at shutdown + // are acceptable under normal circumstances. + LOG(ERROR) << "DeleteSoon failed on thread " << thread; +#endif // UNIT_TEST + } + } + } +}; + +#endif // CEF_LIBCEF_RENDERER_THREAD_UTIL_H_ diff --git a/libcef/renderer/v8_impl.cc b/libcef/renderer/v8_impl.cc new file mode 100644 index 000000000..7e15697c0 --- /dev/null +++ b/libcef/renderer/v8_impl.cc @@ -0,0 +1,2124 @@ +// 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. + +// MSVC++ requires this to be set before any other includes to get M_PI. +// Otherwise there will be compile errors in wtf/MathExtras.h. +#define _USE_MATH_DEFINES + +#include +#include + +#include "base/command_line.h" +#include "base/compiler_specific.h" + +#include "config.h" +MSVC_PUSH_WARNING_LEVEL(0); +#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include "core/workers/WorkerGlobalScope.h" +#include "bindings/v8/ScriptController.h" +#include "bindings/v8/V8Binding.h" +MSVC_POP_WARNING(); +#undef FROM_HERE +#undef LOG + +#include "libcef/renderer/v8_impl.h" + +#include "libcef/common/cef_switches.h" +#include "libcef/common/content_client.h" +#include "libcef/common/task_runner_impl.h" +#include "libcef/common/tracker.h" +#include "libcef/renderer/browser_impl.h" +#include "libcef/renderer/thread_util.h" +#include "libcef/renderer/webkit_glue.h" + +#include "base/bind.h" +#include "base/lazy_instance.h" +#include "base/strings/string_number_conversions.h" +#include "base/threading/thread_local.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebScriptController.h" +#include "url/gurl.h" + +namespace { + +static const char kCefTrackObject[] = "Cef::TrackObject"; +static const char kCefContextState[] = "Cef::ContextState"; + +void MessageListenerCallbackImpl(v8::Handle message, + v8::Handle data); + +// Manages memory and state information associated with a single Isolate. +class CefV8IsolateManager { + public: + CefV8IsolateManager() + : isolate_(v8::Isolate::GetCurrent()), + task_runner_(CefContentRendererClient::Get()->GetCurrentTaskRunner()), + context_safety_impl_(IMPL_HASH), + message_listener_registered_(false), + worker_id_(0) { + DCHECK(isolate_); + DCHECK(task_runner_.get()); + + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kContextSafetyImplementation)) { + std::string value = command_line.GetSwitchValueASCII( + switches::kContextSafetyImplementation); + int mode; + if (base::StringToInt(value, &mode)) { + if (mode < 0) + context_safety_impl_ = IMPL_DISABLED; + else if (mode == 1) + context_safety_impl_ = IMPL_VALUE; + } + } + } + ~CefV8IsolateManager() { + DCHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + DCHECK(context_map_.empty()); + } + + scoped_refptr GetContextState( + v8::Handle context) { + DCHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + DCHECK(context.IsEmpty() || isolate_ == context->GetIsolate()); + + if (context_safety_impl_ == IMPL_DISABLED) + return scoped_refptr(); + + if (context.IsEmpty()) { + if (isolate_->InContext()) + context = isolate_->GetCurrentContext(); + else + return scoped_refptr(); + } + + if (context_safety_impl_ == IMPL_HASH) { + int hash = context->Global()->GetIdentityHash(); + ContextMap::const_iterator it = context_map_.find(hash); + if (it != context_map_.end()) + return it->second; + + scoped_refptr state = new CefV8ContextState(); + context_map_.insert(std::make_pair(hash, state)); + + return state; + } else { + v8::Handle key = + v8::String::NewFromUtf8(isolate_, kCefContextState); + + v8::Handle object = context->Global(); + v8::Handle value = object->GetHiddenValue(key); + if (!value.IsEmpty()) { + return static_cast( + v8::External::Cast(*value)->Value()); + } + + scoped_refptr state = new CefV8ContextState(); + object->SetHiddenValue(key, v8::External::New(isolate_, state.get())); + + // Reference will be released in ReleaseContext. + state->AddRef(); + + return state; + } + } + + void ReleaseContext(v8::Handle context) { + DCHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + DCHECK_EQ(isolate_, context->GetIsolate()); + + if (context_safety_impl_ == IMPL_DISABLED) + return; + + if (context_safety_impl_ == IMPL_HASH) { + int hash = context->Global()->GetIdentityHash(); + ContextMap::iterator it = context_map_.find(hash); + if (it != context_map_.end()) { + it->second->Detach(); + context_map_.erase(it); + } + } else { + v8::Handle key = + v8::String::NewFromUtf8(isolate_, kCefContextState); + v8::Handle object = context->Global(); + v8::Handle value = object->GetHiddenValue(key); + if (value.IsEmpty()) + return; + + scoped_refptr state = + static_cast(v8::External::Cast(*value)->Value()); + state->Detach(); + object->DeleteHiddenValue(key); + + // Match the AddRef in GetContextState. + state->Release(); + } + } + + void AddGlobalTrackObject(CefTrackNode* object) { + DCHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + global_manager_.Add(object); + } + + void DeleteGlobalTrackObject(CefTrackNode* object) { + DCHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + global_manager_.Delete(object); + } + + void SetUncaughtExceptionStackSize(int stack_size) { + if (stack_size <= 0) + return; + + if (!message_listener_registered_) { + v8::V8::AddMessageListener(&MessageListenerCallbackImpl); + message_listener_registered_ = true; + } + + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true, + stack_size, v8::StackTrace::kDetailed); + } + + void SetWorkerAttributes(int worker_id, const GURL& worker_url) { + worker_id_ = worker_id; + worker_url_ = worker_url; + } + + v8::Isolate* isolate() const { return isolate_; } + scoped_refptr task_runner() const { + return task_runner_; + } + + int worker_id() const { + return worker_id_; + } + + const GURL& worker_url() const { + return worker_url_; + } + + private: + v8::Isolate* isolate_; + scoped_refptr task_runner_; + + enum ContextSafetyImpl { + IMPL_DISABLED, + IMPL_HASH, + IMPL_VALUE, + }; + ContextSafetyImpl context_safety_impl_; + + // Used with IMPL_HASH. + typedef std::map > ContextMap; + ContextMap context_map_; + + // Used for globally tracked objects that are not associated with a particular + // context. + CefTrackManager global_manager_; + + // True if the message listener has been registered. + bool message_listener_registered_; + + // Attributes associated with WebWorker threads. + int worker_id_; + GURL worker_url_; +}; + +// Chromium uses the default Isolate for the main render process thread and a +// new Isolate for each WebWorker thread. Continue this pattern by tracking +// Isolate information on a per-thread basis. This implementation will need to +// be re-worked (perhaps using a map keyed on v8::Isolate::GetCurrent()) if +// in the future Chromium begins using the same Isolate across multiple threads. +class CefV8StateManager { +public: + CefV8StateManager() { + } + + void CreateIsolateManager() { + DCHECK(!current_tls_.Get()); + current_tls_.Set(new CefV8IsolateManager()); + } + + void DestroyIsolateManager() { + DCHECK(current_tls_.Get()); + delete current_tls_.Get(); + current_tls_.Set(NULL); + } + + CefV8IsolateManager* GetIsolateManager() { + CefV8IsolateManager* manager = current_tls_.Get(); + DCHECK(manager); + return manager; + } + + private: + base::ThreadLocalPointer current_tls_; +}; + +base::LazyInstance g_v8_state = LAZY_INSTANCE_INITIALIZER; + +CefV8IsolateManager* GetIsolateManager() { + return g_v8_state.Pointer()->GetIsolateManager(); +} + +class V8TrackObject : public CefTrackNode { + public: + explicit V8TrackObject(v8::Isolate* isolate) + : isolate_(isolate), + external_memory_(0) { + DCHECK(isolate_); + isolate_->AdjustAmountOfExternalAllocatedMemory( + static_cast(sizeof(V8TrackObject))); + } + ~V8TrackObject() { + isolate_->AdjustAmountOfExternalAllocatedMemory( + -static_cast(sizeof(V8TrackObject)) - external_memory_); + } + + inline int GetExternallyAllocatedMemory() { + return external_memory_; + } + + int AdjustExternallyAllocatedMemory(int change_in_bytes) { + int new_value = external_memory_ + change_in_bytes; + if (new_value < 0) { + NOTREACHED() << "External memory usage cannot be less than 0 bytes"; + change_in_bytes = -(external_memory_); + new_value = 0; + } + + if (change_in_bytes != 0) + isolate_->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); + external_memory_ = new_value; + + return new_value; + } + + inline void SetAccessor(CefRefPtr accessor) { + accessor_ = accessor; + } + + inline CefRefPtr GetAccessor() { + return accessor_; + } + + inline void SetHandler(CefRefPtr handler) { + handler_ = handler; + } + + inline CefRefPtr GetHandler() { + return handler_; + } + + inline void SetUserData(CefRefPtr user_data) { + user_data_ = user_data; + } + + inline CefRefPtr GetUserData() { + return user_data_; + } + + // Attach this track object to the specified V8 object. + void AttachTo(v8::Handle object) { + object->SetHiddenValue(v8::String::NewFromUtf8(isolate_, kCefTrackObject), + v8::External::New(isolate_, this)); + } + + // Retrieve the track object for the specified V8 object. + static V8TrackObject* Unwrap(v8::Isolate* isolate, + v8::Handle object) { + DCHECK(isolate); + v8::Local value = + object->GetHiddenValue( + v8::String::NewFromUtf8(isolate, kCefTrackObject)); + if (!value.IsEmpty()) + return static_cast(v8::External::Cast(*value)->Value()); + + return NULL; + } + + private: + v8::Isolate* isolate_; + CefRefPtr accessor_; + CefRefPtr handler_; + CefRefPtr user_data_; + int external_memory_; +}; + +class V8TrackString : public CefTrackNode { + public: + explicit V8TrackString(const std::string& str) : string_(str) {} + const char* GetString() { return string_.c_str(); } + + private: + std::string string_; +}; + + +// Convert a CefString to a V8::String. +v8::Handle GetV8String(v8::Isolate* isolate, + const CefString& str) { +#if defined(CEF_STRING_TYPE_UTF16) + // Already a UTF16 string. + return v8::String::NewFromTwoByte( + isolate, + reinterpret_cast( + const_cast(str.c_str())), + v8::String::kNormalString, + str.length()); +#elif defined(CEF_STRING_TYPE_UTF8) + // Already a UTF8 string. + return v8::String::NewFromUtf8(isolate, + const_cast(str.c_str()), + v8::String::kNormalString, + str.length()); +#else + // Convert the string to UTF8. + std::string tmpStr = str; + return v8::String::NewFromUtf8(isolate, + tmpStr.c_str(), + v8::String::kNormalString, + tmpStr.length()); +#endif +} + +#if defined(CEF_STRING_TYPE_UTF16) +void v8impl_string_dtor(char16* str) { + delete [] str; +} +#elif defined(CEF_STRING_TYPE_UTF8) +void v8impl_string_dtor(char* str) { + delete [] str; +} +#endif + +// Convert a v8::String to CefString. +void GetCefString(v8::Handle str, CefString& out) { + if (str.IsEmpty()) + return; + +#if defined(CEF_STRING_TYPE_WIDE) + // Allocate enough space for a worst-case conversion. + int len = str->Utf8Length(); + if (len == 0) + return; + char* buf = new char[len + 1]; + str->WriteUtf8(buf, len + 1); + + // Perform conversion to the wide type. + cef_string_t* retws = out.GetWritableStruct(); + cef_string_utf8_to_wide(buf, len, retws); + + delete [] buf; +#else // !defined(CEF_STRING_TYPE_WIDE) +#if defined(CEF_STRING_TYPE_UTF16) + int len = str->Length(); + if (len == 0) + return; + char16* buf = new char16[len + 1]; + str->Write(reinterpret_cast(buf), 0, len + 1); +#else + // Allocate enough space for a worst-case conversion. + int len = str->Utf8Length(); + if (len == 0) + return; + char* buf = new char[len + 1]; + str->WriteUtf8(buf, len + 1); +#endif + + // Don't perform an extra string copy. + out.clear(); + cef_string_t* retws = out.GetWritableStruct(); + retws->str = buf; + retws->length = len; + retws->dtor = v8impl_string_dtor; +#endif // !defined(CEF_STRING_TYPE_WIDE) +} + +// V8 function callback. +void FunctionCallbackImpl(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + + CefV8Handler* handler = + static_cast(v8::External::Cast(*info.Data())->Value()); + + CefV8ValueList params; + for (int i = 0; i < info.Length(); i++) + params.push_back(new CefV8ValueImpl(isolate, info[i])); + + CefString func_name; + GetCefString(v8::Handle::Cast(info.Callee()->GetName()), + func_name); + CefRefPtr object = new CefV8ValueImpl(isolate, info.This()); + CefRefPtr retval; + CefString exception; + + if (handler->Execute(func_name, object, params, retval, exception)) { + if (!exception.empty()) { + info.GetReturnValue().Set( + isolate->ThrowException( + v8::Exception::Error(GetV8String(isolate, exception)))); + return; + } else { + CefV8ValueImpl* rv = static_cast(retval.get()); + if (rv && rv->IsValid()) { + info.GetReturnValue().Set(rv->GetV8Value(true)); + return; + } + } + } + + info.GetReturnValue().SetUndefined(); +} + +// V8 Accessor callbacks +void AccessorGetterCallbackImpl( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + + v8::Handle obj = info.This(); + + CefRefPtr accessorPtr; + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + accessorPtr = tracker->GetAccessor(); + + if (accessorPtr.get()) { + CefRefPtr retval; + CefRefPtr object = new CefV8ValueImpl(isolate, obj); + CefString name, exception; + GetCefString(property, name); + if (accessorPtr->Get(name, object, retval, exception)) { + if (!exception.empty()) { + info.GetReturnValue().Set( + isolate->ThrowException( + v8::Exception::Error(GetV8String(isolate, exception)))); + return; + } else { + CefV8ValueImpl* rv = static_cast(retval.get()); + if (rv && rv->IsValid()) { + info.GetReturnValue().Set(rv->GetV8Value(true)); + return; + } + } + } + } + + return info.GetReturnValue().SetUndefined(); +} + +void AccessorSetterCallbackImpl( + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + + v8::Handle obj = info.This(); + + CefRefPtr accessorPtr; + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + accessorPtr = tracker->GetAccessor(); + + if (accessorPtr.get()) { + CefRefPtr object = new CefV8ValueImpl(isolate, obj); + CefRefPtr cefValue = new CefV8ValueImpl(isolate, value); + CefString name, exception; + GetCefString(property, name); + accessorPtr->Set(name, object, cefValue, exception); + if (!exception.empty()) { + isolate->ThrowException( + v8::Exception::Error(GetV8String(isolate, exception))); + return; + } + } +} + +v8::Local CallV8Function(v8::Handle context, + v8::Handle function, + v8::Handle receiver, + int argc, + v8::Handle args[], + v8::Isolate* isolate) { + v8::Local func_rv; + + // Execute the function call using the ScriptController so that inspector + // instrumentation works. + if (CEF_CURRENTLY_ON_RT()) { + RefPtr frame = WebCore::toFrameIfNotDetached(context); + DCHECK(frame); + if (frame && + frame->script().canExecuteScripts(WebCore::AboutToExecuteScript)) { + func_rv = frame->script().callFunction(function, receiver, argc, args); + } + } else { + func_rv = WebCore::ScriptController::callFunction( + WebCore::toExecutionContext(context), + function, receiver, argc, args, isolate); + } + + return func_rv; +} + + +// V8 extension registration. + +class ExtensionWrapper : public v8::Extension { + public: + ExtensionWrapper(const char* extension_name, + const char* javascript_code, + CefV8Handler* handler) + : v8::Extension(extension_name, javascript_code), handler_(handler) { + } + + virtual v8::Handle GetNativeFunctionTemplate( + v8::Isolate* isolate, + v8::Handle name) OVERRIDE { + if (!handler_) + return v8::Handle(); + + return v8::FunctionTemplate::New(isolate, + FunctionCallbackImpl, + v8::External::New(isolate, handler_)); + } + + private: + CefV8Handler* handler_; +}; + +class CefV8ExceptionImpl : public CefV8Exception { + public: + explicit CefV8ExceptionImpl(v8::Handle message) + : line_number_(0), + start_position_(0), + end_position_(0), + start_column_(0), + end_column_(0) { + if (message.IsEmpty()) + return; + + GetCefString(message->Get(), message_); + GetCefString(message->GetSourceLine(), source_line_); + + if (!message->GetScriptResourceName().IsEmpty()) + GetCefString(message->GetScriptResourceName()->ToString(), script_); + + line_number_ = message->GetLineNumber(); + start_position_ = message->GetStartPosition(); + end_position_ = message->GetEndPosition(); + start_column_ = message->GetStartColumn(); + end_column_ = message->GetEndColumn(); + } + + virtual CefString GetMessage() OVERRIDE { return message_; } + virtual CefString GetSourceLine() OVERRIDE { return source_line_; } + virtual CefString GetScriptResourceName() OVERRIDE { return script_; } + virtual int GetLineNumber() OVERRIDE { return line_number_; } + virtual int GetStartPosition() OVERRIDE { return start_position_; } + virtual int GetEndPosition() OVERRIDE { return end_position_; } + virtual int GetStartColumn() OVERRIDE { return start_column_; } + virtual int GetEndColumn() OVERRIDE { return end_column_; } + + protected: + CefString message_; + CefString source_line_; + CefString script_; + int line_number_; + int start_position_; + int end_position_; + int start_column_; + int end_column_; + + IMPLEMENT_REFCOUNTING(CefV8ExceptionImpl); +}; + +void MessageListenerCallbackImpl(v8::Handle message, + v8::Handle data) { + CefRefPtr application = CefContentClient::Get()->application(); + if (!application.get()) + return; + + CefRefPtr handler = + application->GetRenderProcessHandler(); + if (!handler.get()) + return; + + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr context = CefV8Context::GetCurrentContext(); + v8::Handle v8Stack = message->GetStackTrace(); + DCHECK(!v8Stack.IsEmpty()); + CefRefPtr stackTrace = + new CefV8StackTraceImpl(isolate, v8Stack); + + CefRefPtr exception = new CefV8ExceptionImpl(message); + + if (CEF_CURRENTLY_ON_RT()) { + handler->OnUncaughtException(context->GetBrowser(), context->GetFrame(), + context, exception, stackTrace); + } +} + +} // namespace + + +// Global functions. + +void CefV8IsolateCreated() { + g_v8_state.Pointer()->CreateIsolateManager(); +} + +void CefV8IsolateDestroyed() { + g_v8_state.Pointer()->DestroyIsolateManager(); +} + +void CefV8ReleaseContext(v8::Handle context) { + GetIsolateManager()->ReleaseContext(context); +} + +void CefV8SetUncaughtExceptionStackSize(int stack_size) { + GetIsolateManager()->SetUncaughtExceptionStackSize(stack_size); +} + +void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url) { + GetIsolateManager()->SetWorkerAttributes(worker_id, worker_url); +} + +bool CefRegisterExtension(const CefString& extension_name, + const CefString& javascript_code, + CefRefPtr handler) { + // Verify that this method was called on the correct thread. + CEF_REQUIRE_RT_RETURN(false); + + CefV8IsolateManager* isolate_manager = GetIsolateManager(); + + V8TrackString* name = new V8TrackString(extension_name); + isolate_manager->AddGlobalTrackObject(name); + V8TrackString* code = new V8TrackString(javascript_code); + isolate_manager->AddGlobalTrackObject(code); + + if (handler) { + // The reference will be released when the process exits. + V8TrackObject* object = new V8TrackObject(isolate_manager->isolate()); + object->SetHandler(handler); + isolate_manager->AddGlobalTrackObject(object); + } + + ExtensionWrapper* wrapper = new ExtensionWrapper( + name->GetString(), + code->GetString(), + handler.get()); + + content::RenderThread::Get()->RegisterExtension(wrapper); + return true; +} + + +// Helper macros + +#define CEF_V8_HAS_ISOLATE() (!!GetIsolateManager()) +#define CEF_V8_REQUIRE_ISOLATE_RETURN(var) \ + if (!CEF_V8_HAS_ISOLATE()) { \ + NOTREACHED() << "V8 isolate is not valid"; \ + return var; \ + } + +#define CEF_V8_CURRENTLY_ON_MLT() \ + (!handle_.get() || handle_->BelongsToCurrentThread()) +#define CEF_V8_REQUIRE_MLT_RETURN(var) \ + CEF_V8_REQUIRE_ISOLATE_RETURN(var); \ + if (!CEF_V8_CURRENTLY_ON_MLT()) { \ + NOTREACHED() << "called on incorrect thread"; \ + return var; \ + } + +#define CEF_V8_HANDLE_IS_VALID() (handle_.get() && handle_->IsValid()) +#define CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret) \ + CEF_V8_REQUIRE_MLT_RETURN(ret); \ + if (!CEF_V8_HANDLE_IS_VALID()) { \ + NOTREACHED() << "V8 handle is not valid"; \ + return ret; \ + } + +#define CEF_V8_IS_VALID() \ + (CEF_V8_HAS_ISOLATE() && \ + CEF_V8_CURRENTLY_ON_MLT() && \ + CEF_V8_HANDLE_IS_VALID()) + +#define CEF_V8_REQUIRE_OBJECT_RETURN(ret) \ + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret); \ + if (type_ != TYPE_OBJECT) { \ + NOTREACHED() << "V8 value is not an object"; \ + return ret; \ + } + + +// CefV8HandleBase + +CefV8HandleBase::~CefV8HandleBase() { + DCHECK(BelongsToCurrentThread()); +} + +bool CefV8HandleBase::BelongsToCurrentThread() const { + return task_runner_->RunsTasksOnCurrentThread(); +} + +CefV8HandleBase::CefV8HandleBase(v8::Isolate* isolate, + v8::Handle context) + : isolate_(isolate) { + DCHECK(isolate_); + + CefV8IsolateManager* manager = GetIsolateManager(); + DCHECK(manager); + DCHECK_EQ(isolate_, manager->isolate()); + + task_runner_ = manager->task_runner(); + context_state_ = manager->GetContextState(context); +} + + +// CefV8Context + +// static +CefRefPtr CefV8Context::GetCurrentContext() { + CefRefPtr context; + CEF_V8_REQUIRE_ISOLATE_RETURN(context); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + if (isolate->InContext()) { + v8::HandleScope handle_scope(isolate); + context = new CefV8ContextImpl(isolate, isolate->GetCurrentContext()); + } + return context; +} + +// static +CefRefPtr CefV8Context::GetEnteredContext() { + CefRefPtr context; + CEF_V8_REQUIRE_ISOLATE_RETURN(context); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + if (isolate->InContext()) { + v8::HandleScope handle_scope(isolate); + context = new CefV8ContextImpl(isolate, isolate->GetEnteredContext()); + } + return context; +} + +// static +bool CefV8Context::InContext() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + return isolate->InContext(); +} + + +// CefV8ContextImpl + +CefV8ContextImpl::CefV8ContextImpl(v8::Isolate* isolate, + v8::Handle context) + : handle_(new Handle(isolate, context, context)) +#ifndef NDEBUG + , enter_count_(0) +#endif +{ // NOLINT(whitespace/braces) +} + +CefV8ContextImpl::~CefV8ContextImpl() { + DLOG_ASSERT(0 == enter_count_); +} + +CefRefPtr CefV8ContextImpl::GetTaskRunner() { + return new CefTaskRunnerImpl(handle_->task_runner()); +} + +bool CefV8ContextImpl::IsValid() { + return CEF_V8_IS_VALID(); +} + +CefRefPtr CefV8ContextImpl::GetBrowser() { + CefRefPtr browser; + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(browser); + + // Return NULL for WebWorkers. + if (!CEF_CURRENTLY_ON_RT()) + return browser; + + blink::WebFrame* webframe = GetWebFrame(); + if (webframe) + browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->top()); + + return browser; +} + +CefRefPtr CefV8ContextImpl::GetFrame() { + CefRefPtr frame; + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(frame); + + // Return NULL for WebWorkers. + if (!CEF_CURRENTLY_ON_RT()) + return frame; + + blink::WebFrame* webframe = GetWebFrame(); + if (webframe) { + CefRefPtr browser = + CefBrowserImpl::GetBrowserForMainFrame(webframe->top()); + frame = browser->GetFrame(webkit_glue::GetIdentifier(webframe)); + } + + return frame; +} + +CefRefPtr CefV8ContextImpl::GetGlobal() { + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(NULL); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle context = GetV8Context(); + v8::Context::Scope context_scope(context); + return new CefV8ValueImpl(isolate, context->Global()); +} + +bool CefV8ContextImpl::Enter() { + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + + WebCore::V8PerIsolateData::from(isolate)->incrementRecursionLevel(); + handle_->GetNewV8Handle()->Enter(); +#ifndef NDEBUG + ++enter_count_; +#endif + return true; +} + +bool CefV8ContextImpl::Exit() { + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(handle_->isolate()); + + DLOG_ASSERT(enter_count_ > 0); + handle_->GetNewV8Handle()->Exit(); + WebCore::V8PerIsolateData::from(isolate)->decrementRecursionLevel(); +#ifndef NDEBUG + --enter_count_; +#endif + return true; +} + +bool CefV8ContextImpl::IsSame(CefRefPtr that) { + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false); + + CefV8ContextImpl* impl = static_cast(that.get()); + if (!impl || !impl->IsValid()) + return false; + + return (handle_->GetPersistentV8Handle() == + impl->handle_->GetPersistentV8Handle()); +} + +bool CefV8ContextImpl::Eval(const CefString& code, + CefRefPtr& retval, + CefRefPtr& exception) { + CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false); + + if (code.empty()) { + NOTREACHED() << "invalid input parameter"; + return false; + } + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Local context = GetV8Context(); + v8::Context::Scope context_scope(context); + v8::Local obj = context->Global(); + + // Retrieve the eval function. + v8::Local val = obj->Get(v8::String::NewFromUtf8(isolate, "eval")); + if (val.IsEmpty() || !val->IsFunction()) + return false; + + v8::Local func = v8::Local::Cast(val); + v8::Handle code_val = GetV8String(isolate, code); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + + retval = NULL; + exception = NULL; + + v8::Local func_rv = + CallV8Function(context, func, obj, 1, &code_val, handle_->isolate()); + + if (try_catch.HasCaught()) { + exception = new CefV8ExceptionImpl(try_catch.Message()); + return false; + } else if (!func_rv.IsEmpty()) { + retval = new CefV8ValueImpl(isolate, func_rv); + } + return true; +} + +v8::Handle CefV8ContextImpl::GetV8Context() { + return handle_->GetNewV8Handle(); +} + +blink::WebFrame* CefV8ContextImpl::GetWebFrame() { + CEF_REQUIRE_RT(); + v8::HandleScope handle_scope(handle_->isolate()); + v8::Context::Scope context_scope(GetV8Context()); + return blink::WebLocalFrame::frameForCurrentContext(); +} + + +// CefV8ValueImpl::Handle + +CefV8ValueImpl::Handle::Handle(v8::Isolate* isolate, + v8::Handle context, + handleType v, + CefTrackNode* tracker) + : CefV8HandleBase(isolate, context), + handle_(isolate, v), + tracker_(tracker), + should_persist_(false), + is_set_weak_(false) { +} + +CefV8ValueImpl::Handle::~Handle() { + DCHECK(BelongsToCurrentThread()); + + if (tracker_) { + if (is_set_weak_) { + if (context_state_.get()) { + // If the associated context is still valid then delete |tracker_|. + // Otherwise, |tracker_| will already have been deleted. + if (context_state_->IsValid()) + context_state_->DeleteTrackObject(tracker_); + } else { + GetIsolateManager()->DeleteGlobalTrackObject(tracker_); + } + + isolate_->AdjustAmountOfExternalAllocatedMemory( + -static_cast(sizeof(Handle))); + } else { + delete tracker_; + } + } + + // Always call Reset() on a persistent handle to avoid the + // CHECK(state() != NEAR_DEATH) in V8's PostGarbageCollectionProcessing. + handle_.Reset(); +} + +CefV8ValueImpl::Handle::handleType +CefV8ValueImpl::Handle::GetNewV8Handle(bool should_persist) { + DCHECK(IsValid()); + if (should_persist && !should_persist_) + should_persist_ = true; + return handleType::New(isolate(), handle_); +} + +CefV8ValueImpl::Handle::persistentType& +CefV8ValueImpl::Handle::GetPersistentV8Handle() { + return handle_; +} + +void CefV8ValueImpl::Handle::SetWeakIfNecessary() { + if (!BelongsToCurrentThread()) { + task_runner()->PostTask(FROM_HERE, + base::Bind(&CefV8ValueImpl::Handle::SetWeakIfNecessary, this)); + return; + } + + // Persist the handle (call SetWeak) if: + // A. The handle has been passed into a V8 function or used as a return value + // from a V8 callback, and + // B. The associated context, if any, is still valid. + if (should_persist_ && (!context_state_.get() || context_state_->IsValid())) { + is_set_weak_ = true; + + if (tracker_) { + if (context_state_.get()) { + // |tracker_| will be deleted when: + // A. The associated context is released, or + // B. Destructor is called for the weak handle. + DCHECK(context_state_->IsValid()); + context_state_->AddTrackObject(tracker_); + } else { + // |tracker_| will be deleted when: + // A. The process shuts down, or + // B. Destructor is called for the weak handle. + GetIsolateManager()->AddGlobalTrackObject(tracker_); + } + } + + isolate_->AdjustAmountOfExternalAllocatedMemory( + static_cast(sizeof(Handle))); + + // The added reference will be released in Destructor. + AddRef(); + handle_.SetWeak(this, Destructor); + } +} + +// static +void CefV8ValueImpl::Handle::Destructor( + const v8::WeakCallbackData& data) { + data.GetParameter()->Release(); +} + + +// CefV8Value + +// static +CefRefPtr CefV8Value::CreateUndefined() { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitUndefined(); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateNull() { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitNull(); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateBool(bool value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitBool(value); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateInt(int32 value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitInt(value); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateUInt(uint32 value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitUInt(value); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateDouble(double value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitDouble(value); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateDate(const CefTime& value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitDate(value); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateString(const CefString& value) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + v8::Isolate* isolate = GetIsolateManager()->isolate(); + CefRefPtr impl = new CefV8ValueImpl(isolate); + CefString str(value); + impl->InitString(str); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateObject( + CefRefPtr accessor) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + + v8::Isolate* isolate = GetIsolateManager()->isolate(); + v8::HandleScope handle_scope(isolate); + + v8::Local context = isolate->GetCurrentContext(); + if (context.IsEmpty()) { + NOTREACHED() << "not currently in a V8 context"; + return NULL; + } + + // Create the new V8 object. + v8::Local obj = v8::Object::New(isolate); + + // Create a tracker object that will cause the user data and/or accessor + // reference to be released when the V8 object is destroyed. + V8TrackObject* tracker = new V8TrackObject(isolate); + tracker->SetAccessor(accessor); + + // Attach the tracker object. + tracker->AttachTo(obj); + + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitObject(obj, tracker); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateArray(int length) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + + v8::Isolate* isolate = GetIsolateManager()->isolate(); + v8::HandleScope handle_scope(isolate); + + v8::Local context = isolate->GetCurrentContext(); + if (context.IsEmpty()) { + NOTREACHED() << "not currently in a V8 context"; + return NULL; + } + + // Create a tracker object that will cause the user data reference to be + // released when the V8 object is destroyed. + V8TrackObject* tracker = new V8TrackObject(isolate); + + // Create the new V8 array. + v8::Local arr = v8::Array::New(isolate, length); + + // Attach the tracker object. + tracker->AttachTo(arr); + + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitObject(arr, tracker); + return impl.get(); +} + +// static +CefRefPtr CefV8Value::CreateFunction( + const CefString& name, + CefRefPtr handler) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + + if (!handler.get()) { + NOTREACHED() << "invalid parameter"; + return NULL; + } + + v8::Isolate* isolate = GetIsolateManager()->isolate(); + v8::HandleScope handle_scope(isolate); + + v8::Local context = isolate->GetCurrentContext(); + if (context.IsEmpty()) { + NOTREACHED() << "not currently in a V8 context"; + return NULL; + } + + // Create a new V8 function template. + v8::Local tmpl = v8::FunctionTemplate::New(isolate); + + v8::Local data = v8::External::New(isolate, handler.get()); + + // Set the function handler callback. + tmpl->SetCallHandler(FunctionCallbackImpl, data); + + // Retrieve the function object and set the name. + v8::Local func = tmpl->GetFunction(); + if (func.IsEmpty()) { + NOTREACHED() << "failed to create V8 function"; + return NULL; + } + + func->SetName(GetV8String(isolate, name)); + + // Create a tracker object that will cause the user data and/or handler + // reference to be released when the V8 object is destroyed. + V8TrackObject* tracker = new V8TrackObject(isolate); + tracker->SetHandler(handler); + + // Attach the tracker object. + tracker->AttachTo(func); + + // Create the CefV8ValueImpl and provide a tracker object that will cause + // the handler reference to be released when the V8 object is destroyed. + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitObject(func, tracker); + return impl.get(); +} + + +// CefV8ValueImpl + +CefV8ValueImpl::CefV8ValueImpl(v8::Isolate* isolate) + : isolate_(isolate), + type_(TYPE_INVALID), + rethrow_exceptions_(false) { + DCHECK(isolate_); +} + +CefV8ValueImpl::CefV8ValueImpl(v8::Isolate* isolate, + v8::Handle value) + : isolate_(isolate), + type_(TYPE_INVALID), + rethrow_exceptions_(false) { + DCHECK(isolate_); + InitFromV8Value(value); +} + +CefV8ValueImpl::~CefV8ValueImpl() { + if (type_ == TYPE_STRING) + cef_string_clear(&string_value_); + if (handle_) + handle_->SetWeakIfNecessary(); +} + +void CefV8ValueImpl::InitFromV8Value(v8::Handle value) { + if (value->IsUndefined()) { + InitUndefined(); + } else if (value->IsNull()) { + InitNull(); + } else if (value->IsTrue()) { + InitBool(true); + } else if (value->IsFalse()) { + InitBool(false); + } else if (value->IsBoolean()) { + InitBool(value->ToBoolean()->Value()); + } else if (value->IsInt32()) { + InitInt(value->ToInt32()->Value()); + } else if (value->IsUint32()) { + InitUInt(value->ToUint32()->Value()); + } else if (value->IsNumber()) { + InitDouble(value->ToNumber()->Value()); + } else if (value->IsDate()) { + // Convert from milliseconds to seconds. + InitDate(CefTime(value->ToNumber()->Value() / 1000)); + } else if (value->IsString()) { + CefString rv; + GetCefString(value->ToString(), rv); + InitString(rv); + } else if (value->IsObject()) { + InitObject(value, NULL); + } +} + +void CefV8ValueImpl::InitUndefined() { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_UNDEFINED; +} + +void CefV8ValueImpl::InitNull() { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_NULL; +} + +void CefV8ValueImpl::InitBool(bool value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_BOOL; + bool_value_ = value; +} + +void CefV8ValueImpl::InitInt(int32 value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_INT; + int_value_ = value; +} + +void CefV8ValueImpl::InitUInt(uint32 value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_UINT; + uint_value_ = value; +} + +void CefV8ValueImpl::InitDouble(double value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_DOUBLE; + double_value_ = value; +} + +void CefV8ValueImpl::InitDate(const CefTime& value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_DATE; + date_value_ = value; +} + +void CefV8ValueImpl::InitString(CefString& value) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_STRING; + // Take ownership of the underling string value. + const cef_string_t* str = value.GetStruct(); + if (str) { + string_value_ = *str; + cef_string_t* writable_struct = value.GetWritableStruct(); + writable_struct->str = NULL; + writable_struct->length = 0; + } else { + string_value_.str = NULL; + string_value_.length = 0; + } +} + +void CefV8ValueImpl::InitObject(v8::Handle value, CefTrackNode* tracker) { + DCHECK_EQ(type_, TYPE_INVALID); + type_ = TYPE_OBJECT; + handle_ = new Handle(isolate_, v8::Handle(), value, tracker); +} + +v8::Handle CefV8ValueImpl::GetV8Value(bool should_persist) { + switch (type_) { + case TYPE_UNDEFINED: + return v8::Undefined(isolate_); + case TYPE_NULL: + return v8::Null(isolate_); + case TYPE_BOOL: + return v8::Boolean::New(isolate_, bool_value_); + case TYPE_INT: + return v8::Int32::New(isolate_, int_value_); + case TYPE_UINT: + return v8::Uint32::New(isolate_, uint_value_); + case TYPE_DOUBLE: + return v8::Number::New(isolate_, double_value_); + case TYPE_DATE: + // Convert from seconds to milliseconds. + return v8::Date::New(isolate_, CefTime(date_value_).GetDoubleT() * 1000); + case TYPE_STRING: + return GetV8String(isolate_, CefString(&string_value_)); + case TYPE_OBJECT: + return handle_->GetNewV8Handle(should_persist); + default: + break; + } + + NOTREACHED() << "Invalid type for CefV8ValueImpl"; + return v8::Handle(); +} + +bool CefV8ValueImpl::IsValid() { + if (!CEF_V8_HAS_ISOLATE() || type_ == TYPE_INVALID || + (type_ == TYPE_OBJECT && + (!handle_->BelongsToCurrentThread() || !handle_->IsValid()))) { + return false; + } + return true; +} + +bool CefV8ValueImpl::IsUndefined() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_UNDEFINED); +} + +bool CefV8ValueImpl::IsNull() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_NULL); +} + +bool CefV8ValueImpl::IsBool() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_BOOL); +} + +bool CefV8ValueImpl::IsInt() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_INT || type_ == TYPE_UINT); +} + +bool CefV8ValueImpl::IsUInt() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_INT || type_ == TYPE_UINT); +} + +bool CefV8ValueImpl::IsDouble() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_INT || type_ == TYPE_UINT || type_ == TYPE_DOUBLE); +} + +bool CefV8ValueImpl::IsDate() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_DATE); +} + +bool CefV8ValueImpl::IsString() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_STRING); +} + +bool CefV8ValueImpl::IsObject() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + return (type_ == TYPE_OBJECT); +} + +bool CefV8ValueImpl::IsArray() { + CEF_V8_REQUIRE_MLT_RETURN(false); + if (type_ == TYPE_OBJECT) { + v8::HandleScope handle_scope(handle_->isolate()); + return handle_->GetNewV8Handle(false)->IsArray(); + } else { + return false; + } +} + +bool CefV8ValueImpl::IsFunction() { + CEF_V8_REQUIRE_MLT_RETURN(false); + if (type_ == TYPE_OBJECT) { + v8::HandleScope handle_scope(handle_->isolate()); + return handle_->GetNewV8Handle(false)->IsFunction(); + } else { + return false; + } +} + +bool CefV8ValueImpl::IsSame(CefRefPtr that) { + CEF_V8_REQUIRE_MLT_RETURN(false); + + CefV8ValueImpl* thatValue = static_cast(that.get()); + if (!thatValue || !thatValue->IsValid() || type_ != thatValue->type_) + return false; + + switch (type_) { + case TYPE_UNDEFINED: + case TYPE_NULL: + return true; + case TYPE_BOOL: + return (bool_value_ == thatValue->bool_value_); + case TYPE_INT: + return (int_value_ == thatValue->int_value_); + case TYPE_UINT: + return (uint_value_ == thatValue->uint_value_); + case TYPE_DOUBLE: + return (double_value_ == thatValue->double_value_); + case TYPE_DATE: + return (CefTime(date_value_).GetTimeT() == + CefTime(thatValue->date_value_).GetTimeT()); + case TYPE_STRING: + return (CefString(&string_value_) == + CefString(&thatValue->string_value_)); + case TYPE_OBJECT: { + return (handle_->GetPersistentV8Handle() == + thatValue->handle_->GetPersistentV8Handle()); + } + default: + break; + } + + return false; +} + +bool CefV8ValueImpl::GetBoolValue() { + CEF_V8_REQUIRE_ISOLATE_RETURN(false); + if (type_ == TYPE_BOOL) + return bool_value_; + return false; +} + +int32 CefV8ValueImpl::GetIntValue() { + CEF_V8_REQUIRE_ISOLATE_RETURN(0); + if (type_ == TYPE_INT || type_ == TYPE_UINT) + return int_value_; + return 0; +} + +uint32 CefV8ValueImpl::GetUIntValue() { + CEF_V8_REQUIRE_ISOLATE_RETURN(0); + if (type_ == TYPE_INT || type_ == TYPE_UINT) + return uint_value_; + return 0; +} + +double CefV8ValueImpl::GetDoubleValue() { + CEF_V8_REQUIRE_ISOLATE_RETURN(0.); + if (type_ == TYPE_DOUBLE) + return double_value_; + else if (type_ == TYPE_INT) + return int_value_; + else if (type_ == TYPE_UINT) + return uint_value_; + return 0.; +} + +CefTime CefV8ValueImpl::GetDateValue() { + CEF_V8_REQUIRE_ISOLATE_RETURN(CefTime(0.)); + if (type_ == TYPE_DATE) + return date_value_; + return CefTime(0.); +} + +CefString CefV8ValueImpl::GetStringValue() { + CefString rv; + CEF_V8_REQUIRE_ISOLATE_RETURN(rv); + if (type_ == TYPE_STRING) + rv = CefString(&string_value_); + return rv; +} + +bool CefV8ValueImpl::IsUserCreated() { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + return (tracker != NULL); +} + +bool CefV8ValueImpl::HasException() { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + return (last_exception_.get() != NULL); +} + +CefRefPtr CefV8ValueImpl::GetException() { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + return last_exception_; +} + +bool CefV8ValueImpl::ClearException() { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + last_exception_ = NULL; + return true; +} + +bool CefV8ValueImpl::WillRethrowExceptions() { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + return rethrow_exceptions_; +} + +bool CefV8ValueImpl::SetRethrowExceptions(bool rethrow) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + rethrow_exceptions_ = rethrow; + return true; +} + +bool CefV8ValueImpl::HasValue(const CefString& key) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + return obj->Has(GetV8String(isolate, key)); +} + +bool CefV8ValueImpl::HasValue(int index) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + if (index < 0) { + NOTREACHED() << "invalid input parameter"; + return false; + } + + v8::HandleScope handle_scope(handle_->isolate()); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + return obj->Has(index); +} + +bool CefV8ValueImpl::DeleteValue(const CefString& key) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + bool del = obj->Delete(GetV8String(isolate, key)); + return (!HasCaught(try_catch) && del); +} + +bool CefV8ValueImpl::DeleteValue(int index) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + if (index < 0) { + NOTREACHED() << "invalid input parameter"; + return false; + } + + v8::HandleScope handle_scope(handle_->isolate()); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + bool del = obj->Delete(index); + return (!HasCaught(try_catch) && del); +} + +CefRefPtr CefV8ValueImpl::GetValue(const CefString& key) { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + v8::Local ret_value = obj->Get(GetV8String(isolate, key)); + if (!HasCaught(try_catch) && !ret_value.IsEmpty()) + return new CefV8ValueImpl(isolate, ret_value); + return NULL; +} + +CefRefPtr CefV8ValueImpl::GetValue(int index) { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + if (index < 0) { + NOTREACHED() << "invalid input parameter"; + return NULL; + } + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + v8::Local ret_value = obj->Get(v8::Number::New(isolate, index)); + if (!HasCaught(try_catch) && !ret_value.IsEmpty()) + return new CefV8ValueImpl(isolate, ret_value); + return NULL; +} + +bool CefV8ValueImpl::SetValue(const CefString& key, + CefRefPtr value, + PropertyAttribute attribute) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + CefV8ValueImpl* impl = static_cast(value.get()); + if (impl && impl->IsValid()) { + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + bool set = obj->Set(GetV8String(isolate, key), impl->GetV8Value(true), + static_cast(attribute)); + return (!HasCaught(try_catch) && set); + } else { + NOTREACHED() << "invalid input parameter"; + return false; + } +} + +bool CefV8ValueImpl::SetValue(int index, CefRefPtr value) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + if (index < 0) { + NOTREACHED() << "invalid input parameter"; + return false; + } + + CefV8ValueImpl* impl = static_cast(value.get()); + if (impl && impl->IsValid()) { + v8::HandleScope handle_scope(handle_->isolate()); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + bool set = obj->Set(index, impl->GetV8Value(true)); + return (!HasCaught(try_catch) && set); + } else { + NOTREACHED() << "invalid input parameter"; + return false; + } +} + +bool CefV8ValueImpl::SetValue(const CefString& key, AccessControl settings, + PropertyAttribute attribute) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + CefRefPtr accessorPtr; + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + accessorPtr = tracker->GetAccessor(); + + // Verify that an accessor exists for this object. + if (!accessorPtr.get()) + return false; + + v8::AccessorGetterCallback getter = AccessorGetterCallbackImpl; + v8::AccessorSetterCallback setter = + (attribute & V8_PROPERTY_ATTRIBUTE_READONLY) ? + NULL : AccessorSetterCallbackImpl; + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + bool set = obj->SetAccessor(GetV8String(isolate, key), getter, setter, obj, + static_cast(settings), + static_cast(attribute)); + return (!HasCaught(try_catch) && set); +} + +bool CefV8ValueImpl::GetKeys(std::vector& keys) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + v8::Local arr_keys = obj->GetPropertyNames(); + uint32_t len = arr_keys->Length(); + for (uint32_t i = 0; i < len; ++i) { + v8::Local value = arr_keys->Get(v8::Integer::New(isolate, i)); + CefString str; + GetCefString(value->ToString(), str); + keys.push_back(str); + } + return true; +} + +bool CefV8ValueImpl::SetUserData(CefRefPtr user_data) { + CEF_V8_REQUIRE_OBJECT_RETURN(false); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) { + tracker->SetUserData(user_data); + return true; + } + + return false; +} + +CefRefPtr CefV8ValueImpl::GetUserData() { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + return tracker->GetUserData(); + + return NULL; +} + +int CefV8ValueImpl::GetExternallyAllocatedMemory() { + CEF_V8_REQUIRE_OBJECT_RETURN(0); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + return tracker->GetExternallyAllocatedMemory(); + + return 0; +} + +int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) { + CEF_V8_REQUIRE_OBJECT_RETURN(0); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + v8::Handle obj = value->ToObject(); + + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + return tracker->AdjustExternallyAllocatedMemory(change_in_bytes); + + return 0; +} + +int CefV8ValueImpl::GetArrayLength() { + CEF_V8_REQUIRE_OBJECT_RETURN(0); + + v8::HandleScope handle_scope(handle_->isolate()); + v8::Handle value = handle_->GetNewV8Handle(false); + if (!value->IsArray()) { + NOTREACHED() << "V8 value is not an array"; + return 0; + } + + v8::Handle obj = value->ToObject(); + v8::Local arr = v8::Handle::Cast(obj); + return arr->Length(); +} + +CefString CefV8ValueImpl::GetFunctionName() { + CefString rv; + CEF_V8_REQUIRE_OBJECT_RETURN(rv); + + v8::HandleScope handle_scope(handle_->isolate()); + v8::Handle value = handle_->GetNewV8Handle(false); + if (!value->IsFunction()) { + NOTREACHED() << "V8 value is not a function"; + return rv; + } + + v8::Handle obj = value->ToObject(); + v8::Handle func = v8::Handle::Cast(obj); + GetCefString(v8::Handle::Cast(func->GetName()), rv); + return rv; +} + +CefRefPtr CefV8ValueImpl::GetFunctionHandler() { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + if (!value->IsFunction()) { + NOTREACHED() << "V8 value is not a function"; + return 0; + } + + v8::Handle obj = value->ToObject(); + V8TrackObject* tracker = V8TrackObject::Unwrap(isolate, obj); + if (tracker) + return tracker->GetHandler(); + + return NULL; +} + +CefRefPtr CefV8ValueImpl::ExecuteFunction( + CefRefPtr object, + const CefV8ValueList& arguments) { + // An empty context value defaults to the current context. + CefRefPtr context; + return ExecuteFunctionWithContext(context, object, arguments); +} + +CefRefPtr CefV8ValueImpl::ExecuteFunctionWithContext( + CefRefPtr context, + CefRefPtr object, + const CefV8ValueList& arguments) { + CEF_V8_REQUIRE_OBJECT_RETURN(NULL); + + v8::Isolate* isolate = handle_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle value = handle_->GetNewV8Handle(false); + if (!value->IsFunction()) { + NOTREACHED() << "V8 value is not a function"; + return 0; + } + + if (context.get() && !context->IsValid()) { + NOTREACHED() << "invalid V8 context parameter"; + return NULL; + } + if (object.get() && (!object->IsValid() || !object->IsObject())) { + NOTREACHED() << "invalid V8 object parameter"; + return NULL; + } + + int argc = arguments.size(); + if (argc > 0) { + for (int i = 0; i < argc; ++i) { + if (!arguments[i].get() || !arguments[i]->IsValid()) { + NOTREACHED() << "invalid V8 arguments parameter"; + return NULL; + } + } + } + + v8::Local context_local; + if (context.get()) { + CefV8ContextImpl* context_impl = + static_cast(context.get()); + context_local = context_impl->GetV8Context(); + } else { + context_local = isolate->GetCurrentContext(); + } + + v8::Context::Scope context_scope(context_local); + + v8::Handle obj = value->ToObject(); + v8::Handle func = v8::Handle::Cast(obj); + v8::Handle recv; + + // Default to the global object if no object was provided. + if (object.get()) { + CefV8ValueImpl* recv_impl = static_cast(object.get()); + recv = v8::Handle::Cast(recv_impl->GetV8Value(true)); + } else { + recv = context_local->Global(); + } + + v8::Handle *argv = NULL; + if (argc > 0) { + argv = new v8::Handle[argc]; + for (int i = 0; i < argc; ++i) { + argv[i] = + static_cast(arguments[i].get())->GetV8Value(true); + } + } + + CefRefPtr retval; + + { + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + + v8::Local func_rv = + CallV8Function(context_local, func, recv, argc, argv, + handle_->isolate()); + + if (!HasCaught(try_catch) && !func_rv.IsEmpty()) + retval = new CefV8ValueImpl(isolate, func_rv); + } + + if (argv) + delete [] argv; + + return retval; +} + +bool CefV8ValueImpl::HasCaught(v8::TryCatch& try_catch) { + if (try_catch.HasCaught()) { + last_exception_ = new CefV8ExceptionImpl(try_catch.Message()); + if (rethrow_exceptions_) + try_catch.ReThrow(); + return true; + } else { + if (last_exception_.get()) + last_exception_ = NULL; + return false; + } +} + + +// CefV8StackTrace + +// static +CefRefPtr CefV8StackTrace::GetCurrent(int frame_limit) { + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); + + v8::Isolate* isolate = GetIsolateManager()->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle stackTrace = + v8::StackTrace::CurrentStackTrace( + isolate, frame_limit, v8::StackTrace::kDetailed); + if (stackTrace.IsEmpty()) + return NULL; + return new CefV8StackTraceImpl(isolate, stackTrace); +} + + +// CefV8StackTraceImpl + +CefV8StackTraceImpl::CefV8StackTraceImpl( + v8::Isolate* isolate, + v8::Handle handle) { + int frame_count = handle->GetFrameCount(); + if (frame_count > 0) { + frames_.reserve(frame_count); + for (int i = 0; i < frame_count; ++i) + frames_.push_back(new CefV8StackFrameImpl(isolate, handle->GetFrame(i))); + } +} + +CefV8StackTraceImpl::~CefV8StackTraceImpl() { +} + +bool CefV8StackTraceImpl::IsValid() { + return true; +} + +int CefV8StackTraceImpl::GetFrameCount() { + return frames_.size(); +} + +CefRefPtr CefV8StackTraceImpl::GetFrame(int index) { + if (index < 0 || index >= static_cast(frames_.size())) + return NULL; + return frames_[index]; +} + + +// CefV8StackFrameImpl + +CefV8StackFrameImpl::CefV8StackFrameImpl( + v8::Isolate* isolate, + v8::Handle handle) + : line_number_(0), + column_(0), + is_eval_(false), + is_constructor_(false) { + if (handle.IsEmpty()) + return; + GetCefString(v8::Handle::Cast(handle->GetScriptName()), + script_name_); + GetCefString( + v8::Handle::Cast(handle->GetScriptNameOrSourceURL()), + script_name_or_source_url_); + GetCefString(v8::Handle::Cast(handle->GetFunctionName()), + function_name_); + line_number_ = handle->GetLineNumber(); + column_ = handle->GetColumn(); + is_eval_ = handle->IsEval(); + is_constructor_ = handle->IsConstructor(); +} + +CefV8StackFrameImpl::~CefV8StackFrameImpl() { +} + +bool CefV8StackFrameImpl::IsValid() { + return true; +} + +CefString CefV8StackFrameImpl::GetScriptName() { + return script_name_; +} + +CefString CefV8StackFrameImpl::GetScriptNameOrSourceURL() { + return script_name_or_source_url_; +} + +CefString CefV8StackFrameImpl::GetFunctionName() { + return function_name_; +} + +int CefV8StackFrameImpl::GetLineNumber() { + return line_number_; +} + +int CefV8StackFrameImpl::GetColumn() { + return column_; +} + +bool CefV8StackFrameImpl::IsEval() { + return is_eval_; +} + +bool CefV8StackFrameImpl::IsConstructor() { + return is_constructor_; +} diff --git a/libcef/renderer/v8_impl.h b/libcef/renderer/v8_impl.h new file mode 100644 index 000000000..09935a2db --- /dev/null +++ b/libcef/renderer/v8_impl.h @@ -0,0 +1,391 @@ +// 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_LIBCEF_RENDERER_V8_IMPL_H_ +#define CEF_LIBCEF_RENDERER_V8_IMPL_H_ +#pragma once + +#include + +#include "include/cef_v8.h" +#include "libcef/common/tracker.h" + +#include "v8/include/v8.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" + +class CefTrackNode; +class GURL; + +namespace blink { +class WebFrame; +}; + +// Call after a V8 Isolate has been created and entered for the first time. +void CefV8IsolateCreated(); + +// Call before a V8 Isolate is exited and destroyed. +void CefV8IsolateDestroyed(); + +// Call to detach all handles associated with the specified context. +void CefV8ReleaseContext(v8::Handle context); + +// Set the stack size for uncaught exceptions. +void CefV8SetUncaughtExceptionStackSize(int stack_size); + +// Set attributes associated with a WebWorker thread. +void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url); + +// Used to detach handles when the associated context is released. +class CefV8ContextState : public base::RefCounted { + public: + CefV8ContextState() : valid_(true) {} + virtual ~CefV8ContextState() {} + + bool IsValid() { return valid_; } + void Detach() { + DCHECK(valid_); + valid_ = false; + track_manager_.DeleteAll(); + } + + void AddTrackObject(CefTrackNode* object) { + DCHECK(valid_); + track_manager_.Add(object); + } + + void DeleteTrackObject(CefTrackNode* object) { + DCHECK(valid_); + track_manager_.Delete(object); + } + + private: + bool valid_; + CefTrackManager track_manager_; +}; + + +// Use this template in conjuction with RefCountedThreadSafe to ensure that a +// V8 object is deleted on the correct thread. +struct CefV8DeleteOnMessageLoopThread { + template + static void Destruct(const T* x) { + if (x->task_runner()->RunsTasksOnCurrentThread()) { + delete x; + } else { + if (!x->task_runner()->DeleteSoon(FROM_HERE, x)) { +#if defined(UNIT_TEST) + // Only logged under unit testing because leaks at shutdown + // are acceptable under normal circumstances. + LOG(ERROR) << "DeleteSoon failed on thread " << thread; +#endif // UNIT_TEST + } + } + } +}; + +// Base class for V8 Handle types. +class CefV8HandleBase : + public base::RefCountedThreadSafe { + public: + virtual ~CefV8HandleBase(); + + // Returns true if there is no underlying context or if the underlying context + // is valid. + bool IsValid() const { + return (!context_state_.get() || context_state_->IsValid()); + } + + bool BelongsToCurrentThread() const; + + v8::Isolate* isolate() const { return isolate_; } + scoped_refptr task_runner() const { + return task_runner_; + } + + protected: + // |context| is the context that owns this handle. If empty the current + // context will be used. + CefV8HandleBase(v8::Isolate* isolate, + v8::Handle context); + + protected: + v8::Isolate* isolate_; + scoped_refptr task_runner_; + scoped_refptr context_state_; +}; + +// Template for V8 Handle types. This class is used to ensure that V8 objects +// are only released on the render thread. +template +class CefV8Handle : public CefV8HandleBase { + public: + typedef v8::Local handleType; + typedef v8::Persistent persistentType; + + CefV8Handle(v8::Isolate* isolate, + v8::Handle context, + handleType v) + : CefV8HandleBase(isolate, context), + handle_(isolate, v) { + } + virtual ~CefV8Handle() { + handle_.Reset(); + } + + handleType GetNewV8Handle() { + DCHECK(IsValid()); + return handleType::New(isolate(), handle_); + } + + persistentType& GetPersistentV8Handle() { + return handle_; + } + + protected: + persistentType handle_; + + DISALLOW_COPY_AND_ASSIGN(CefV8Handle); +}; + +// Specialization for v8::Value with empty implementation to avoid incorrect +// usage. +template <> +class CefV8Handle { +}; + + +class CefV8ContextImpl : public CefV8Context { + public: + CefV8ContextImpl(v8::Isolate* isolate, + v8::Handle context); + virtual ~CefV8ContextImpl(); + + virtual CefRefPtr GetTaskRunner() OVERRIDE; + virtual bool IsValid() OVERRIDE; + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual CefRefPtr GetFrame() OVERRIDE; + virtual CefRefPtr GetGlobal() OVERRIDE; + virtual bool Enter() OVERRIDE; + virtual bool Exit() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool Eval(const CefString& code, + CefRefPtr& retval, + CefRefPtr& exception) OVERRIDE; + + v8::Handle GetV8Context(); + blink::WebFrame* GetWebFrame(); + + protected: + typedef CefV8Handle Handle; + scoped_refptr handle_; + +#ifndef NDEBUG + // Used in debug builds to catch missing Exits in destructor. + int enter_count_; +#endif + + IMPLEMENT_REFCOUNTING(CefV8ContextImpl); + DISALLOW_COPY_AND_ASSIGN(CefV8ContextImpl); +}; + +class CefV8ValueImpl : public CefV8Value { + public: + explicit CefV8ValueImpl(v8::Isolate* isolate); + CefV8ValueImpl(v8::Isolate* isolate, + v8::Handle value); + virtual ~CefV8ValueImpl(); + + // Used for initializing the CefV8ValueImpl. Should be called a single time + // after the CefV8ValueImpl is created. + void InitFromV8Value(v8::Handle value); + void InitUndefined(); + void InitNull(); + void InitBool(bool value); + void InitInt(int32 value); + void InitUInt(uint32 value); + void InitDouble(double value); + void InitDate(const CefTime& value); + void InitString(CefString& value); + void InitObject(v8::Handle value, CefTrackNode* tracker); + + // Creates a new V8 value for the underlying value or returns the existing + // object handle. + v8::Handle GetV8Value(bool should_persist); + + virtual bool IsValid() OVERRIDE; + virtual bool IsUndefined() OVERRIDE; + virtual bool IsNull() OVERRIDE; + virtual bool IsBool() OVERRIDE; + virtual bool IsInt() OVERRIDE; + virtual bool IsUInt() OVERRIDE; + virtual bool IsDouble() OVERRIDE; + virtual bool IsDate() OVERRIDE; + virtual bool IsString() OVERRIDE; + virtual bool IsObject() OVERRIDE; + virtual bool IsArray() OVERRIDE; + virtual bool IsFunction() OVERRIDE; + virtual bool IsSame(CefRefPtr value) OVERRIDE; + virtual bool GetBoolValue() OVERRIDE; + virtual int32 GetIntValue() OVERRIDE; + virtual uint32 GetUIntValue() OVERRIDE; + virtual double GetDoubleValue() OVERRIDE; + virtual CefTime GetDateValue() OVERRIDE; + virtual CefString GetStringValue() OVERRIDE; + virtual bool IsUserCreated() OVERRIDE; + virtual bool HasException() OVERRIDE; + virtual CefRefPtr GetException() OVERRIDE; + virtual bool ClearException() OVERRIDE; + virtual bool WillRethrowExceptions() OVERRIDE; + virtual bool SetRethrowExceptions(bool rethrow) OVERRIDE; + virtual bool HasValue(const CefString& key) OVERRIDE; + virtual bool HasValue(int index) OVERRIDE; + virtual bool DeleteValue(const CefString& key) OVERRIDE; + virtual bool DeleteValue(int index) OVERRIDE; + virtual CefRefPtr GetValue(const CefString& key) OVERRIDE; + virtual CefRefPtr GetValue(int index) OVERRIDE; + virtual bool SetValue(const CefString& key, CefRefPtr value, + PropertyAttribute attribute) OVERRIDE; + virtual bool SetValue(int index, CefRefPtr value) OVERRIDE; + virtual bool SetValue(const CefString& key, AccessControl settings, + PropertyAttribute attribute) OVERRIDE; + virtual bool GetKeys(std::vector& keys) OVERRIDE; + virtual bool SetUserData(CefRefPtr user_data) OVERRIDE; + virtual CefRefPtr GetUserData() OVERRIDE; + virtual int GetExternallyAllocatedMemory() OVERRIDE; + virtual int AdjustExternallyAllocatedMemory(int change_in_bytes) OVERRIDE; + virtual int GetArrayLength() OVERRIDE; + virtual CefString GetFunctionName() OVERRIDE; + virtual CefRefPtr GetFunctionHandler() OVERRIDE; + virtual CefRefPtr ExecuteFunction( + CefRefPtr object, + const CefV8ValueList& arguments) OVERRIDE; + virtual CefRefPtr ExecuteFunctionWithContext( + CefRefPtr context, + CefRefPtr object, + const CefV8ValueList& arguments) OVERRIDE; + + protected: + // Test for and record any exception. + bool HasCaught(v8::TryCatch& try_catch); + + class Handle : public CefV8HandleBase { + public: + typedef v8::Local handleType; + typedef v8::Persistent persistentType; + + Handle(v8::Isolate* isolate, + v8::Handle context, + handleType v, + CefTrackNode* tracker); + virtual ~Handle(); + + handleType GetNewV8Handle(bool should_persist); + + persistentType& GetPersistentV8Handle(); + + void SetWeakIfNecessary(); + + private: + // Callback for weak persistent reference destruction. + static void Destructor(const v8::WeakCallbackData& data); + + persistentType handle_; + + // For Object and Function types, we need to hold on to a reference to their + // internal data or function handler objects that are reference counted. + CefTrackNode* tracker_; + + // True if the handle needs to persist due to it being passed into V8. + bool should_persist_; + + // True if the handle has been set as weak. + bool is_set_weak_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + + v8::Isolate* isolate_; + + enum { + TYPE_INVALID = 0, + TYPE_UNDEFINED, + TYPE_NULL, + TYPE_BOOL, + TYPE_INT, + TYPE_UINT, + TYPE_DOUBLE, + TYPE_DATE, + TYPE_STRING, + TYPE_OBJECT, + } type_; + + union { + bool bool_value_; + int32 int_value_; + uint32 uint_value_; + double double_value_; + cef_time_t date_value_; + cef_string_t string_value_; + }; + + // Used with Object, Function and Array types. + scoped_refptr handle_; + + CefRefPtr last_exception_; + bool rethrow_exceptions_; + + IMPLEMENT_REFCOUNTING(CefV8ValueImpl); + DISALLOW_COPY_AND_ASSIGN(CefV8ValueImpl); +}; + +class CefV8StackTraceImpl : public CefV8StackTrace { + public: + CefV8StackTraceImpl(v8::Isolate* isolate, + v8::Handle handle); + virtual ~CefV8StackTraceImpl(); + + virtual bool IsValid() OVERRIDE; + virtual int GetFrameCount() OVERRIDE; + virtual CefRefPtr GetFrame(int index) OVERRIDE; + + protected: + std::vector > frames_; + + IMPLEMENT_REFCOUNTING(CefV8StackTraceImpl); + DISALLOW_COPY_AND_ASSIGN(CefV8StackTraceImpl); +}; + +class CefV8StackFrameImpl : public CefV8StackFrame { + public: + CefV8StackFrameImpl(v8::Isolate* isolate, + v8::Handle handle); + virtual ~CefV8StackFrameImpl(); + + virtual bool IsValid() OVERRIDE; + virtual CefString GetScriptName() OVERRIDE; + virtual CefString GetScriptNameOrSourceURL() OVERRIDE; + virtual CefString GetFunctionName() OVERRIDE; + virtual int GetLineNumber() OVERRIDE; + virtual int GetColumn() OVERRIDE; + virtual bool IsEval() OVERRIDE; + virtual bool IsConstructor() OVERRIDE; + + protected: + CefString script_name_; + CefString script_name_or_source_url_; + CefString function_name_; + int line_number_; + int column_; + bool is_eval_; + bool is_constructor_; + + IMPLEMENT_REFCOUNTING(CefV8StackFrameImpl); + DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl); +}; + +#endif // CEF_LIBCEF_RENDERER_V8_IMPL_H_ diff --git a/libcef/renderer/webkit_glue.cc b/libcef/renderer/webkit_glue.cc new file mode 100644 index 000000000..d24eecd75 --- /dev/null +++ b/libcef/renderer/webkit_glue.cc @@ -0,0 +1,97 @@ +// Copyright (c) 2012 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. + +// MSVC++ requires this to be set before any other includes to get M_PI. +// Otherwise there will be compile errors in wtf/MathExtras.h. +#define _USE_MATH_DEFINES + +// Defines required to access Blink internals (unwrap WebNode). +#undef BLINK_IMPLEMENTATION +#define BLINK_IMPLEMENTATION 1 +#undef INSIDE_BLINK +#define INSIDE_BLINK 1 + +#include "libcef/renderer/webkit_glue.h" + +#include "base/compiler_specific.h" + +#include "config.h" +MSVC_PUSH_WARNING_LEVEL(0); +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/web/WebDocument.h" +#include "third_party/WebKit/public/web/WebElement.h" +#include "third_party/WebKit/public/web/WebNode.h" +#include "third_party/WebKit/public/web/WebViewClient.h" + +#include "third_party/WebKit/Source/core/dom/Node.h" +#include "third_party/WebKit/Source/web/WebViewImpl.h" +MSVC_POP_WARNING(); +#undef LOG + +#include "base/logging.h" +#include "content/public/renderer/render_frame.h" + +namespace webkit_glue { + +const int64 kInvalidFrameId = -1; + +bool CanGoBack(blink::WebView* view) { + if (!view) + return false; + blink::WebViewImpl* impl = reinterpret_cast(view); + return (impl->client()->historyBackListCount() > 0); +} + +bool CanGoForward(blink::WebView* view) { + if (!view) + return false; + blink::WebViewImpl* impl = reinterpret_cast(view); + return (impl->client()->historyForwardListCount() > 0); +} + +void GoBack(blink::WebView* view) { + if (!view) + return; + blink::WebViewImpl* impl = reinterpret_cast(view); + if (impl->client()->historyBackListCount() > 0) + impl->client()->navigateBackForwardSoon(-1); +} + +void GoForward(blink::WebView* view) { + if (!view) + return; + blink::WebViewImpl* impl = reinterpret_cast(view); + if (impl->client()->historyForwardListCount() > 0) + impl->client()->navigateBackForwardSoon(1); +} + +std::string DumpDocumentText(blink::WebFrame* frame) { + // We use the document element's text instead of the body text here because + // not all documents have a body, such as XML documents. + blink::WebElement document_element = frame->document().documentElement(); + if (document_element.isNull()) + return std::string(); + + return document_element.innerText().utf8(); +} + +bool SetNodeValue(blink::WebNode& node, const blink::WebString& value) { + WebCore::Node* web_node = node.unwrap(); + web_node->setNodeValue(value); + return true; +} + +int64 GetIdentifier(blink::WebFrame* frame) { + // Each WebFrame will have an associated RenderFrame. The RenderFrame + // routing IDs are unique within a given renderer process. + content::RenderFrame* render_frame = + content::RenderFrame::FromWebFrame(frame); + DCHECK(render_frame); + if (render_frame) + return render_frame->GetRoutingID(); + return kInvalidFrameId; +} + +} // webkit_glue diff --git a/libcef/renderer/webkit_glue.h b/libcef/renderer/webkit_glue.h new file mode 100644 index 000000000..479d81099 --- /dev/null +++ b/libcef/renderer/webkit_glue.h @@ -0,0 +1,43 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_RENDERER_WEBKIT_GLUE_H_ +#define CEF_LIBCEF_RENDERER_WEBKIT_GLUE_H_ + +#include +#include "base/basictypes.h" + +namespace v8 { +class Context; +template class Handle; +class Isolate; +} + +namespace blink { +class WebFrame; +class WebNode; +class WebString; +class WebView; +} + +namespace webkit_glue { + +extern const int64 kInvalidFrameId; + +bool CanGoBack(blink::WebView* view); +bool CanGoForward(blink::WebView* view); +void GoBack(blink::WebView* view); +void GoForward(blink::WebView* view); + +// Returns the text of the document element. +std::string DumpDocumentText(blink::WebFrame* frame); + +bool SetNodeValue(blink::WebNode& node, const blink::WebString& value); + +int64 GetIdentifier(blink::WebFrame* frame); + +} // webkit_glue + +#endif // CEF_LIBCEF_RENDERER_WEBKIT_GLUE_H_ diff --git a/libcef/resources/about_version.html b/libcef/resources/about_version.html new file mode 100644 index 000000000..873957512 --- /dev/null +++ b/libcef/resources/about_version.html @@ -0,0 +1,123 @@ + + + + + + + About Version + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CEF$$CEF$$
Chromium$$CHROMIUM$$
OS$$OS$$
WebKit$$WEBKIT$$
JavaScript$$JAVASCRIPT$$
Flash$$FLASH$$
User Agent$$USERAGENT$$
Command Line$$COMMANDLINE$$
Module Path$$MODULEPATH$$
Cache Path$$CACHEPATH$$
+
+ + + + diff --git a/libcef/resources/cef_resources.grd b/libcef/resources/cef_resources.grd new file mode 100644 index 000000000..63dc921f6 --- /dev/null +++ b/libcef/resources/cef_resources.grd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/libcef/resources/cef_strings.grd b/libcef/resources/cef_strings.grd new file mode 100644 index 000000000..e72d539ce --- /dev/null +++ b/libcef/resources/cef_strings.grd @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &Back + + + &Forward + + + Re&load + + + Reload no cache + + + &Stop + + + &Undo + + + &Redo + + + Cu&t + + + &Copy + + + &Paste + + + &Delete + + + Select &all + + + &Find... + + + &Print... + + + View s&ource + + + Audio Files + + + Image Files + + + Text Files + + + Video Files + + + + + Untitled Document + + + Print Failed + + + Something went wrong when trying to print. Please check your printer and try again. + + + The selected printer is not available or not installed correctly. Check your printer or try selecting another printer. + + + + diff --git a/libcef/resources/devtools_discovery_page.html b/libcef/resources/devtools_discovery_page.html new file mode 100644 index 000000000..87933d1af --- /dev/null +++ b/libcef/resources/devtools_discovery_page.html @@ -0,0 +1,54 @@ + + +CEF remote debugging + + + + + +
Inspectable WebContents
+
+ + diff --git a/libcef/resources/framework-Info.plist b/libcef/resources/framework-Info.plist new file mode 100644 index 000000000..21f1d2058 --- /dev/null +++ b/libcef/resources/framework-Info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.chromium.ContentShell.framework + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + + diff --git a/libcef/resources/grit_stub/grit/browser_resources.h b/libcef/resources/grit_stub/grit/browser_resources.h new file mode 100644 index 000000000..0d2c14a96 --- /dev/null +++ b/libcef/resources/grit_stub/grit/browser_resources.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/libcef/resources/grit_stub/grit/generated_resources.h b/libcef/resources/grit_stub/grit/generated_resources.h new file mode 100644 index 000000000..0d2c14a96 --- /dev/null +++ b/libcef/resources/grit_stub/grit/generated_resources.h @@ -0,0 +1,2 @@ +#include +#include diff --git a/libcef/resources/print_preview_page_stub.html b/libcef/resources/print_preview_page_stub.html new file mode 100644 index 000000000..18ecdcb79 --- /dev/null +++ b/libcef/resources/print_preview_page_stub.html @@ -0,0 +1 @@ + diff --git a/libcef/utility/content_utility_client.cc b/libcef/utility/content_utility_client.cc new file mode 100644 index 000000000..0cf615ccf --- /dev/null +++ b/libcef/utility/content_utility_client.cc @@ -0,0 +1,60 @@ +// 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 "libcef/utility/content_utility_client.h" + +#include "chrome/common/chrome_utility_messages.h" +#include "chrome/utility/utility_message_handler.h" +#include "content/public/utility/utility_thread.h" + +#if defined(ENABLE_FULL_PRINTING) && defined(WIN_PDF_METAFILE_FOR_PRINTING) +#include "libcef/utility/printing_handler.h" +#endif + +namespace { + +bool Send(IPC::Message* message) { + return content::UtilityThread::Get()->Send(message); +} + +} // namespace + +CefContentUtilityClient::CefContentUtilityClient() { +#if defined(ENABLE_FULL_PRINTING) && defined(WIN_PDF_METAFILE_FOR_PRINTING) + handlers_.push_back(new PrintingHandler()); +#endif +} + +CefContentUtilityClient::~CefContentUtilityClient() { +} + +bool CefContentUtilityClient::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + + IPC_BEGIN_MESSAGE_MAP(CefContentUtilityClient, message) + IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + for (Handlers::iterator it = handlers_.begin(); + !handled && it != handlers_.end(); ++it) { + handled = (*it)->OnMessageReceived(message); + } + + return handled; +} + +// static +void CefContentUtilityClient::PreSandboxStartup() { +#if defined(ENABLE_FULL_PRINTING) && defined(WIN_PDF_METAFILE_FOR_PRINTING) + PrintingHandler::PreSandboxStartup(); +#endif +} + +void CefContentUtilityClient::OnStartupPing() { + Send(new ChromeUtilityHostMsg_ProcessStarted); + // Don't release the process, we assume further messages are on the way. +} diff --git a/libcef/utility/content_utility_client.h b/libcef/utility/content_utility_client.h new file mode 100644 index 000000000..aed828481 --- /dev/null +++ b/libcef/utility/content_utility_client.h @@ -0,0 +1,33 @@ +// 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 LIBCEF_UTILITY_CONTENT_UTILITY_CLIENT_H_ +#define LIBCEF_UTILITY_CONTENT_UTILITY_CLIENT_H_ + +#include "base/memory/scoped_vector.h" +#include "content/public/utility/content_utility_client.h" + +class UtilityMessageHandler; + +class CefContentUtilityClient : public content::ContentUtilityClient { + public: + CefContentUtilityClient(); + virtual ~CefContentUtilityClient(); + + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + static void PreSandboxStartup(); + + private: + // IPC message handlers. + void OnStartupPing(); + + typedef ScopedVector Handlers; + Handlers handlers_; + + DISALLOW_COPY_AND_ASSIGN(CefContentUtilityClient); +}; + +#endif // LIBCEF_UTILITY_CONTENT_UTILITY_CLIENT_H_ diff --git a/libcef/utility/printing_handler.cc b/libcef/utility/printing_handler.cc new file mode 100644 index 000000000..6d53e9769 --- /dev/null +++ b/libcef/utility/printing_handler.cc @@ -0,0 +1,418 @@ +// Copyright 2014 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 "libcef/utility/printing_handler.h" + +#include "base/file_util.h" +#include "base/lazy_instance.h" +#include "base/path_service.h" +#include "base/scoped_native_library.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_utility_printing_messages.h" +#include "content/public/utility/utility_thread.h" +#include "printing/page_range.h" +#include "printing/pdf_render_settings.h" + +#if defined(OS_WIN) +#include "base/win/iat_patch_function.h" +#include "printing/emf_win.h" +#include "ui/gfx/gdi_util.h" +#endif + +#if defined(ENABLE_FULL_PRINTING) +#include "printing/backend/print_backend.h" +#endif + +namespace { + +bool Send(IPC::Message* message) { + return content::UtilityThread::Get()->Send(message); +} + +void ReleaseProcessIfNeeded() { + content::UtilityThread::Get()->ReleaseProcessIfNeeded(); +} + +class PdfFunctionsBase { + public: + PdfFunctionsBase() : render_pdf_to_bitmap_func_(NULL), + get_pdf_doc_info_func_(NULL) {} + + bool Init() { + base::FilePath pdf_module_path; + if (!PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_module_path) || + !base::PathExists(pdf_module_path)) { + return false; + } + + pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL)); + if (!pdf_lib_.is_valid()) { + LOG(WARNING) << "Couldn't load PDF plugin"; + return false; + } + + render_pdf_to_bitmap_func_ = + reinterpret_cast( + pdf_lib_.GetFunctionPointer("RenderPDFPageToBitmap")); + LOG_IF(WARNING, !render_pdf_to_bitmap_func_) << + "Missing RenderPDFPageToBitmap"; + + get_pdf_doc_info_func_ = + reinterpret_cast( + pdf_lib_.GetFunctionPointer("GetPDFDocInfo")); + LOG_IF(WARNING, !get_pdf_doc_info_func_) << "Missing GetPDFDocInfo"; + + if (!render_pdf_to_bitmap_func_ || !get_pdf_doc_info_func_ || + !PlatformInit(pdf_module_path, pdf_lib_)) { + Reset(); + } + + return IsValid(); + } + + bool IsValid() const { + return pdf_lib_.is_valid(); + } + + void Reset() { + pdf_lib_.Reset(NULL); + } + + bool RenderPDFPageToBitmap(const void* pdf_buffer, + int pdf_buffer_size, + int page_number, + void* bitmap_buffer, + int bitmap_width, + int bitmap_height, + int dpi_x, + int dpi_y, + bool autorotate) { + if (!render_pdf_to_bitmap_func_) + return false; + return render_pdf_to_bitmap_func_(pdf_buffer, pdf_buffer_size, page_number, + bitmap_buffer, bitmap_width, + bitmap_height, dpi_x, dpi_y, autorotate); + } + + bool GetPDFDocInfo(const void* pdf_buffer, + int buffer_size, + int* page_count, + double* max_page_width) { + if (!get_pdf_doc_info_func_) + return false; + return get_pdf_doc_info_func_(pdf_buffer, buffer_size, page_count, + max_page_width); + } + + protected: + virtual bool PlatformInit( + const base::FilePath& pdf_module_path, + const base::ScopedNativeLibrary& pdf_lib) { + return true; + } + + private: + // Exported by PDF plugin. + typedef bool (*RenderPDFPageToBitmapProc)(const void* pdf_buffer, + int pdf_buffer_size, + int page_number, + void* bitmap_buffer, + int bitmap_width, + int bitmap_height, + int dpi_x, + int dpi_y, + bool autorotate); + typedef bool (*GetPDFDocInfoProc)(const void* pdf_buffer, + int buffer_size, int* page_count, + double* max_page_width); + + RenderPDFPageToBitmapProc render_pdf_to_bitmap_func_; + GetPDFDocInfoProc get_pdf_doc_info_func_; + + base::ScopedNativeLibrary pdf_lib_; + DISALLOW_COPY_AND_ASSIGN(PdfFunctionsBase); +}; + +#if defined(OS_WIN) +// The 2 below IAT patch functions are almost identical to the code in +// render_process_impl.cc. This is needed to work around specific Windows APIs +// used by the Chrome PDF plugin that will fail in the sandbox. +static base::win::IATPatchFunction g_iat_patch_createdca; +HDC WINAPI UtilityProcess_CreateDCAPatch(LPCSTR driver_name, + LPCSTR device_name, + LPCSTR output, + const DEVMODEA* init_data) { + if (driver_name && (std::string("DISPLAY") == driver_name)) { + // CreateDC fails behind the sandbox, but not CreateCompatibleDC. + return CreateCompatibleDC(NULL); + } + + NOTREACHED(); + return CreateDCA(driver_name, device_name, output, init_data); +} + +static base::win::IATPatchFunction g_iat_patch_get_font_data; +DWORD WINAPI UtilityProcess_GetFontDataPatch( + HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) { + int rv = GetFontData(hdc, table, offset, buffer, length); + if (rv == GDI_ERROR && hdc) { + HFONT font = static_cast(GetCurrentObject(hdc, OBJ_FONT)); + + LOGFONT logfont; + if (GetObject(font, sizeof(LOGFONT), &logfont)) { + content::UtilityThread::Get()->PreCacheFont(logfont); + rv = GetFontData(hdc, table, offset, buffer, length); + content::UtilityThread::Get()->ReleaseCachedFonts(); + } + } + return rv; +} + +class PdfFunctionsWin : public PdfFunctionsBase { + public: + PdfFunctionsWin() : render_pdf_to_dc_func_(NULL) { + } + + bool PlatformInit( + const base::FilePath& pdf_module_path, + const base::ScopedNativeLibrary& pdf_lib) OVERRIDE { + // Patch the IAT for handling specific APIs known to fail in the sandbox. + if (!g_iat_patch_createdca.is_patched()) { + g_iat_patch_createdca.Patch(pdf_module_path.value().c_str(), + "gdi32.dll", "CreateDCA", + UtilityProcess_CreateDCAPatch); + } + + if (!g_iat_patch_get_font_data.is_patched()) { + g_iat_patch_get_font_data.Patch(pdf_module_path.value().c_str(), + "gdi32.dll", "GetFontData", + UtilityProcess_GetFontDataPatch); + } + render_pdf_to_dc_func_ = + reinterpret_cast( + pdf_lib.GetFunctionPointer("RenderPDFPageToDC")); + LOG_IF(WARNING, !render_pdf_to_dc_func_) << "Missing RenderPDFPageToDC"; + + return render_pdf_to_dc_func_ != NULL; + } + + bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, + int page_number, + HDC dc, + int dpi_x, + int dpi_y, + int bounds_origin_x, + int bounds_origin_y, + int bounds_width, + int bounds_height, + bool fit_to_bounds, + bool stretch_to_bounds, + bool keep_aspect_ratio, + bool center_in_bounds, + bool autorotate) { + if (!render_pdf_to_dc_func_) + return false; + return render_pdf_to_dc_func_(pdf_buffer, buffer_size, page_number, + dc, dpi_x, dpi_y, bounds_origin_x, + bounds_origin_y, bounds_width, bounds_height, + fit_to_bounds, stretch_to_bounds, + keep_aspect_ratio, center_in_bounds, + autorotate); + } + + private: + // Exported by PDF plugin. + typedef bool (*RenderPDFPageToDCProc)( + const void* pdf_buffer, int buffer_size, int page_number, HDC dc, + int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y, + int bounds_width, int bounds_height, bool fit_to_bounds, + bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds, + bool autorotate); + RenderPDFPageToDCProc render_pdf_to_dc_func_; + + DISALLOW_COPY_AND_ASSIGN(PdfFunctionsWin); +}; + +typedef PdfFunctionsWin PdfFunctions; +#else // OS_WIN +typedef PdfFunctionsBase PdfFunctions; +#endif // OS_WIN + +base::LazyInstance g_pdf_lib = LAZY_INSTANCE_INITIALIZER; + +} // namespace + +PrintingHandler::PrintingHandler() {} + +PrintingHandler::~PrintingHandler() {} + +// static +void PrintingHandler::PreSandboxStartup() { + g_pdf_lib.Get().Init(); +} + +bool PrintingHandler::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message) +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) + IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles, + OnRenderPDFPagesToMetafile) +#endif + IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults, + OnGetPrinterCapsAndDefaults) + IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults, + OnGetPrinterSemanticCapsAndDefaults) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) +void PrintingHandler::OnRenderPDFPagesToMetafile( + IPC::PlatformFileForTransit pdf_transit, + const base::FilePath& metafile_path, + const printing::PdfRenderSettings& settings, + const std::vector& page_ranges_const) { + bool succeeded = false; + base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit); + int highest_rendered_page_number = 0; + double scale_factor = 1.0; + std::vector page_ranges = page_ranges_const; + succeeded = RenderPDFToWinMetafile(pdf_file.Pass(), + metafile_path, + settings, + &page_ranges, + &highest_rendered_page_number, + &scale_factor); + if (succeeded) { + // TODO(vitalybuka|scottmg): http://crbug.com/170859. These could + // potentially be sent as each page is converted so that the spool could + // start sooner. + Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_Succeeded( + page_ranges, scale_factor)); + } else { + Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafile_Failed()); + } + ReleaseProcessIfNeeded(); +} +#endif + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) +bool PrintingHandler::RenderPDFToWinMetafile( + base::File pdf_file, + const base::FilePath& metafile_path, + const printing::PdfRenderSettings& settings, + std::vector* page_ranges, + int* highest_rendered_page_number, + double* scale_factor) { + DCHECK(page_ranges); + *highest_rendered_page_number = -1; + *scale_factor = 1.0; + + if (!g_pdf_lib.Get().IsValid()) + return false; + + // TODO(sanjeevr): Add a method to the PDF DLL that takes in a file handle + // and a page range array. That way we don't need to read the entire PDF into + // memory. + int64 length = pdf_file.GetLength(); + if (length < 0) + return false; + + std::vector buffer; + buffer.resize(length); + if (length != pdf_file.Read(0, &buffer.front(), length)) + return false; + + int total_page_count = 0; + if (!g_pdf_lib.Get().GetPDFDocInfo(&buffer.front(), buffer.size(), + &total_page_count, NULL)) { + return false; + } + + // If no range supplied, do all pages. + if (page_ranges->empty()) { + printing::PageRange page_range_all; + page_range_all.from = 0; + page_range_all.to = total_page_count - 1; + page_ranges->push_back(page_range_all); + } + + bool ret = false; + std::vector::const_iterator iter; + for (iter = page_ranges->begin(); iter != page_ranges->end(); ++iter) { + for (int page_number = iter->from; page_number <= iter->to; ++page_number) { + if (page_number >= total_page_count) + break; + + printing::Emf metafile; + metafile.InitToFile(metafile_path.InsertBeforeExtensionASCII( + base::StringPrintf(".%d", page_number))); + + // We need to scale down DC to fit an entire page into DC available area. + // Current metafile is based on screen DC and have current screen size. + // Writing outside of those boundaries will result in the cut-off output. + // On metafiles (this is the case here), scaling down will still record + // original coordinates and we'll be able to print in full resolution. + // Before playback we'll need to counter the scaling up that will happen + // in the service (print_system_win.cc). + *scale_factor = gfx::CalculatePageScale(metafile.context(), + settings.area().right(), + settings.area().bottom()); + gfx::ScaleDC(metafile.context(), *scale_factor); + + // The underlying metafile is of type Emf and ignores the arguments passed + // to StartPage. + metafile.StartPage(gfx::Size(), gfx::Rect(), 1); + if (g_pdf_lib.Get().RenderPDFPageToDC( + &buffer.front(), buffer.size(), page_number, metafile.context(), + settings.dpi(), settings.dpi(), settings.area().x(), + settings.area().y(), settings.area().width(), + settings.area().height(), true, false, true, true, + settings.autorotate())) { + if (*highest_rendered_page_number < page_number) + *highest_rendered_page_number = page_number; + ret = true; + } + metafile.FinishPage(); + metafile.FinishDocument(); + } + } + return ret; +} +#endif // defined(WIN_PDF_METAFILE_FOR_PRINTING) + +void PrintingHandler::OnGetPrinterCapsAndDefaults( + const std::string& printer_name) { + scoped_refptr print_backend = + printing::PrintBackend::CreateInstance(NULL); + printing::PrinterCapsAndDefaults printer_info; + + if (print_backend->GetPrinterCapsAndDefaults(printer_name, &printer_info)) { + Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded( + printer_name, printer_info)); + } else { + Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed( + printer_name)); + } + ReleaseProcessIfNeeded(); +} + +void PrintingHandler::OnGetPrinterSemanticCapsAndDefaults( + const std::string& printer_name) { + scoped_refptr print_backend = + printing::PrintBackend::CreateInstance(NULL); + printing::PrinterSemanticCapsAndDefaults printer_info; + + if (print_backend->GetPrinterSemanticCapsAndDefaults(printer_name, + &printer_info)) { + Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded( + printer_name, printer_info)); + } else { + Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed( + printer_name)); + } + ReleaseProcessIfNeeded(); +} diff --git a/libcef/utility/printing_handler.h b/libcef/utility/printing_handler.h new file mode 100644 index 000000000..c8bd2f9ba --- /dev/null +++ b/libcef/utility/printing_handler.h @@ -0,0 +1,64 @@ +// Copyright 2014 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 LIBCEF_UTILITY_PRINTING_HANDLER_H_ +#define LIBCEF_UTILITY_PRINTING_HANDLER_H_ + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "chrome/utility/utility_message_handler.h" +#include "ipc/ipc_platform_file.h" + +#if !defined(ENABLE_FULL_PRINTING) +#error "Full printing must be enabled" +#endif + +namespace printing { +class PdfRenderSettings; +struct PageRange; +} + +// Dispatches IPCs for printing. +class PrintingHandler : public UtilityMessageHandler { + public: + PrintingHandler(); + virtual ~PrintingHandler(); + + static void PreSandboxStartup(); + + // IPC::Listener: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + private: + // IPC message handlers. +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) + void OnRenderPDFPagesToMetafile( + IPC::PlatformFileForTransit pdf_transit, + const base::FilePath& metafile_path, + const printing::PdfRenderSettings& settings, + const std::vector& page_ranges); +#endif + +#if defined(WIN_PDF_METAFILE_FOR_PRINTING) + // Helper method for Windows. + // |highest_rendered_page_number| is set to -1 on failure to render any page. + // |page_ranges| is both input and output. If supplied as input, only the + // specified pages will be rendered. If an empty vector is supplied it will + // be filled with a range of all pages that were rendered. + bool RenderPDFToWinMetafile( + base::File pdf_file, + const base::FilePath& metafile_path, + const printing::PdfRenderSettings& settings, + std::vector* page_ranges, + int* highest_rendered_page_number, + double* scale_factor); +#endif + + void OnGetPrinterCapsAndDefaults(const std::string& printer_name); + void OnGetPrinterSemanticCapsAndDefaults(const std::string& printer_name); + + DISALLOW_COPY_AND_ASSIGN(PrintingHandler); +}; + +#endif // LIBCEF_UTILITY_PRINTING_HANDLER_H_ diff --git a/libcef_dll/base/cef_atomicops_x86_gcc.cc b/libcef_dll/base/cef_atomicops_x86_gcc.cc new file mode 100644 index 000000000..4471eedaf --- /dev/null +++ b/libcef_dll/base/cef_atomicops_x86_gcc.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2006-2008 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. + +// This module gets enough CPU information to optimize the +// atomicops module on x86. + +#include +#include + +#include "include/base/cef_atomicops.h" + +// This file only makes sense with atomicops_internals_x86_gcc.h -- it +// depends on structs that are defined in that file. If atomicops.h +// doesn't sub-include that file, then we aren't needed, and shouldn't +// try to do anything. +#ifdef CEF_INCLUDE_BASE_INTERNAL_CEF_ATOMICOPS_X86_GCC_H_ + +// Inline cpuid instruction. In PIC compilations, %ebx contains the address +// of the global offset table. To avoid breaking such executables, this code +// must preserve that register's value across cpuid instructions. +#if defined(__i386__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%ebx, %%edi\n" \ + "cpuid\n" \ + "xchg %%edi, %%ebx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#elif defined(__x86_64__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%rbx, %%rdi\n" \ + "cpuid\n" \ + "xchg %%rdi, %%rbx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#endif + +#if defined(cpuid) // initialize the struct only on x86 + +// Set the flags so that code will run correctly and conservatively, so even +// if we haven't been initialized yet, we're probably single threaded, and our +// default values should hopefully be pretty safe. +struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { + false, // bug can't exist before process spawns multiple threads +}; + +namespace { + +// Initialize the AtomicOps_Internalx86CPUFeatures struct. +void AtomicOps_Internalx86CPUFeaturesInit() { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + + // Get vendor string (issue CPUID with eax = 0) + cpuid(eax, ebx, ecx, edx, 0); + char vendor[13]; + memcpy(vendor, &ebx, 4); + memcpy(vendor + 4, &edx, 4); + memcpy(vendor + 8, &ecx, 4); + vendor[12] = 0; + + // get feature flags in ecx/edx, and family/model in eax + cpuid(eax, ebx, ecx, edx, 1); + + int family = (eax >> 8) & 0xf; // family and model fields + int model = (eax >> 4) & 0xf; + if (family == 0xf) { // use extended family and model fields + family += (eax >> 20) & 0xff; + model += ((eax >> 16) & 0xf) << 4; + } + + // Opteron Rev E has a bug in which on very rare occasions a locked + // instruction doesn't act as a read-acquire barrier if followed by a + // non-locked read-modify-write instruction. Rev F has this bug in + // pre-release versions, but not in versions released to customers, + // so we test only for Rev E, which is family 15, model 32..63 inclusive. + if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD + family == 15 && + 32 <= model && model <= 63) { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; + } else { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; + } +} + +class AtomicOpsx86Initializer { + public: + AtomicOpsx86Initializer() { + AtomicOps_Internalx86CPUFeaturesInit(); + } +}; + +// A global to get use initialized on startup via static initialization :/ +AtomicOpsx86Initializer g_initer; + +} // namespace + +#endif // if x86 + +#endif // ifdef CEF_INCLUDE_BASE_CEF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/libcef_dll/base/cef_bind_helpers.cc b/libcef_dll/base/cef_bind_helpers.cc new file mode 100644 index 000000000..b65f5f31f --- /dev/null +++ b/libcef_dll/base/cef_bind_helpers.cc @@ -0,0 +1,14 @@ +// 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 "include/base/cef_bind_helpers.h" + +#include "include/base/cef_callback.h" + +namespace base { + +void DoNothing() { +} + +} // namespace base diff --git a/libcef_dll/base/cef_callback_helpers.cc b/libcef_dll/base/cef_callback_helpers.cc new file mode 100644 index 000000000..726104c7b --- /dev/null +++ b/libcef_dll/base/cef_callback_helpers.cc @@ -0,0 +1,42 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/base/cef_callback_helpers.h" + +#include "include/base/cef_callback.h" + +namespace base { + +ScopedClosureRunner::ScopedClosureRunner() { +} + +ScopedClosureRunner::ScopedClosureRunner(const Closure& closure) + : closure_(closure) { +} + +ScopedClosureRunner::~ScopedClosureRunner() { + if (!closure_.is_null()) + closure_.Run(); +} + +void ScopedClosureRunner::Reset() { + Closure old_closure = Release(); + if (!old_closure.is_null()) + old_closure.Run(); +} + +void ScopedClosureRunner::Reset(const Closure& closure) { + Closure old_closure = Release(); + closure_ = closure; + if (!old_closure.is_null()) + old_closure.Run(); +} + +Closure ScopedClosureRunner::Release() { + Closure result = closure_; + closure_.Reset(); + return result; +} + +} // namespace base diff --git a/libcef_dll/base/cef_callback_internal.cc b/libcef_dll/base/cef_callback_internal.cc new file mode 100644 index 000000000..1da9ac855 --- /dev/null +++ b/libcef_dll/base/cef_callback_internal.cc @@ -0,0 +1,38 @@ +// 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 "include/base/internal/cef_callback_internal.h" + +#include "include/base/cef_logging.h" + +namespace base { +namespace internal { + +bool CallbackBase::is_null() const { + return bind_state_.get() == NULL; +} + +void CallbackBase::Reset() { + polymorphic_invoke_ = NULL; + // NULL the bind_state_ last, since it may be holding the last ref to whatever + // object owns us, and we may be deleted after that. + bind_state_ = NULL; +} + +bool CallbackBase::Equals(const CallbackBase& other) const { + return bind_state_.get() == other.bind_state_.get() && + polymorphic_invoke_ == other.polymorphic_invoke_; +} + +CallbackBase::CallbackBase(BindStateBase* bind_state) + : bind_state_(bind_state), + polymorphic_invoke_(NULL) { + DCHECK(!bind_state_.get() || bind_state_->HasOneRef()); +} + +CallbackBase::~CallbackBase() { +} + +} // namespace internal +} // namespace base diff --git a/libcef_dll/base/cef_lock.cc b/libcef_dll/base/cef_lock.cc new file mode 100644 index 000000000..f0a2cd44a --- /dev/null +++ b/libcef_dll/base/cef_lock.cc @@ -0,0 +1,44 @@ +// 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. + +// This file is used for debugging assertion support. The Lock class +// is functionally a wrapper around the LockImpl class, so the only +// real intelligence in the class is in the debugging logic. + +#if !defined(NDEBUG) + +#include "include/base/cef_lock.h" +#include "include/base/cef_logging.h" + +namespace base { + +Lock::Lock() : lock_() { +} + +Lock::~Lock() { + DCHECK(owning_thread_ref_.is_null()); +} + +void Lock::AssertAcquired() const { + DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); +} + +void Lock::CheckHeldAndUnmark() { + DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); + owning_thread_ref_ = PlatformThreadRef(); +} + +void Lock::CheckUnheldAndMark() { + // Hitting this DCHECK means that your code is trying to re-enter a lock that + // is already held. The Chromium Lock implementation is not reentrant. + // See "Why can the holder of a Lock not reacquire it?" at + // http://www.chromium.org/developers/lock-and-condition-variable for more + // information. + DCHECK(owning_thread_ref_.is_null()); + owning_thread_ref_ = PlatformThread::CurrentRef(); +} + +} // namespace base + +#endif // NDEBUG diff --git a/libcef_dll/base/cef_lock_impl.cc b/libcef_dll/base/cef_lock_impl.cc new file mode 100644 index 000000000..97a03d192 --- /dev/null +++ b/libcef_dll/base/cef_lock_impl.cc @@ -0,0 +1,92 @@ +// 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 "include/base/internal/cef_lock_impl.h" + +#if defined(OS_WIN) + +namespace base { +namespace internal { + +LockImpl::LockImpl() { + // The second parameter is the spin count, for short-held locks it avoid the + // contending thread from going to sleep which helps performance greatly. + ::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000); +} + +LockImpl::~LockImpl() { + ::DeleteCriticalSection(&native_handle_); +} + +bool LockImpl::Try() { + if (::TryEnterCriticalSection(&native_handle_) != FALSE) { + return true; + } + return false; +} + +void LockImpl::Lock() { + ::EnterCriticalSection(&native_handle_); +} + +void LockImpl::Unlock() { + ::LeaveCriticalSection(&native_handle_); +} + +} // namespace internal +} // namespace base + +#elif defined(OS_POSIX) + +#include +#include + +#include "include/base/cef_logging.h" + +namespace base { +namespace internal { + +LockImpl::LockImpl() { +#ifndef NDEBUG + // In debug, setup attributes for lock error checking. + pthread_mutexattr_t mta; + int rv = pthread_mutexattr_init(&mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutex_init(&native_handle_, &mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + rv = pthread_mutexattr_destroy(&mta); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +#else + // In release, go with the default lock attributes. + pthread_mutex_init(&native_handle_, NULL); +#endif +} + +LockImpl::~LockImpl() { + int rv = pthread_mutex_destroy(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +bool LockImpl::Try() { + int rv = pthread_mutex_trylock(&native_handle_); + DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); + return rv == 0; +} + +void LockImpl::Lock() { + int rv = pthread_mutex_lock(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +void LockImpl::Unlock() { + int rv = pthread_mutex_unlock(&native_handle_); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); +} + +} // namespace internal +} // namespace base + +#endif // defined(OS_POSIX) diff --git a/libcef_dll/base/cef_logging.cc b/libcef_dll/base/cef_logging.cc new file mode 100644 index 000000000..a828b8fad --- /dev/null +++ b/libcef_dll/base/cef_logging.cc @@ -0,0 +1,259 @@ +// Copyright (c) 2014 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 "include/base/cef_logging.h" + +#if defined(OS_WIN) +#include +#include +#include +#elif defined(OS_POSIX) +#include +#include +#include +#endif + +#include "include/internal/cef_string_types.h" + +namespace cef { +namespace logging { + +namespace { + +#if defined(OS_POSIX) +// From base/safe_strerror_posix.cc. + +#define USE_HISTORICAL_STRERRO_R (defined(__GLIBC__) || defined(OS_NACL)) + +#if USE_HISTORICAL_STRERRO_R && defined(__GNUC__) +// GCC will complain about the unused second wrap function unless we tell it +// that we meant for them to be potentially unused, which is exactly what this +// attribute is for. +#define POSSIBLY_UNUSED __attribute__((unused)) +#else +#define POSSIBLY_UNUSED +#endif + +#if USE_HISTORICAL_STRERRO_R +// glibc has two strerror_r functions: a historical GNU-specific one that +// returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4 +// that returns int. This wraps the GNU-specific one. +static void POSSIBLY_UNUSED wrap_posix_strerror_r( + char *(*strerror_r_ptr)(int, char *, size_t), + int err, + char *buf, + size_t len) { + // GNU version. + char *rc = (*strerror_r_ptr)(err, buf, len); + if (rc != buf) { + // glibc did not use buf and returned a static string instead. Copy it + // into buf. + buf[0] = '\0'; + strncat(buf, rc, len - 1); + } + // The GNU version never fails. Unknown errors get an "unknown error" message. + // The result is always null terminated. +} +#endif // USE_HISTORICAL_STRERRO_R + +// Wrapper for strerror_r functions that implement the POSIX interface. POSIX +// does not define the behaviour for some of the edge cases, so we wrap it to +// guarantee that they are handled. This is compiled on all POSIX platforms, but +// it will only be used on Linux if the POSIX strerror_r implementation is +// being used (see below). +static void POSSIBLY_UNUSED wrap_posix_strerror_r( + int (*strerror_r_ptr)(int, char *, size_t), + int err, + char *buf, + size_t len) { + int old_errno = errno; + // Have to cast since otherwise we get an error if this is the GNU version + // (but in such a scenario this function is never called). Sadly we can't use + // C++-style casts because the appropriate one is reinterpret_cast but it's + // considered illegal to reinterpret_cast a type to itself, so we get an + // error in the opposite case. + int result = (*strerror_r_ptr)(err, buf, len); + if (result == 0) { + // POSIX is vague about whether the string will be terminated, although + // it indirectly implies that typically ERANGE will be returned, instead + // of truncating the string. We play it safe by always terminating the + // string explicitly. + buf[len - 1] = '\0'; + } else { + // Error. POSIX is vague about whether the return value is itself a system + // error code or something else. On Linux currently it is -1 and errno is + // set. On BSD-derived systems it is a system error and errno is unchanged. + // We try and detect which case it is so as to put as much useful info as + // we can into our message. + int strerror_error; // The error encountered in strerror + int new_errno = errno; + if (new_errno != old_errno) { + // errno was changed, so probably the return value is just -1 or something + // else that doesn't provide any info, and errno is the error. + strerror_error = new_errno; + } else { + // Either the error from strerror_r was the same as the previous value, or + // errno wasn't used. Assume the latter. + strerror_error = result; + } + // snprintf truncates and always null-terminates. + snprintf(buf, + len, + "Error %d while retrieving error %d", + strerror_error, + err); + } + errno = old_errno; +} + +void safe_strerror_r(int err, char *buf, size_t len) { + if (buf == NULL || len <= 0) { + return; + } + // If using glibc (i.e., Linux), the compiler will automatically select the + // appropriate overloaded function based on the function type of strerror_r. + // The other one will be elided from the translation unit since both are + // static. + wrap_posix_strerror_r(&strerror_r, err, buf, len); +} + +std::string safe_strerror(int err) { + const int buffer_size = 256; + char buf[buffer_size]; + safe_strerror_r(err, buf, sizeof(buf)); + return std::string(buf); +} +#endif // defined(OS_POSIX) + +} // namespace + +// MSVC doesn't like complex extern templates and DLLs. +#if !defined(COMPILER_MSVC) +// Explicit instantiations for commonly used comparisons. +template std::string* MakeCheckOpString( + const int&, const int&, const char* names); +template std::string* MakeCheckOpString( + const unsigned long&, const unsigned long&, const char* names); +template std::string* MakeCheckOpString( + const unsigned long&, const unsigned int&, const char* names); +template std::string* MakeCheckOpString( + const unsigned int&, const unsigned long&, const char* names); +template std::string* MakeCheckOpString( + const std::string&, const std::string&, const char* name); +#endif + +#if defined(OS_WIN) +LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { +} + +LogMessage::SaveLastError::~SaveLastError() { + ::SetLastError(last_error_); +} +#endif // defined(OS_WIN) + +LogMessage::LogMessage(const char* file, int line, LogSeverity severity) + : severity_(severity), file_(file), line_(line) { +} + +LogMessage::LogMessage(const char* file, int line, std::string* result) + : severity_(LOG_FATAL), file_(file), line_(line) { + stream_ << "Check failed: " << *result; + delete result; +} + +LogMessage::LogMessage(const char* file, int line, LogSeverity severity, + std::string* result) + : severity_(severity), file_(file), line_(line) { + stream_ << "Check failed: " << *result; + delete result; +} + +LogMessage::~LogMessage() { + stream_ << std::endl; + std::string str_newline(stream_.str()); + cef_log(file_, line_, severity_, str_newline.c_str()); +} + +#if defined(OS_WIN) +// This has already been defined in the header, but defining it again as DWORD +// ensures that the type used in the header is equivalent to DWORD. If not, +// the redefinition is a compile error. +typedef DWORD SystemErrorCode; +#endif + +SystemErrorCode GetLastSystemErrorCode() { +#if defined(OS_WIN) + return ::GetLastError(); +#elif defined(OS_POSIX) + return errno; +#else +#error Not implemented +#endif +} + +#if defined(OS_WIN) +std::string SystemErrorCodeToString(SystemErrorCode error_code) { + const int error_message_buffer_size = 256; + char msgbuf[error_message_buffer_size]; + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + DWORD len = FormatMessageA(flags, NULL, error_code, 0, msgbuf, + arraysize(msgbuf), NULL); + std::stringstream ss; + if (len) { + std::string s(msgbuf); + // Messages returned by system end with line breaks. + s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); + ss << s << " (0x" << std::hex << error_code << ")"; + } else { + ss << "Error (0x" << std::hex << GetLastError() << + ") while retrieving error. (0x" << error_code << ")"; + } + return ss.str(); +} +#elif defined(OS_POSIX) +std::string SystemErrorCodeToString(SystemErrorCode error_code) { + return safe_strerror(error_code); +} +#else +#error Not implemented +#endif + +#if defined(OS_WIN) +Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { +} + +Win32ErrorLogMessage::~Win32ErrorLogMessage() { + stream() << ": " << SystemErrorCodeToString(err_); +} +#elif defined(OS_POSIX) +ErrnoLogMessage::ErrnoLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { +} + +ErrnoLogMessage::~ErrnoLogMessage() { + stream() << ": " << SystemErrorCodeToString(err_); +} +#endif // OS_WIN + +std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { + cef_string_utf8_t str = {0}; + std::wstring tmp_str(wstr); + cef_string_wide_to_utf8(wstr, tmp_str.size(), &str); + out << str.str; + cef_string_utf8_clear(&str); + return out; +} + +} // namespace logging +} // namespace cef diff --git a/libcef_dll/base/cef_ref_counted.cc b/libcef_dll/base/cef_ref_counted.cc new file mode 100644 index 000000000..76b44b5b3 --- /dev/null +++ b/libcef_dll/base/cef_ref_counted.cc @@ -0,0 +1,53 @@ +// 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 "include/base/cef_ref_counted.h" +#include "include/base/cef_thread_collision_warner.h" + +namespace base { + +namespace subtle { + +bool RefCountedThreadSafeBase::HasOneRef() const { + return AtomicRefCountIsOne( + &const_cast(this)->ref_count_); +} + +RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) { +#ifndef NDEBUG + in_dtor_ = false; +#endif +} + +RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { +#ifndef NDEBUG + DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " + "calling Release()"; +#endif +} + +void RefCountedThreadSafeBase::AddRef() const { +#ifndef NDEBUG + DCHECK(!in_dtor_); +#endif + AtomicRefCountInc(&ref_count_); +} + +bool RefCountedThreadSafeBase::Release() const { +#ifndef NDEBUG + DCHECK(!in_dtor_); + DCHECK(!AtomicRefCountIsZero(&ref_count_)); +#endif + if (!AtomicRefCountDec(&ref_count_)) { +#ifndef NDEBUG + in_dtor_ = true; +#endif + return true; + } + return false; +} + +} // namespace subtle + +} // namespace base diff --git a/libcef_dll/base/cef_string16.cc b/libcef_dll/base/cef_string16.cc new file mode 100644 index 000000000..2e5f0b820 --- /dev/null +++ b/libcef_dll/base/cef_string16.cc @@ -0,0 +1,89 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/base/cef_string16.h" + +#if defined(OS_POSIX) +#if defined(WCHAR_T_IS_UTF16) + +#error This file should not be used on 2-byte wchar_t systems +// If this winds up being needed on 2-byte wchar_t systems, either the +// definitions below can be used, or the host system's wide character +// functions like wmemcmp can be wrapped. + +#elif defined(WCHAR_T_IS_UTF32) + +#include +#include + +#include "include/internal/cef_string_types.h" + +namespace base { + +int c16memcmp(const char16* s1, const char16* s2, size_t n) { + // We cannot call memcmp because that changes the semantics. + while (n-- > 0) { + if (*s1 != *s2) { + // We cannot use (*s1 - *s2) because char16 is unsigned. + return ((*s1 < *s2) ? -1 : 1); + } + ++s1; + ++s2; + } + return 0; +} + +size_t c16len(const char16* s) { + const char16 *s_orig = s; + while (*s) { + ++s; + } + return s - s_orig; +} + +const char16* c16memchr(const char16* s, char16 c, size_t n) { + while (n-- > 0) { + if (*s == c) { + return s; + } + ++s; + } + return 0; +} + +char16* c16memmove(char16* s1, const char16* s2, size_t n) { + return static_cast(memmove(s1, s2, n * sizeof(char16))); +} + +char16* c16memcpy(char16* s1, const char16* s2, size_t n) { + return static_cast(memcpy(s1, s2, n * sizeof(char16))); +} + +char16* c16memset(char16* s, char16 c, size_t n) { + char16 *s_orig = s; + while (n-- > 0) { + *s = c; + ++s; + } + return s_orig; +} + +std::ostream& operator<<(std::ostream& out, const string16& str) { + cef_string_utf8_t cef_str = {0}; + cef_string_utf16_to_utf8(str.c_str(), str.size(), &cef_str); + out << cef_str.str; + cef_string_utf8_clear(&cef_str); + return out; +} + +void PrintTo(const string16& str, std::ostream* out) { + *out << str; +} + +} // namespace base + +template class std::basic_string; + +#endif // WCHAR_T_IS_UTF32 +#endif // OS_POSIX diff --git a/libcef_dll/base/cef_thread_checker_impl.cc b/libcef_dll/base/cef_thread_checker_impl.cc new file mode 100644 index 000000000..d3193a28d --- /dev/null +++ b/libcef_dll/base/cef_thread_checker_impl.cc @@ -0,0 +1,34 @@ +// 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 "include/base/internal/cef_thread_checker_impl.h" + +namespace base { + +ThreadCheckerImpl::ThreadCheckerImpl() + : valid_thread_id_() { + EnsureThreadIdAssigned(); +} + +ThreadCheckerImpl::~ThreadCheckerImpl() {} + +bool ThreadCheckerImpl::CalledOnValidThread() const { + EnsureThreadIdAssigned(); + AutoLock auto_lock(lock_); + return valid_thread_id_ == PlatformThread::CurrentRef(); +} + +void ThreadCheckerImpl::DetachFromThread() { + AutoLock auto_lock(lock_); + valid_thread_id_ = PlatformThreadRef(); +} + +void ThreadCheckerImpl::EnsureThreadIdAssigned() const { + AutoLock auto_lock(lock_); + if (valid_thread_id_.is_null()) { + valid_thread_id_ = PlatformThread::CurrentRef(); + } +} + +} // namespace base diff --git a/libcef_dll/base/cef_thread_collision_warner.cc b/libcef_dll/base/cef_thread_collision_warner.cc new file mode 100644 index 000000000..794ab64a4 --- /dev/null +++ b/libcef_dll/base/cef_thread_collision_warner.cc @@ -0,0 +1,65 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/base/cef_thread_collision_warner.h" + +#include "include/base/cef_logging.h" +#include "include/internal/cef_thread_internal.h" + +namespace base { + +void DCheckAsserter::warn() { + NOTREACHED() << "Thread Collision"; +} + +static subtle::Atomic32 CurrentThread() { + const cef_platform_thread_id_t current_thread_id = + cef_get_current_platform_thread_id(); + // We need to get the thread id into an atomic data type. This might be a + // truncating conversion, but any loss-of-information just increases the + // chance of a fault negative, not a false positive. + const subtle::Atomic32 atomic_thread_id = + static_cast(current_thread_id); + + return atomic_thread_id; +} + +void ThreadCollisionWarner::EnterSelf() { + // If the active thread is 0 then I'll write the current thread ID + // if two or more threads arrive here only one will succeed to + // write on valid_thread_id_ the current thread ID. + subtle::Atomic32 current_thread_id = CurrentThread(); + + int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, + 0, + current_thread_id); + if (previous_value != 0 && previous_value != current_thread_id) { + // gotcha! a thread is trying to use the same class and that is + // not current thread. + asserter_->warn(); + } + + subtle::NoBarrier_AtomicIncrement(&counter_, 1); +} + +void ThreadCollisionWarner::Enter() { + subtle::Atomic32 current_thread_id = CurrentThread(); + + if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_, + 0, + current_thread_id) != 0) { + // gotcha! another thread is trying to use the same class. + asserter_->warn(); + } + + subtle::NoBarrier_AtomicIncrement(&counter_, 1); +} + +void ThreadCollisionWarner::Leave() { + if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) { + subtle::NoBarrier_Store(&valid_thread_id_, 0); + } +} + +} // namespace base diff --git a/libcef_dll/base/cef_weak_ptr.cc b/libcef_dll/base/cef_weak_ptr.cc new file mode 100644 index 000000000..f8a9779d5 --- /dev/null +++ b/libcef_dll/base/cef_weak_ptr.cc @@ -0,0 +1,77 @@ +// 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 "include/base/cef_weak_ptr.h" + +namespace base { +namespace internal { + +WeakReference::Flag::Flag() : is_valid_(true) { + // Flags only become bound when checked for validity, or invalidated, + // so that we can check that later validity/invalidation operations on + // the same Flag take place on the same thread. + thread_checker_.DetachFromThread(); +} + +void WeakReference::Flag::Invalidate() { + // The flag being invalidated with a single ref implies that there are no + // weak pointers in existence. Allow deletion on other thread in this case. + DCHECK(thread_checker_.CalledOnValidThread() || HasOneRef()) + << "WeakPtrs must be invalidated on the same thread."; + is_valid_ = false; +} + +bool WeakReference::Flag::IsValid() const { + DCHECK(thread_checker_.CalledOnValidThread()) + << "WeakPtrs must be checked on the same thread."; + return is_valid_; +} + +WeakReference::Flag::~Flag() { +} + +WeakReference::WeakReference() { +} + +WeakReference::WeakReference(const Flag* flag) : flag_(flag) { +} + +WeakReference::~WeakReference() { +} + +bool WeakReference::is_valid() const { return flag_.get() && flag_->IsValid(); } + +WeakReferenceOwner::WeakReferenceOwner() { +} + +WeakReferenceOwner::~WeakReferenceOwner() { + Invalidate(); +} + +WeakReference WeakReferenceOwner::GetRef() const { + // If we hold the last reference to the Flag then create a new one. + if (!HasRefs()) + flag_ = new WeakReference::Flag(); + + return WeakReference(flag_.get()); +} + +void WeakReferenceOwner::Invalidate() { + if (flag_.get()) { + flag_->Invalidate(); + flag_ = NULL; + } +} + +WeakPtrBase::WeakPtrBase() { +} + +WeakPtrBase::~WeakPtrBase() { +} + +WeakPtrBase::WeakPtrBase(const WeakReference& ref) : ref_(ref) { +} + +} // namespace internal +} // namespace base diff --git a/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc new file mode 100644 index 000000000..e0ec4d3db --- /dev/null +++ b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.cc @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK allow_certificate_error_callback_cont( + struct _cef_allow_certificate_error_callback_t* self, int allow) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefAllowCertificateErrorCallbackCppToC::Get(self)->Continue( + allow?true:false); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefAllowCertificateErrorCallbackCppToC::CefAllowCertificateErrorCallbackCppToC( + CefAllowCertificateErrorCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = allow_certificate_error_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h new file mode 100644 index 000000000..4e8a7dd39 --- /dev/null +++ b/libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h @@ -0,0 +1,39 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_ALLOW_CERTIFICATE_ERROR_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_ALLOW_CERTIFICATE_ERROR_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefAllowCertificateErrorCallbackCppToC + : public CefCppToC { + public: + explicit CefAllowCertificateErrorCallbackCppToC( + CefAllowCertificateErrorCallback* cls); + virtual ~CefAllowCertificateErrorCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_ALLOW_CERTIFICATE_ERROR_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/app_cpptoc.cc b/libcef_dll/cpptoc/app_cpptoc.cc new file mode 100644 index 000000000..557b3a1c8 --- /dev/null +++ b/libcef_dll/cpptoc/app_cpptoc.cc @@ -0,0 +1,125 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/app_cpptoc.h" +#include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h" +#include "libcef_dll/ctocpp/command_line_ctocpp.h" +#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK app_on_before_command_line_processing(struct _cef_app_t* self, + const cef_string_t* process_type, + struct _cef_command_line_t* command_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: command_line; type: refptr_diff + DCHECK(command_line); + if (!command_line) + return; + // Unverified params: process_type + + // Execute + CefAppCppToC::Get(self)->OnBeforeCommandLineProcessing( + CefString(process_type), + CefCommandLineCToCpp::Wrap(command_line)); +} + +void CEF_CALLBACK app_on_register_custom_schemes(struct _cef_app_t* self, + struct _cef_scheme_registrar_t* registrar) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: registrar; type: refptr_diff + DCHECK(registrar); + if (!registrar) + return; + + // Execute + CefAppCppToC::Get(self)->OnRegisterCustomSchemes( + CefSchemeRegistrarCToCpp::Wrap(registrar)); +} + +struct _cef_resource_bundle_handler_t* CEF_CALLBACK app_get_resource_bundle_handler( + struct _cef_app_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefAppCppToC::Get( + self)->GetResourceBundleHandler(); + + // Return type: refptr_same + return CefResourceBundleHandlerCppToC::Wrap(_retval); +} + +struct _cef_browser_process_handler_t* CEF_CALLBACK app_get_browser_process_handler( + struct _cef_app_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefAppCppToC::Get( + self)->GetBrowserProcessHandler(); + + // Return type: refptr_same + return CefBrowserProcessHandlerCppToC::Wrap(_retval); +} + +struct _cef_render_process_handler_t* CEF_CALLBACK app_get_render_process_handler( + struct _cef_app_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefAppCppToC::Get( + self)->GetRenderProcessHandler(); + + // Return type: refptr_same + return CefRenderProcessHandlerCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefAppCppToC::CefAppCppToC(CefApp* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_command_line_processing = + app_on_before_command_line_processing; + struct_.struct_.on_register_custom_schemes = app_on_register_custom_schemes; + struct_.struct_.get_resource_bundle_handler = app_get_resource_bundle_handler; + struct_.struct_.get_browser_process_handler = app_get_browser_process_handler; + struct_.struct_.get_render_process_handler = app_get_render_process_handler; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/app_cpptoc.h b/libcef_dll/cpptoc/app_cpptoc.h new file mode 100644 index 000000000..27379e399 --- /dev/null +++ b/libcef_dll/cpptoc/app_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_APP_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_APP_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_app.h" +#include "include/capi/cef_app_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefAppCppToC + : public CefCppToC { + public: + explicit CefAppCppToC(CefApp* cls); + virtual ~CefAppCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_APP_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/auth_callback_cpptoc.cc b/libcef_dll/cpptoc/auth_callback_cpptoc.cc new file mode 100644 index 000000000..623a7c7ba --- /dev/null +++ b/libcef_dll/cpptoc/auth_callback_cpptoc.cc @@ -0,0 +1,65 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/auth_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK auth_callback_cont(struct _cef_auth_callback_t* self, + const cef_string_t* username, const cef_string_t* password) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: username; type: string_byref_const + DCHECK(username); + if (!username) + return; + // Verify param: password; type: string_byref_const + DCHECK(password); + if (!password) + return; + + // Execute + CefAuthCallbackCppToC::Get(self)->Continue( + CefString(username), + CefString(password)); +} + +void CEF_CALLBACK auth_callback_cancel(struct _cef_auth_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefAuthCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefAuthCallbackCppToC::CefAuthCallbackCppToC(CefAuthCallback* cls) + : CefCppToC( + cls) { + struct_.struct_.cont = auth_callback_cont; + struct_.struct_.cancel = auth_callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/auth_callback_cpptoc.h b/libcef_dll/cpptoc/auth_callback_cpptoc.h new file mode 100644 index 000000000..fbfb7b260 --- /dev/null +++ b/libcef_dll/cpptoc/auth_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_AUTH_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_AUTH_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_auth_callback.h" +#include "include/capi/cef_auth_callback_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefAuthCallbackCppToC + : public CefCppToC { + public: + explicit CefAuthCallbackCppToC(CefAuthCallback* cls); + virtual ~CefAuthCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_AUTH_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/base_cpptoc.h b/libcef_dll/cpptoc/base_cpptoc.h new file mode 100644 index 000000000..fc20cb7ca --- /dev/null +++ b/libcef_dll/cpptoc/base_cpptoc.h @@ -0,0 +1,148 @@ +// 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_LIBCEF_DLL_CPPTOC_BASE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BASE_CPPTOC_H_ +#pragma once + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_base.h" +#include "include/capi/cef_base_capi.h" + +// CefCppToC implementation for CefBase. +class CefBaseCppToC : public CefBase { + public: + // Use this method to retrieve the underlying class instance from our + // own structure when the structure is passed as the required first + // parameter of a C API function call. No explicit reference counting + // is done in this case. + static CefRefPtr Get(cef_base_t* s) { + DCHECK(s); + + // Cast our structure to the wrapper structure type. + CefBaseCppToC::Struct* wrapperStruct = + reinterpret_cast(s); + // Return the underlying object instance. + return wrapperStruct->class_->GetClass(); + } + + // Use this method to create a wrapper structure for passing our class + // instance to the other side. + static cef_base_t* Wrap(CefRefPtr c) { + if (!c.get()) + return NULL; + + // Wrap our object with the CefCppToC class. + CefBaseCppToC* wrapper = new CefBaseCppToC(c); + // Add a reference to our wrapper object that will be released once our + // structure arrives on the other side. + wrapper->AddRef(); + // Return the structure pointer that can now be passed to the other side. + return wrapper->GetStruct(); + } + + // Use this method to retrieve the underlying class instance when receiving + // our wrapper structure back from the other side. + static CefRefPtr Unwrap(cef_base_t* s) { + if (!s) + return NULL; + + // Cast our structure to the wrapper structure type. + CefBaseCppToC::Struct* wrapperStruct = + reinterpret_cast(s); + // Add the underlying object instance to a smart pointer. + CefRefPtr objectPtr(wrapperStruct->class_->GetClass()); + // Release the reference to our wrapper object that was added before the + // structure was passed back to us. + wrapperStruct->class_->Release(); + // Return the underlying object instance. + return objectPtr; + } + + // Structure representation with pointer to the C++ class. + struct Struct { + cef_base_t struct_; + CefBaseCppToC* class_; + }; + + explicit CefBaseCppToC(CefBase* cls) + : class_(cls) { + DCHECK(cls); + + struct_.class_ = this; + + // zero the underlying structure and set base members + memset(&struct_.struct_, 0, sizeof(cef_base_t)); + struct_.struct_.size = sizeof(cef_base_t); + struct_.struct_.add_ref = struct_add_ref; + struct_.struct_.release = struct_release; + struct_.struct_.has_one_ref = struct_has_one_ref; + } + virtual ~CefBaseCppToC() {} + + CefBase* GetClass() { return class_; } + + // If returning the structure across the DLL boundary you should call + // AddRef() on this CefCppToC object. On the other side of the DLL boundary, + // call UnderlyingRelease() on the wrapping CefCToCpp object. + cef_base_t* GetStruct() { return &struct_.struct_; } + + // CefBase methods increment/decrement reference counts on both this object + // and the underlying wrapper class. + void AddRef() const { + UnderlyingAddRef(); + ref_count_.AddRef(); + } + bool Release() const { + UnderlyingRelease(); + if (ref_count_.Release()) { + delete this; + return true; + } + return false; + } + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + // Increment/decrement reference counts on only the underlying class. + void UnderlyingAddRef() const { class_->AddRef(); } + bool UnderlyingRelease() const { return class_->Release(); } + bool UnderlyingHasOneRef() const { return class_->HasOneRef(); } + + private: + static void CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return; + + Struct* impl = reinterpret_cast(base); + impl->class_->AddRef(); + } + + static int CEF_CALLBACK struct_release(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return 0; + + Struct* impl = reinterpret_cast(base); + return impl->class_->Release(); + } + + static int CEF_CALLBACK struct_has_one_ref(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return 0; + + Struct* impl = reinterpret_cast(base); + return impl->class_->HasOneRef(); + } + + CefRefCount ref_count_; + Struct struct_; + CefBase* class_; + + DISALLOW_COPY_AND_ASSIGN(CefBaseCppToC); +}; + +#endif // CEF_LIBCEF_DLL_CPPTOC_BASE_CPPTOC_H_ diff --git a/libcef_dll/cpptoc/before_download_callback_cpptoc.cc b/libcef_dll/cpptoc/before_download_callback_cpptoc.cc new file mode 100644 index 000000000..534fa0567 --- /dev/null +++ b/libcef_dll/cpptoc/before_download_callback_cpptoc.cc @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/before_download_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK before_download_callback_cont( + struct _cef_before_download_callback_t* self, + const cef_string_t* download_path, int show_dialog) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: download_path + + // Execute + CefBeforeDownloadCallbackCppToC::Get(self)->Continue( + CefString(download_path), + show_dialog?true:false); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefBeforeDownloadCallbackCppToC::CefBeforeDownloadCallbackCppToC( + CefBeforeDownloadCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = before_download_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = + 0; +#endif + diff --git a/libcef_dll/cpptoc/before_download_callback_cpptoc.h b/libcef_dll/cpptoc/before_download_callback_cpptoc.h new file mode 100644 index 000000000..06d40c760 --- /dev/null +++ b/libcef_dll/cpptoc/before_download_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_BEFORE_DOWNLOAD_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BEFORE_DOWNLOAD_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefBeforeDownloadCallbackCppToC + : public CefCppToC { + public: + explicit CefBeforeDownloadCallbackCppToC(CefBeforeDownloadCallback* cls); + virtual ~CefBeforeDownloadCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_BEFORE_DOWNLOAD_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/binary_value_cpptoc.cc b/libcef_dll/cpptoc/binary_value_cpptoc.cc new file mode 100644 index 000000000..81c9109a7 --- /dev/null +++ b/libcef_dll/cpptoc/binary_value_cpptoc.cc @@ -0,0 +1,134 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/binary_value_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_binary_value_t* cef_binary_value_create(const void* data, + size_t data_size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return NULL; + + // Execute + CefRefPtr _retval = CefBinaryValue::Create( + data, + data_size); + + // Return type: refptr_same + return CefBinaryValueCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK binary_value_is_valid(struct _cef_binary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBinaryValueCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK binary_value_is_owned(struct _cef_binary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBinaryValueCppToC::Get(self)->IsOwned(); + + // Return type: bool + return _retval; +} + +struct _cef_binary_value_t* CEF_CALLBACK binary_value_copy( + struct _cef_binary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBinaryValueCppToC::Get(self)->Copy(); + + // Return type: refptr_same + return CefBinaryValueCppToC::Wrap(_retval); +} + +size_t CEF_CALLBACK binary_value_get_size(struct _cef_binary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefBinaryValueCppToC::Get(self)->GetSize(); + + // Return type: simple + return _retval; +} + +size_t CEF_CALLBACK binary_value_get_data(struct _cef_binary_value_t* self, + void* buffer, size_t buffer_size, size_t data_offset) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return 0; + + // Execute + size_t _retval = CefBinaryValueCppToC::Get(self)->GetData( + buffer, + buffer_size, + data_offset); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefBinaryValueCppToC::CefBinaryValueCppToC(CefBinaryValue* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = binary_value_is_valid; + struct_.struct_.is_owned = binary_value_is_owned; + struct_.struct_.copy = binary_value_copy; + struct_.struct_.get_size = binary_value_get_size; + struct_.struct_.get_data = binary_value_get_data; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/binary_value_cpptoc.h b/libcef_dll/cpptoc/binary_value_cpptoc.h new file mode 100644 index 000000000..4bdbfe6c7 --- /dev/null +++ b/libcef_dll/cpptoc/binary_value_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_BINARY_VALUE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BINARY_VALUE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefBinaryValueCppToC + : public CefCppToC { + public: + explicit CefBinaryValueCppToC(CefBinaryValue* cls); + virtual ~CefBinaryValueCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_BINARY_VALUE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/browser_cpptoc.cc b/libcef_dll/cpptoc/browser_cpptoc.cc new file mode 100644 index 000000000..3844a556b --- /dev/null +++ b/libcef_dll/cpptoc/browser_cpptoc.cc @@ -0,0 +1,390 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/browser_host_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +struct _cef_browser_host_t* CEF_CALLBACK browser_get_host( + struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserCppToC::Get(self)->GetHost(); + + // Return type: refptr_same + return CefBrowserHostCppToC::Wrap(_retval); +} + +int CEF_CALLBACK browser_can_go_back(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->CanGoBack(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK browser_go_back(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserCppToC::Get(self)->GoBack(); +} + +int CEF_CALLBACK browser_can_go_forward(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->CanGoForward(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK browser_go_forward(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserCppToC::Get(self)->GoForward(); +} + +int CEF_CALLBACK browser_is_loading(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->IsLoading(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK browser_reload(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserCppToC::Get(self)->Reload(); +} + +void CEF_CALLBACK browser_reload_ignore_cache(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserCppToC::Get(self)->ReloadIgnoreCache(); +} + +void CEF_CALLBACK browser_stop_load(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserCppToC::Get(self)->StopLoad(); +} + +int CEF_CALLBACK browser_get_identifier(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefBrowserCppToC::Get(self)->GetIdentifier(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK browser_is_same(struct _cef_browser_t* self, + struct _cef_browser_t* that) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: that; type: refptr_same + DCHECK(that); + if (!that) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->IsSame( + CefBrowserCppToC::Unwrap(that)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK browser_is_popup(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->IsPopup(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK browser_has_document(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->HasDocument(); + + // Return type: bool + return _retval; +} + +struct _cef_frame_t* CEF_CALLBACK browser_get_main_frame( + struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserCppToC::Get(self)->GetMainFrame(); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +struct _cef_frame_t* CEF_CALLBACK browser_get_focused_frame( + struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserCppToC::Get(self)->GetFocusedFrame(); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +struct _cef_frame_t* CEF_CALLBACK browser_get_frame_byident( + struct _cef_browser_t* self, int64 identifier) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserCppToC::Get(self)->GetFrame( + identifier); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +struct _cef_frame_t* CEF_CALLBACK browser_get_frame(struct _cef_browser_t* self, + const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserCppToC::Get(self)->GetFrame( + CefString(name)); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +size_t CEF_CALLBACK browser_get_frame_count(struct _cef_browser_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefBrowserCppToC::Get(self)->GetFrameCount(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK browser_get_frame_identifiers(struct _cef_browser_t* self, + size_t* identifiersCount, int64* identifiers) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: identifiers; type: simple_vec_byref + DCHECK(identifiersCount && (*identifiersCount == 0 || identifiers)); + if (!identifiersCount || (*identifiersCount > 0 && !identifiers)) + return; + + // Translate param: identifiers; type: simple_vec_byref + std::vector identifiersList; + if (identifiersCount && *identifiersCount > 0 && identifiers) { + for (size_t i = 0; i < *identifiersCount; ++i) { + identifiersList.push_back(identifiers[i]); + } + } + + // Execute + CefBrowserCppToC::Get(self)->GetFrameIdentifiers( + identifiersList); + + // Restore param: identifiers; type: simple_vec_byref + if (identifiersCount && identifiers) { + *identifiersCount = std::min(identifiersList.size(), *identifiersCount); + if (*identifiersCount > 0) { + for (size_t i = 0; i < *identifiersCount; ++i) { + identifiers[i] = identifiersList[i]; + } + } + } +} + +void CEF_CALLBACK browser_get_frame_names(struct _cef_browser_t* self, + cef_string_list_t names) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: names; type: string_vec_byref + DCHECK(names); + if (!names) + return; + + // Translate param: names; type: string_vec_byref + std::vector namesList; + transfer_string_list_contents(names, namesList); + + // Execute + CefBrowserCppToC::Get(self)->GetFrameNames( + namesList); + + // Restore param: names; type: string_vec_byref + cef_string_list_clear(names); + transfer_string_list_contents(namesList, names); +} + +int CEF_CALLBACK browser_send_process_message(struct _cef_browser_t* self, + cef_process_id_t target_process, struct _cef_process_message_t* message) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: message; type: refptr_same + DCHECK(message); + if (!message) + return 0; + + // Execute + bool _retval = CefBrowserCppToC::Get(self)->SendProcessMessage( + target_process, + CefProcessMessageCppToC::Unwrap(message)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls) + : CefCppToC(cls) { + struct_.struct_.get_host = browser_get_host; + struct_.struct_.can_go_back = browser_can_go_back; + struct_.struct_.go_back = browser_go_back; + struct_.struct_.can_go_forward = browser_can_go_forward; + struct_.struct_.go_forward = browser_go_forward; + struct_.struct_.is_loading = browser_is_loading; + struct_.struct_.reload = browser_reload; + struct_.struct_.reload_ignore_cache = browser_reload_ignore_cache; + struct_.struct_.stop_load = browser_stop_load; + struct_.struct_.get_identifier = browser_get_identifier; + struct_.struct_.is_same = browser_is_same; + struct_.struct_.is_popup = browser_is_popup; + struct_.struct_.has_document = browser_has_document; + struct_.struct_.get_main_frame = browser_get_main_frame; + struct_.struct_.get_focused_frame = browser_get_focused_frame; + struct_.struct_.get_frame_byident = browser_get_frame_byident; + struct_.struct_.get_frame = browser_get_frame; + struct_.struct_.get_frame_count = browser_get_frame_count; + struct_.struct_.get_frame_identifiers = browser_get_frame_identifiers; + struct_.struct_.get_frame_names = browser_get_frame_names; + struct_.struct_.send_process_message = browser_send_process_message; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/browser_cpptoc.h b/libcef_dll/cpptoc/browser_cpptoc.h new file mode 100644 index 000000000..5c1fc02ea --- /dev/null +++ b/libcef_dll/cpptoc/browser_cpptoc.h @@ -0,0 +1,38 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BROWSER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefBrowserCppToC + : public CefCppToC { + public: + explicit CefBrowserCppToC(CefBrowser* cls); + virtual ~CefBrowserCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_BROWSER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc new file mode 100644 index 000000000..3577dc80e --- /dev/null +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -0,0 +1,818 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/browser_host_cpptoc.h" +#include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/cpptoc/request_context_cpptoc.h" +#include "libcef_dll/ctocpp/client_ctocpp.h" +#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT int cef_browser_host_create_browser( + const cef_window_info_t* windowInfo, struct _cef_client_t* client, + const cef_string_t* url, const struct _cef_browser_settings_t* settings, + struct _cef_request_context_t* request_context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: windowInfo; type: struct_byref_const + DCHECK(windowInfo); + if (!windowInfo) + return 0; + // Verify param: settings; type: struct_byref_const + DCHECK(settings); + if (!settings) + return 0; + // Unverified params: client, url, request_context + + // Translate param: windowInfo; type: struct_byref_const + CefWindowInfo windowInfoObj; + if (windowInfo) + windowInfoObj.Set(*windowInfo, false); + // Translate param: settings; type: struct_byref_const + CefBrowserSettings settingsObj; + if (settings) + settingsObj.Set(*settings, false); + + // Execute + bool _retval = CefBrowserHost::CreateBrowser( + windowInfoObj, + CefClientCToCpp::Wrap(client), + CefString(url), + settingsObj, + CefRequestContextCppToC::Unwrap(request_context)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT cef_browser_t* cef_browser_host_create_browser_sync( + const cef_window_info_t* windowInfo, struct _cef_client_t* client, + const cef_string_t* url, const struct _cef_browser_settings_t* settings, + struct _cef_request_context_t* request_context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: windowInfo; type: struct_byref_const + DCHECK(windowInfo); + if (!windowInfo) + return NULL; + // Verify param: settings; type: struct_byref_const + DCHECK(settings); + if (!settings) + return NULL; + // Unverified params: client, url, request_context + + // Translate param: windowInfo; type: struct_byref_const + CefWindowInfo windowInfoObj; + if (windowInfo) + windowInfoObj.Set(*windowInfo, false); + // Translate param: settings; type: struct_byref_const + CefBrowserSettings settingsObj; + if (settings) + settingsObj.Set(*settings, false); + + // Execute + CefRefPtr _retval = CefBrowserHost::CreateBrowserSync( + windowInfoObj, + CefClientCToCpp::Wrap(client), + CefString(url), + settingsObj, + CefRequestContextCppToC::Unwrap(request_context)); + + // Return type: refptr_same + return CefBrowserCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_browser_t* CEF_CALLBACK browser_host_get_browser( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserHostCppToC::Get(self)->GetBrowser(); + + // Return type: refptr_same + return CefBrowserCppToC::Wrap(_retval); +} + +void CEF_CALLBACK browser_host_close_browser(struct _cef_browser_host_t* self, + int force_close) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->CloseBrowser( + force_close?true:false); +} + +void CEF_CALLBACK browser_host_set_focus(struct _cef_browser_host_t* self, + int focus) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SetFocus( + focus?true:false); +} + +void CEF_CALLBACK browser_host_set_window_visibility( + struct _cef_browser_host_t* self, int visible) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SetWindowVisibility( + visible?true:false); +} + +cef_window_handle_t CEF_CALLBACK browser_host_get_window_handle( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return kNullWindowHandle; + + // Execute + cef_window_handle_t _retval = CefBrowserHostCppToC::Get( + self)->GetWindowHandle(); + + // Return type: simple + return _retval; +} + +cef_window_handle_t CEF_CALLBACK browser_host_get_opener_window_handle( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return kNullWindowHandle; + + // Execute + cef_window_handle_t _retval = CefBrowserHostCppToC::Get( + self)->GetOpenerWindowHandle(); + + // Return type: simple + return _retval; +} + +struct _cef_client_t* CEF_CALLBACK browser_host_get_client( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserHostCppToC::Get(self)->GetClient(); + + // Return type: refptr_diff + return CefClientCToCpp::Unwrap(_retval); +} + +struct _cef_request_context_t* CEF_CALLBACK browser_host_get_request_context( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserHostCppToC::Get( + self)->GetRequestContext(); + + // Return type: refptr_same + return CefRequestContextCppToC::Wrap(_retval); +} + +double CEF_CALLBACK browser_host_get_zoom_level( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + double _retval = CefBrowserHostCppToC::Get(self)->GetZoomLevel(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK browser_host_set_zoom_level(struct _cef_browser_host_t* self, + double zoomLevel) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SetZoomLevel( + zoomLevel); +} + +void CEF_CALLBACK browser_host_run_file_dialog(struct _cef_browser_host_t* self, + cef_file_dialog_mode_t mode, const cef_string_t* title, + const cef_string_t* default_file_name, cef_string_list_t accept_types, + cef_run_file_dialog_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return; + // Unverified params: title, default_file_name, accept_types + + // Translate param: accept_types; type: string_vec_byref_const + std::vector accept_typesList; + transfer_string_list_contents(accept_types, accept_typesList); + + // Execute + CefBrowserHostCppToC::Get(self)->RunFileDialog( + mode, + CefString(title), + CefString(default_file_name), + accept_typesList, + CefRunFileDialogCallbackCToCpp::Wrap(callback)); +} + +void CEF_CALLBACK browser_host_start_download(struct _cef_browser_host_t* self, + const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->StartDownload( + CefString(url)); +} + +void CEF_CALLBACK browser_host_print(struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->Print(); +} + +void CEF_CALLBACK browser_host_find(struct _cef_browser_host_t* self, + int identifier, const cef_string_t* searchText, int forward, int matchCase, + int findNext) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: searchText; type: string_byref_const + DCHECK(searchText); + if (!searchText) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->Find( + identifier, + CefString(searchText), + forward?true:false, + matchCase?true:false, + findNext?true:false); +} + +void CEF_CALLBACK browser_host_stop_finding(struct _cef_browser_host_t* self, + int clearSelection) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->StopFinding( + clearSelection?true:false); +} + +void CEF_CALLBACK browser_host_show_dev_tools(struct _cef_browser_host_t* self, + const cef_window_info_t* windowInfo, struct _cef_client_t* client, + const struct _cef_browser_settings_t* settings) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: windowInfo; type: struct_byref_const + DCHECK(windowInfo); + if (!windowInfo) + return; + // Verify param: client; type: refptr_diff + DCHECK(client); + if (!client) + return; + // Verify param: settings; type: struct_byref_const + DCHECK(settings); + if (!settings) + return; + + // Translate param: windowInfo; type: struct_byref_const + CefWindowInfo windowInfoObj; + if (windowInfo) + windowInfoObj.Set(*windowInfo, false); + // Translate param: settings; type: struct_byref_const + CefBrowserSettings settingsObj; + if (settings) + settingsObj.Set(*settings, false); + + // Execute + CefBrowserHostCppToC::Get(self)->ShowDevTools( + windowInfoObj, + CefClientCToCpp::Wrap(client), + settingsObj); +} + +void CEF_CALLBACK browser_host_close_dev_tools( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->CloseDevTools(); +} + +void CEF_CALLBACK browser_host_set_mouse_cursor_change_disabled( + struct _cef_browser_host_t* self, int disabled) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SetMouseCursorChangeDisabled( + disabled?true:false); +} + +int CEF_CALLBACK browser_host_is_mouse_cursor_change_disabled( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserHostCppToC::Get(self)->IsMouseCursorChangeDisabled(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK browser_host_is_window_rendering_disabled( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefBrowserHostCppToC::Get(self)->IsWindowRenderingDisabled(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK browser_host_was_resized(struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->WasResized(); +} + +void CEF_CALLBACK browser_host_was_hidden(struct _cef_browser_host_t* self, + int hidden) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->WasHidden( + hidden?true:false); +} + +void CEF_CALLBACK browser_host_notify_screen_info_changed( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->NotifyScreenInfoChanged(); +} + +void CEF_CALLBACK browser_host_invalidate(struct _cef_browser_host_t* self, + cef_paint_element_type_t type) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->Invalidate( + type); +} + +void CEF_CALLBACK browser_host_send_key_event(struct _cef_browser_host_t* self, + const struct _cef_key_event_t* event) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefKeyEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->SendKeyEvent( + eventObj); +} + +void CEF_CALLBACK browser_host_send_mouse_click_event( + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + cef_mouse_button_type_t type, int mouseUp, int clickCount) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->SendMouseClickEvent( + eventObj, + type, + mouseUp?true:false, + clickCount); +} + +void CEF_CALLBACK browser_host_send_mouse_move_event( + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + int mouseLeave) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->SendMouseMoveEvent( + eventObj, + mouseLeave?true:false); +} + +void CEF_CALLBACK browser_host_send_mouse_wheel_event( + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + int deltaX, int deltaY) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->SendMouseWheelEvent( + eventObj, + deltaX, + deltaY); +} + +void CEF_CALLBACK browser_host_send_focus_event( + struct _cef_browser_host_t* self, int setFocus) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SendFocusEvent( + setFocus?true:false); +} + +void CEF_CALLBACK browser_host_send_capture_lost_event( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->SendCaptureLostEvent(); +} + +cef_text_input_context_t CEF_CALLBACK browser_host_get_nstext_input_context( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + cef_text_input_context_t _retval = CefBrowserHostCppToC::Get( + self)->GetNSTextInputContext(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK browser_host_handle_key_event_before_text_input_client( + struct _cef_browser_host_t* self, cef_event_handle_t keyEvent) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->HandleKeyEventBeforeTextInputClient( + keyEvent); +} + +void CEF_CALLBACK browser_host_handle_key_event_after_text_input_client( + struct _cef_browser_host_t* self, cef_event_handle_t keyEvent) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->HandleKeyEventAfterTextInputClient( + keyEvent); +} + +void CEF_CALLBACK browser_host_drag_target_drag_enter( + struct _cef_browser_host_t* self, struct _cef_drag_data_t* drag_data, + const struct _cef_mouse_event_t* event, + cef_drag_operations_mask_t allowed_ops) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: drag_data; type: refptr_same + DCHECK(drag_data); + if (!drag_data) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->DragTargetDragEnter( + CefDragDataCppToC::Unwrap(drag_data), + eventObj, + allowed_ops); +} + +void CEF_CALLBACK browser_host_drag_target_drag_over( + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + cef_drag_operations_mask_t allowed_ops) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->DragTargetDragOver( + eventObj, + allowed_ops); +} + +void CEF_CALLBACK browser_host_drag_target_drag_leave( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->DragTargetDragLeave(); +} + +void CEF_CALLBACK browser_host_drag_target_drop( + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + CefBrowserHostCppToC::Get(self)->DragTargetDrop( + eventObj); +} + +void CEF_CALLBACK browser_host_drag_source_ended_at( + struct _cef_browser_host_t* self, int x, int y, + cef_drag_operations_mask_t op) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->DragSourceEndedAt( + x, + y, + op); +} + +void CEF_CALLBACK browser_host_drag_source_system_drag_ended( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->DragSourceSystemDragEnded(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls) + : CefCppToC(cls) { + struct_.struct_.get_browser = browser_host_get_browser; + struct_.struct_.close_browser = browser_host_close_browser; + struct_.struct_.set_focus = browser_host_set_focus; + struct_.struct_.set_window_visibility = browser_host_set_window_visibility; + struct_.struct_.get_window_handle = browser_host_get_window_handle; + struct_.struct_.get_opener_window_handle = + browser_host_get_opener_window_handle; + struct_.struct_.get_client = browser_host_get_client; + struct_.struct_.get_request_context = browser_host_get_request_context; + struct_.struct_.get_zoom_level = browser_host_get_zoom_level; + struct_.struct_.set_zoom_level = browser_host_set_zoom_level; + struct_.struct_.run_file_dialog = browser_host_run_file_dialog; + struct_.struct_.start_download = browser_host_start_download; + struct_.struct_.print = browser_host_print; + struct_.struct_.find = browser_host_find; + struct_.struct_.stop_finding = browser_host_stop_finding; + struct_.struct_.show_dev_tools = browser_host_show_dev_tools; + struct_.struct_.close_dev_tools = browser_host_close_dev_tools; + struct_.struct_.set_mouse_cursor_change_disabled = + browser_host_set_mouse_cursor_change_disabled; + struct_.struct_.is_mouse_cursor_change_disabled = + browser_host_is_mouse_cursor_change_disabled; + struct_.struct_.is_window_rendering_disabled = + browser_host_is_window_rendering_disabled; + struct_.struct_.was_resized = browser_host_was_resized; + struct_.struct_.was_hidden = browser_host_was_hidden; + struct_.struct_.notify_screen_info_changed = + browser_host_notify_screen_info_changed; + struct_.struct_.invalidate = browser_host_invalidate; + struct_.struct_.send_key_event = browser_host_send_key_event; + struct_.struct_.send_mouse_click_event = browser_host_send_mouse_click_event; + struct_.struct_.send_mouse_move_event = browser_host_send_mouse_move_event; + struct_.struct_.send_mouse_wheel_event = browser_host_send_mouse_wheel_event; + struct_.struct_.send_focus_event = browser_host_send_focus_event; + struct_.struct_.send_capture_lost_event = + browser_host_send_capture_lost_event; + struct_.struct_.get_nstext_input_context = + browser_host_get_nstext_input_context; + struct_.struct_.handle_key_event_before_text_input_client = + browser_host_handle_key_event_before_text_input_client; + struct_.struct_.handle_key_event_after_text_input_client = + browser_host_handle_key_event_after_text_input_client; + struct_.struct_.drag_target_drag_enter = browser_host_drag_target_drag_enter; + struct_.struct_.drag_target_drag_over = browser_host_drag_target_drag_over; + struct_.struct_.drag_target_drag_leave = browser_host_drag_target_drag_leave; + struct_.struct_.drag_target_drop = browser_host_drag_target_drop; + struct_.struct_.drag_source_ended_at = browser_host_drag_source_ended_at; + struct_.struct_.drag_source_system_drag_ended = + browser_host_drag_source_system_drag_ended; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.h b/libcef_dll/cpptoc/browser_host_cpptoc.h new file mode 100644 index 000000000..939439aa4 --- /dev/null +++ b/libcef_dll/cpptoc/browser_host_cpptoc.h @@ -0,0 +1,39 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_HOST_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BROWSER_HOST_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefBrowserHostCppToC + : public CefCppToC { + public: + explicit CefBrowserHostCppToC(CefBrowserHost* cls); + virtual ~CefBrowserHostCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_BROWSER_HOST_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc new file mode 100644 index 000000000..7748d276f --- /dev/null +++ b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc @@ -0,0 +1,105 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/print_handler_cpptoc.h" +#include "libcef_dll/ctocpp/command_line_ctocpp.h" +#include "libcef_dll/ctocpp/list_value_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK browser_process_handler_on_context_initialized( + struct _cef_browser_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserProcessHandlerCppToC::Get(self)->OnContextInitialized(); +} + +void CEF_CALLBACK browser_process_handler_on_before_child_process_launch( + struct _cef_browser_process_handler_t* self, + struct _cef_command_line_t* command_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: command_line; type: refptr_diff + DCHECK(command_line); + if (!command_line) + return; + + // Execute + CefBrowserProcessHandlerCppToC::Get(self)->OnBeforeChildProcessLaunch( + CefCommandLineCToCpp::Wrap(command_line)); +} + +void CEF_CALLBACK browser_process_handler_on_render_process_thread_created( + struct _cef_browser_process_handler_t* self, + struct _cef_list_value_t* extra_info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: extra_info; type: refptr_diff + DCHECK(extra_info); + if (!extra_info) + return; + + // Execute + CefBrowserProcessHandlerCppToC::Get(self)->OnRenderProcessThreadCreated( + CefListValueCToCpp::Wrap(extra_info)); +} + +struct _cef_print_handler_t* CEF_CALLBACK browser_process_handler_get_print_handler( + struct _cef_browser_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefBrowserProcessHandlerCppToC::Get( + self)->GetPrintHandler(); + + // Return type: refptr_same + return CefPrintHandlerCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC( + CefBrowserProcessHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_context_initialized = + browser_process_handler_on_context_initialized; + struct_.struct_.on_before_child_process_launch = + browser_process_handler_on_before_child_process_launch; + struct_.struct_.on_render_process_thread_created = + browser_process_handler_on_render_process_thread_created; + struct_.struct_.get_print_handler = browser_process_handler_get_print_handler; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/browser_process_handler_cpptoc.h b/libcef_dll/cpptoc/browser_process_handler_cpptoc.h new file mode 100644 index 000000000..f8fba2758 --- /dev/null +++ b/libcef_dll/cpptoc/browser_process_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_BROWSER_PROCESS_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_BROWSER_PROCESS_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_browser_process_handler.h" +#include "include/capi/cef_browser_process_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefBrowserProcessHandlerCppToC + : public CefCppToC { + public: + explicit CefBrowserProcessHandlerCppToC(CefBrowserProcessHandler* cls); + virtual ~CefBrowserProcessHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_BROWSER_PROCESS_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/callback_cpptoc.cc b/libcef_dll/cpptoc/callback_cpptoc.cc new file mode 100644 index 000000000..c87bd9013 --- /dev/null +++ b/libcef_dll/cpptoc/callback_cpptoc.cc @@ -0,0 +1,53 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK callback_cont(struct _cef_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefCallbackCppToC::Get(self)->Continue(); +} + +void CEF_CALLBACK callback_cancel(struct _cef_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCallbackCppToC::CefCallbackCppToC(CefCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = callback_cont; + struct_.struct_.cancel = callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/callback_cpptoc.h b/libcef_dll/cpptoc/callback_cpptoc.h new file mode 100644 index 000000000..69d7d3a4a --- /dev/null +++ b/libcef_dll/cpptoc/callback_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_callback.h" +#include "include/capi/cef_callback_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefCallbackCppToC + : public CefCppToC { + public: + explicit CefCallbackCppToC(CefCallback* cls); + virtual ~CefCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/client_cpptoc.cc b/libcef_dll/cpptoc/client_cpptoc.cc new file mode 100644 index 000000000..c06675e09 --- /dev/null +++ b/libcef_dll/cpptoc/client_cpptoc.cc @@ -0,0 +1,294 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/client_cpptoc.h" +#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h" +#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h" +#include "libcef_dll/cpptoc/display_handler_cpptoc.h" +#include "libcef_dll/cpptoc/download_handler_cpptoc.h" +#include "libcef_dll/cpptoc/drag_handler_cpptoc.h" +#include "libcef_dll/cpptoc/focus_handler_cpptoc.h" +#include "libcef_dll/cpptoc/geolocation_handler_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" +#include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h" +#include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" +#include "libcef_dll/cpptoc/load_handler_cpptoc.h" +#include "libcef_dll/cpptoc/render_handler_cpptoc.h" +#include "libcef_dll/cpptoc/request_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +struct _cef_context_menu_handler_t* CEF_CALLBACK client_get_context_menu_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetContextMenuHandler(); + + // Return type: refptr_same + return CefContextMenuHandlerCppToC::Wrap(_retval); +} + +struct _cef_dialog_handler_t* CEF_CALLBACK client_get_dialog_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetDialogHandler(); + + // Return type: refptr_same + return CefDialogHandlerCppToC::Wrap(_retval); +} + +struct _cef_display_handler_t* CEF_CALLBACK client_get_display_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetDisplayHandler(); + + // Return type: refptr_same + return CefDisplayHandlerCppToC::Wrap(_retval); +} + +struct _cef_download_handler_t* CEF_CALLBACK client_get_download_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetDownloadHandler(); + + // Return type: refptr_same + return CefDownloadHandlerCppToC::Wrap(_retval); +} + +struct _cef_drag_handler_t* CEF_CALLBACK client_get_drag_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetDragHandler(); + + // Return type: refptr_same + return CefDragHandlerCppToC::Wrap(_retval); +} + +struct _cef_focus_handler_t* CEF_CALLBACK client_get_focus_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetFocusHandler(); + + // Return type: refptr_same + return CefFocusHandlerCppToC::Wrap(_retval); +} + +struct _cef_geolocation_handler_t* CEF_CALLBACK client_get_geolocation_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetGeolocationHandler(); + + // Return type: refptr_same + return CefGeolocationHandlerCppToC::Wrap(_retval); +} + +struct _cef_jsdialog_handler_t* CEF_CALLBACK client_get_jsdialog_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetJSDialogHandler(); + + // Return type: refptr_same + return CefJSDialogHandlerCppToC::Wrap(_retval); +} + +struct _cef_keyboard_handler_t* CEF_CALLBACK client_get_keyboard_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetKeyboardHandler(); + + // Return type: refptr_same + return CefKeyboardHandlerCppToC::Wrap(_retval); +} + +struct _cef_life_span_handler_t* CEF_CALLBACK client_get_life_span_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetLifeSpanHandler(); + + // Return type: refptr_same + return CefLifeSpanHandlerCppToC::Wrap(_retval); +} + +struct _cef_load_handler_t* CEF_CALLBACK client_get_load_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetLoadHandler(); + + // Return type: refptr_same + return CefLoadHandlerCppToC::Wrap(_retval); +} + +struct _cef_render_handler_t* CEF_CALLBACK client_get_render_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetRenderHandler(); + + // Return type: refptr_same + return CefRenderHandlerCppToC::Wrap(_retval); +} + +struct _cef_request_handler_t* CEF_CALLBACK client_get_request_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetRequestHandler(); + + // Return type: refptr_same + return CefRequestHandlerCppToC::Wrap(_retval); +} + +int CEF_CALLBACK client_on_process_message_received(struct _cef_client_t* self, + cef_browser_t* browser, cef_process_id_t source_process, + struct _cef_process_message_t* message) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: message; type: refptr_diff + DCHECK(message); + if (!message) + return 0; + + // Execute + bool _retval = CefClientCppToC::Get(self)->OnProcessMessageReceived( + CefBrowserCToCpp::Wrap(browser), + source_process, + CefProcessMessageCToCpp::Wrap(message)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefClientCppToC::CefClientCppToC(CefClient* cls) + : CefCppToC(cls) { + struct_.struct_.get_context_menu_handler = client_get_context_menu_handler; + struct_.struct_.get_dialog_handler = client_get_dialog_handler; + struct_.struct_.get_display_handler = client_get_display_handler; + struct_.struct_.get_download_handler = client_get_download_handler; + struct_.struct_.get_drag_handler = client_get_drag_handler; + struct_.struct_.get_focus_handler = client_get_focus_handler; + struct_.struct_.get_geolocation_handler = client_get_geolocation_handler; + struct_.struct_.get_jsdialog_handler = client_get_jsdialog_handler; + struct_.struct_.get_keyboard_handler = client_get_keyboard_handler; + struct_.struct_.get_life_span_handler = client_get_life_span_handler; + struct_.struct_.get_load_handler = client_get_load_handler; + struct_.struct_.get_render_handler = client_get_render_handler; + struct_.struct_.get_request_handler = client_get_request_handler; + struct_.struct_.on_process_message_received = + client_on_process_message_received; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/client_cpptoc.h b/libcef_dll/cpptoc/client_cpptoc.h new file mode 100644 index 000000000..16919e89b --- /dev/null +++ b/libcef_dll/cpptoc/client_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_CLIENT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_CLIENT_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefClientCppToC + : public CefCppToC { + public: + explicit CefClientCppToC(CefClient* cls); + virtual ~CefClientCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_CLIENT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/command_line_cpptoc.cc b/libcef_dll/cpptoc/command_line_cpptoc.cc new file mode 100644 index 000000000..3eda76e54 --- /dev/null +++ b/libcef_dll/cpptoc/command_line_cpptoc.cc @@ -0,0 +1,428 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/command_line_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_command_line_t* cef_command_line_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefCommandLine::CreateCommandLine(); + + // Return type: refptr_same + return CefCommandLineCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_command_line_t* cef_command_line_get_global() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefCommandLine::GetGlobalCommandLine(); + + // Return type: refptr_same + return CefCommandLineCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK command_line_is_valid(struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefCommandLineCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK command_line_is_read_only(struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefCommandLineCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +struct _cef_command_line_t* CEF_CALLBACK command_line_copy( + struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefCommandLineCppToC::Get(self)->Copy(); + + // Return type: refptr_same + return CefCommandLineCppToC::Wrap(_retval); +} + +void CEF_CALLBACK command_line_init_from_argv(struct _cef_command_line_t* self, + int argc, const char* const* argv) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: argv; type: simple_byaddr + DCHECK(argv); + if (!argv) + return; + + // Execute + CefCommandLineCppToC::Get(self)->InitFromArgv( + argc, + argv); +} + +void CEF_CALLBACK command_line_init_from_string( + struct _cef_command_line_t* self, const cef_string_t* command_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: command_line; type: string_byref_const + DCHECK(command_line); + if (!command_line) + return; + + // Execute + CefCommandLineCppToC::Get(self)->InitFromString( + CefString(command_line)); +} + +void CEF_CALLBACK command_line_reset(struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefCommandLineCppToC::Get(self)->Reset(); +} + +void CEF_CALLBACK command_line_get_argv(struct _cef_command_line_t* self, + cef_string_list_t argv) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: argv; type: string_vec_byref + DCHECK(argv); + if (!argv) + return; + + // Translate param: argv; type: string_vec_byref + std::vector argvList; + transfer_string_list_contents(argv, argvList); + + // Execute + CefCommandLineCppToC::Get(self)->GetArgv( + argvList); + + // Restore param: argv; type: string_vec_byref + cef_string_list_clear(argv); + transfer_string_list_contents(argvList, argv); +} + +cef_string_userfree_t CEF_CALLBACK command_line_get_command_line_string( + struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefCommandLineCppToC::Get(self)->GetCommandLineString(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK command_line_get_program( + struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefCommandLineCppToC::Get(self)->GetProgram(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK command_line_set_program(struct _cef_command_line_t* self, + const cef_string_t* program) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: program; type: string_byref_const + DCHECK(program); + if (!program) + return; + + // Execute + CefCommandLineCppToC::Get(self)->SetProgram( + CefString(program)); +} + +int CEF_CALLBACK command_line_has_switches(struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefCommandLineCppToC::Get(self)->HasSwitches(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK command_line_has_switch(struct _cef_command_line_t* self, + const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return 0; + + // Execute + bool _retval = CefCommandLineCppToC::Get(self)->HasSwitch( + CefString(name)); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK command_line_get_switch_value( + struct _cef_command_line_t* self, const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return NULL; + + // Execute + CefString _retval = CefCommandLineCppToC::Get(self)->GetSwitchValue( + CefString(name)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK command_line_get_switches(struct _cef_command_line_t* self, + cef_string_map_t switches) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: switches; type: string_map_single_byref + DCHECK(switches); + if (!switches) + return; + + // Translate param: switches; type: string_map_single_byref + std::map switchesMap; + transfer_string_map_contents(switches, switchesMap); + + // Execute + CefCommandLineCppToC::Get(self)->GetSwitches( + switchesMap); + + // Restore param: switches; type: string_map_single_byref + cef_string_map_clear(switches); + transfer_string_map_contents(switchesMap, switches); +} + +void CEF_CALLBACK command_line_append_switch(struct _cef_command_line_t* self, + const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return; + + // Execute + CefCommandLineCppToC::Get(self)->AppendSwitch( + CefString(name)); +} + +void CEF_CALLBACK command_line_append_switch_with_value( + struct _cef_command_line_t* self, const cef_string_t* name, + const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return; + // Verify param: value; type: string_byref_const + DCHECK(value); + if (!value) + return; + + // Execute + CefCommandLineCppToC::Get(self)->AppendSwitchWithValue( + CefString(name), + CefString(value)); +} + +int CEF_CALLBACK command_line_has_arguments(struct _cef_command_line_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefCommandLineCppToC::Get(self)->HasArguments(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK command_line_get_arguments(struct _cef_command_line_t* self, + cef_string_list_t arguments) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: arguments; type: string_vec_byref + DCHECK(arguments); + if (!arguments) + return; + + // Translate param: arguments; type: string_vec_byref + std::vector argumentsList; + transfer_string_list_contents(arguments, argumentsList); + + // Execute + CefCommandLineCppToC::Get(self)->GetArguments( + argumentsList); + + // Restore param: arguments; type: string_vec_byref + cef_string_list_clear(arguments); + transfer_string_list_contents(argumentsList, arguments); +} + +void CEF_CALLBACK command_line_append_argument(struct _cef_command_line_t* self, + const cef_string_t* argument) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: argument; type: string_byref_const + DCHECK(argument); + if (!argument) + return; + + // Execute + CefCommandLineCppToC::Get(self)->AppendArgument( + CefString(argument)); +} + +void CEF_CALLBACK command_line_prepend_wrapper(struct _cef_command_line_t* self, + const cef_string_t* wrapper) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: wrapper; type: string_byref_const + DCHECK(wrapper); + if (!wrapper) + return; + + // Execute + CefCommandLineCppToC::Get(self)->PrependWrapper( + CefString(wrapper)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCommandLineCppToC::CefCommandLineCppToC(CefCommandLine* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = command_line_is_valid; + struct_.struct_.is_read_only = command_line_is_read_only; + struct_.struct_.copy = command_line_copy; + struct_.struct_.init_from_argv = command_line_init_from_argv; + struct_.struct_.init_from_string = command_line_init_from_string; + struct_.struct_.reset = command_line_reset; + struct_.struct_.get_argv = command_line_get_argv; + struct_.struct_.get_command_line_string = + command_line_get_command_line_string; + struct_.struct_.get_program = command_line_get_program; + struct_.struct_.set_program = command_line_set_program; + struct_.struct_.has_switches = command_line_has_switches; + struct_.struct_.has_switch = command_line_has_switch; + struct_.struct_.get_switch_value = command_line_get_switch_value; + struct_.struct_.get_switches = command_line_get_switches; + struct_.struct_.append_switch = command_line_append_switch; + struct_.struct_.append_switch_with_value = + command_line_append_switch_with_value; + struct_.struct_.has_arguments = command_line_has_arguments; + struct_.struct_.get_arguments = command_line_get_arguments; + struct_.struct_.append_argument = command_line_append_argument; + struct_.struct_.prepend_wrapper = command_line_prepend_wrapper; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/command_line_cpptoc.h b/libcef_dll/cpptoc/command_line_cpptoc.h new file mode 100644 index 000000000..8d172772e --- /dev/null +++ b/libcef_dll/cpptoc/command_line_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_COMMAND_LINE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_COMMAND_LINE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_command_line.h" +#include "include/capi/cef_command_line_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefCommandLineCppToC + : public CefCppToC { + public: + explicit CefCommandLineCppToC(CefCommandLine* cls); + virtual ~CefCommandLineCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_COMMAND_LINE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/completion_callback_cpptoc.cc b/libcef_dll/cpptoc/completion_callback_cpptoc.cc new file mode 100644 index 000000000..3b8d25a85 --- /dev/null +++ b/libcef_dll/cpptoc/completion_callback_cpptoc.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/completion_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK completion_callback_on_complete( + struct _cef_completion_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefCompletionCallbackCppToC::Get(self)->OnComplete(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCompletionCallbackCppToC::CefCompletionCallbackCppToC( + CefCompletionCallback* cls) + : CefCppToC(cls) { + struct_.struct_.on_complete = completion_callback_on_complete; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/completion_callback_cpptoc.h b/libcef_dll/cpptoc/completion_callback_cpptoc.h new file mode 100644 index 000000000..b198ad8ab --- /dev/null +++ b/libcef_dll/cpptoc/completion_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_COMPLETION_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_COMPLETION_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_callback.h" +#include "include/capi/cef_callback_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefCompletionCallbackCppToC + : public CefCppToC { + public: + explicit CefCompletionCallbackCppToC(CefCompletionCallback* cls); + virtual ~CefCompletionCallbackCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_COMPLETION_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc b/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc new file mode 100644 index 000000000..b1924f430 --- /dev/null +++ b/libcef_dll/cpptoc/context_menu_handler_cpptoc.cc @@ -0,0 +1,132 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/context_menu_params_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/menu_model_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK context_menu_handler_on_before_context_menu( + struct _cef_context_menu_handler_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_context_menu_params_t* params, + struct _cef_menu_model_t* model) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: params; type: refptr_diff + DCHECK(params); + if (!params) + return; + // Verify param: model; type: refptr_diff + DCHECK(model); + if (!model) + return; + + // Execute + CefContextMenuHandlerCppToC::Get(self)->OnBeforeContextMenu( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefContextMenuParamsCToCpp::Wrap(params), + CefMenuModelCToCpp::Wrap(model)); +} + +int CEF_CALLBACK context_menu_handler_on_context_menu_command( + struct _cef_context_menu_handler_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_context_menu_params_t* params, + int command_id, cef_event_flags_t event_flags) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: params; type: refptr_diff + DCHECK(params); + if (!params) + return 0; + + // Execute + bool _retval = CefContextMenuHandlerCppToC::Get(self)->OnContextMenuCommand( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefContextMenuParamsCToCpp::Wrap(params), + command_id, + event_flags); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK context_menu_handler_on_context_menu_dismissed( + struct _cef_context_menu_handler_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + + // Execute + CefContextMenuHandlerCppToC::Get(self)->OnContextMenuDismissed( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC( + CefContextMenuHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_context_menu = + context_menu_handler_on_before_context_menu; + struct_.struct_.on_context_menu_command = + context_menu_handler_on_context_menu_command; + struct_.struct_.on_context_menu_dismissed = + context_menu_handler_on_context_menu_dismissed; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/context_menu_handler_cpptoc.h b/libcef_dll/cpptoc/context_menu_handler_cpptoc.h new file mode 100644 index 000000000..e84bc23b7 --- /dev/null +++ b/libcef_dll/cpptoc/context_menu_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_context_menu_handler.h" +#include "include/capi/cef_context_menu_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefContextMenuHandlerCppToC + : public CefCppToC { + public: + explicit CefContextMenuHandlerCppToC(CefContextMenuHandler* cls); + virtual ~CefContextMenuHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/context_menu_params_cpptoc.cc b/libcef_dll/cpptoc/context_menu_params_cpptoc.cc new file mode 100644 index 000000000..017dfafd1 --- /dev/null +++ b/libcef_dll/cpptoc/context_menu_params_cpptoc.cc @@ -0,0 +1,279 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/context_menu_params_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK context_menu_params_get_xcoord( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefContextMenuParamsCppToC::Get(self)->GetXCoord(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK context_menu_params_get_ycoord( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefContextMenuParamsCppToC::Get(self)->GetYCoord(); + + // Return type: simple + return _retval; +} + +cef_context_menu_type_flags_t CEF_CALLBACK context_menu_params_get_type_flags( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CM_TYPEFLAG_NONE; + + // Execute + cef_context_menu_type_flags_t _retval = CefContextMenuParamsCppToC::Get( + self)->GetTypeFlags(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_link_url( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetLinkUrl(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_unfiltered_link_url( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get( + self)->GetUnfilteredLinkUrl(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_source_url( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetSourceUrl(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK context_menu_params_has_image_contents( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefContextMenuParamsCppToC::Get(self)->HasImageContents(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_page_url( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetPageUrl(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_frame_url( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetFrameUrl(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_frame_charset( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetFrameCharset(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_context_menu_media_type_t CEF_CALLBACK context_menu_params_get_media_type( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CM_MEDIATYPE_NONE; + + // Execute + cef_context_menu_media_type_t _retval = CefContextMenuParamsCppToC::Get( + self)->GetMediaType(); + + // Return type: simple + return _retval; +} + +cef_context_menu_media_state_flags_t CEF_CALLBACK context_menu_params_get_media_state_flags( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CM_MEDIAFLAG_NONE; + + // Execute + cef_context_menu_media_state_flags_t _retval = + CefContextMenuParamsCppToC::Get(self)->GetMediaStateFlags(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK context_menu_params_get_selection_text( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefContextMenuParamsCppToC::Get(self)->GetSelectionText(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK context_menu_params_is_editable( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefContextMenuParamsCppToC::Get(self)->IsEditable(); + + // Return type: bool + return _retval; +} + +cef_context_menu_edit_state_flags_t CEF_CALLBACK context_menu_params_get_edit_state_flags( + struct _cef_context_menu_params_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CM_EDITFLAG_NONE; + + // Execute + cef_context_menu_edit_state_flags_t _retval = CefContextMenuParamsCppToC::Get( + self)->GetEditStateFlags(); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefContextMenuParamsCppToC::CefContextMenuParamsCppToC( + CefContextMenuParams* cls) + : CefCppToC(cls) { + struct_.struct_.get_xcoord = context_menu_params_get_xcoord; + struct_.struct_.get_ycoord = context_menu_params_get_ycoord; + struct_.struct_.get_type_flags = context_menu_params_get_type_flags; + struct_.struct_.get_link_url = context_menu_params_get_link_url; + struct_.struct_.get_unfiltered_link_url = + context_menu_params_get_unfiltered_link_url; + struct_.struct_.get_source_url = context_menu_params_get_source_url; + struct_.struct_.has_image_contents = context_menu_params_has_image_contents; + struct_.struct_.get_page_url = context_menu_params_get_page_url; + struct_.struct_.get_frame_url = context_menu_params_get_frame_url; + struct_.struct_.get_frame_charset = context_menu_params_get_frame_charset; + struct_.struct_.get_media_type = context_menu_params_get_media_type; + struct_.struct_.get_media_state_flags = + context_menu_params_get_media_state_flags; + struct_.struct_.get_selection_text = context_menu_params_get_selection_text; + struct_.struct_.is_editable = context_menu_params_is_editable; + struct_.struct_.get_edit_state_flags = + context_menu_params_get_edit_state_flags; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/context_menu_params_cpptoc.h b/libcef_dll/cpptoc/context_menu_params_cpptoc.h new file mode 100644 index 000000000..ef24da9cf --- /dev/null +++ b/libcef_dll/cpptoc/context_menu_params_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_PARAMS_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_PARAMS_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_context_menu_handler.h" +#include "include/capi/cef_context_menu_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefContextMenuParamsCppToC + : public CefCppToC { + public: + explicit CefContextMenuParamsCppToC(CefContextMenuParams* cls); + virtual ~CefContextMenuParamsCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_CONTEXT_MENU_PARAMS_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc new file mode 100644 index 000000000..61fbcb41e --- /dev/null +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc @@ -0,0 +1,225 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" +#include "libcef_dll/ctocpp/completion_callback_ctocpp.h" +#include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefCookieManager::GetGlobalManager(); + + // Return type: refptr_same + return CefCookieManagerCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( + const cef_string_t* path, int persist_session_cookies) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + CefRefPtr _retval = CefCookieManager::CreateManager( + CefString(path), + persist_session_cookies?true:false); + + // Return type: refptr_same + return CefCookieManagerCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK cookie_manager_set_supported_schemes( + struct _cef_cookie_manager_t* self, cef_string_list_t schemes) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: schemes; type: string_vec_byref_const + DCHECK(schemes); + if (!schemes) + return; + + // Translate param: schemes; type: string_vec_byref_const + std::vector schemesList; + transfer_string_list_contents(schemes, schemesList); + + // Execute + CefCookieManagerCppToC::Get(self)->SetSupportedSchemes( + schemesList); +} + +int CEF_CALLBACK cookie_manager_visit_all_cookies( + struct _cef_cookie_manager_t* self, + struct _cef_cookie_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return 0; + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->VisitAllCookies( + CefCookieVisitorCToCpp::Wrap(visitor)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_visit_url_cookies( + struct _cef_cookie_manager_t* self, const cef_string_t* url, + int includeHttpOnly, struct _cef_cookie_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return 0; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return 0; + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->VisitUrlCookies( + CefString(url), + includeHttpOnly?true:false, + CefCookieVisitorCToCpp::Wrap(visitor)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const struct _cef_cookie_t* cookie) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return 0; + // Verify param: cookie; type: struct_byref_const + DCHECK(cookie); + if (!cookie) + return 0; + + // Translate param: cookie; type: struct_byref_const + CefCookie cookieObj; + if (cookie) + cookieObj.Set(*cookie, false); + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->SetCookie( + CefString(url), + cookieObj); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_delete_cookies( + struct _cef_cookie_manager_t* self, const cef_string_t* url, + const cef_string_t* cookie_name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: url, cookie_name + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->DeleteCookies( + CefString(url), + CefString(cookie_name)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_set_storage_path( + struct _cef_cookie_manager_t* self, const cef_string_t* path, + int persist_session_cookies) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: path + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->SetStoragePath( + CefString(path), + persist_session_cookies?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_flush_store(struct _cef_cookie_manager_t* self, + cef_completion_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->FlushStore( + CefCompletionCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCookieManagerCppToC::CefCookieManagerCppToC(CefCookieManager* cls) + : CefCppToC( + cls) { + struct_.struct_.set_supported_schemes = cookie_manager_set_supported_schemes; + struct_.struct_.visit_all_cookies = cookie_manager_visit_all_cookies; + struct_.struct_.visit_url_cookies = cookie_manager_visit_url_cookies; + struct_.struct_.set_cookie = cookie_manager_set_cookie; + struct_.struct_.delete_cookies = cookie_manager_delete_cookies; + struct_.struct_.set_storage_path = cookie_manager_set_storage_path; + struct_.struct_.flush_store = cookie_manager_flush_store; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.h b/libcef_dll/cpptoc/cookie_manager_cpptoc.h new file mode 100644 index 000000000..960459b3c --- /dev/null +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefCookieManagerCppToC + : public CefCppToC { + public: + explicit CefCookieManagerCppToC(CefCookieManager* cls); + virtual ~CefCookieManagerCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc b/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc new file mode 100644 index 000000000..c93c2eef4 --- /dev/null +++ b/libcef_dll/cpptoc/cookie_visitor_cpptoc.cc @@ -0,0 +1,70 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK cookie_visitor_visit(struct _cef_cookie_visitor_t* self, + const struct _cef_cookie_t* cookie, int count, int total, + int* deleteCookie) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: cookie; type: struct_byref_const + DCHECK(cookie); + if (!cookie) + return 0; + // Verify param: deleteCookie; type: bool_byref + DCHECK(deleteCookie); + if (!deleteCookie) + return 0; + + // Translate param: cookie; type: struct_byref_const + CefCookie cookieObj; + if (cookie) + cookieObj.Set(*cookie, false); + // Translate param: deleteCookie; type: bool_byref + bool deleteCookieBool = (deleteCookie && *deleteCookie)?true:false; + + // Execute + bool _retval = CefCookieVisitorCppToC::Get(self)->Visit( + cookieObj, + count, + total, + deleteCookieBool); + + // Restore param: deleteCookie; type: bool_byref + if (deleteCookie) + *deleteCookie = deleteCookieBool?true:false; + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCookieVisitorCppToC::CefCookieVisitorCppToC(CefCookieVisitor* cls) + : CefCppToC( + cls) { + struct_.struct_.visit = cookie_visitor_visit; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/cookie_visitor_cpptoc.h b/libcef_dll/cpptoc/cookie_visitor_cpptoc.h new file mode 100644 index 000000000..5b1417621 --- /dev/null +++ b/libcef_dll/cpptoc/cookie_visitor_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_COOKIE_VISITOR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_COOKIE_VISITOR_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefCookieVisitorCppToC + : public CefCppToC { + public: + explicit CefCookieVisitorCppToC(CefCookieVisitor* cls); + virtual ~CefCookieVisitorCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_COOKIE_VISITOR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/cpptoc.h b/libcef_dll/cpptoc/cpptoc.h new file mode 100644 index 000000000..8d2e48c4f --- /dev/null +++ b/libcef_dll/cpptoc/cpptoc.h @@ -0,0 +1,165 @@ +// 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_LIBCEF_DLL_CPPTOC_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_CPPTOC_H_ +#pragma once + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_base.h" +#include "include/capi/cef_base_capi.h" + + +// Wrap a C++ class with a C structure. This is used when the class +// implementation exists on this side of the DLL boundary but will have methods +// called from the other side of the DLL boundary. +template +class CefCppToC : public CefBase { + public: + // Structure representation with pointer to the C++ class. + struct Struct { + StructName struct_; + CefCppToC* class_; + }; + + // Use this method to retrieve the underlying class instance from our + // own structure when the structure is passed as the required first + // parameter of a C API function call. No explicit reference counting + // is done in this case. + static CefRefPtr Get(StructName* s) { + DCHECK(s); + + // Cast our structure to the wrapper structure type. + Struct* wrapperStruct = reinterpret_cast(s); + // Return the underlying object instance. + return wrapperStruct->class_->GetClass(); + } + + // Use this method to create a wrapper structure for passing our class + // instance to the other side. + static StructName* Wrap(CefRefPtr c) { + if (!c.get()) + return NULL; + + // Wrap our object with the CefCppToC class. + ClassName* wrapper = new ClassName(c); + // Add a reference to our wrapper object that will be released once our + // structure arrives on the other side. + wrapper->AddRef(); + // Return the structure pointer that can now be passed to the other side. + return wrapper->GetStruct(); + } + + // Use this method to retrieve the underlying class instance when receiving + // our wrapper structure back from the other side. + static CefRefPtr Unwrap(StructName* s) { + if (!s) + return NULL; + + // Cast our structure to the wrapper structure type. + Struct* wrapperStruct = reinterpret_cast(s); + // Add the underlying object instance to a smart pointer. + CefRefPtr objectPtr(wrapperStruct->class_->GetClass()); + // Release the reference to our wrapper object that was added before the + // structure was passed back to us. + wrapperStruct->class_->Release(); + // Return the underlying object instance. + return objectPtr; + } + + explicit CefCppToC(BaseName* cls) + : class_(cls) { + DCHECK(cls); + + struct_.class_ = this; + + // zero the underlying structure and set base members + memset(&struct_.struct_, 0, sizeof(StructName)); + struct_.struct_.base.size = sizeof(StructName); + struct_.struct_.base.add_ref = struct_add_ref; + struct_.struct_.base.release = struct_release; + struct_.struct_.base.has_one_ref = struct_has_one_ref; + +#ifndef NDEBUG + base::AtomicRefCountInc(&DebugObjCt); +#endif + } + virtual ~CefCppToC() { +#ifndef NDEBUG + base::AtomicRefCountDec(&DebugObjCt); +#endif + } + + BaseName* GetClass() { return class_; } + + // If returning the structure across the DLL boundary you should call + // AddRef() on this CefCppToC object. On the other side of the DLL boundary, + // call UnderlyingRelease() on the wrapping CefCToCpp object. + StructName* GetStruct() { return &struct_.struct_; } + + // CefBase methods increment/decrement reference counts on both this object + // and the underlying wrapper class. + void AddRef() const { + UnderlyingAddRef(); + ref_count_.AddRef(); + } + bool Release() const { + UnderlyingRelease(); + if (ref_count_.Release()) { + delete this; + return true; + } + return false; + } + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + // Increment/decrement reference counts on only the underlying class. + void UnderlyingAddRef() const { class_->AddRef(); } + bool UnderlyingRelease() const { return class_->Release(); } + bool UnderlyingHasOneRef() const { return class_->HasOneRef(); } + +#ifndef NDEBUG + // Simple tracking of allocated objects. + static base::AtomicRefCount DebugObjCt; // NOLINT(runtime/int) +#endif + + protected: + Struct struct_; + BaseName* class_; + + private: + static void CEF_CALLBACK struct_add_ref(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return; + + Struct* impl = reinterpret_cast(base); + impl->class_->AddRef(); + } + + static int CEF_CALLBACK struct_release(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return 0; + + Struct* impl = reinterpret_cast(base); + return impl->class_->Release(); + } + + static int CEF_CALLBACK struct_has_one_ref(struct _cef_base_t* base) { + DCHECK(base); + if (!base) + return 0; + + Struct* impl = reinterpret_cast(base); + return impl->class_->HasOneRef(); + } + + CefRefCount ref_count_; + + DISALLOW_COPY_AND_ASSIGN(CefCppToC); +}; + +#endif // CEF_LIBCEF_DLL_CPPTOC_CPPTOC_H_ diff --git a/libcef_dll/cpptoc/dialog_handler_cpptoc.cc b/libcef_dll/cpptoc/dialog_handler_cpptoc.cc new file mode 100644 index 000000000..80320a36f --- /dev/null +++ b/libcef_dll/cpptoc/dialog_handler_cpptoc.cc @@ -0,0 +1,71 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK dialog_handler_on_file_dialog( + struct _cef_dialog_handler_t* self, cef_browser_t* browser, + cef_file_dialog_mode_t mode, const cef_string_t* title, + const cef_string_t* default_file_name, cef_string_list_t accept_types, + cef_file_dialog_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Unverified params: title, default_file_name, accept_types + + // Translate param: accept_types; type: string_vec_byref_const + std::vector accept_typesList; + transfer_string_list_contents(accept_types, accept_typesList); + + // Execute + bool _retval = CefDialogHandlerCppToC::Get(self)->OnFileDialog( + CefBrowserCToCpp::Wrap(browser), + mode, + CefString(title), + CefString(default_file_name), + accept_typesList, + CefFileDialogCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDialogHandlerCppToC::CefDialogHandlerCppToC(CefDialogHandler* cls) + : CefCppToC( + cls) { + struct_.struct_.on_file_dialog = dialog_handler_on_file_dialog; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/dialog_handler_cpptoc.h b/libcef_dll/cpptoc/dialog_handler_cpptoc.h new file mode 100644 index 000000000..a629a5ee0 --- /dev/null +++ b/libcef_dll/cpptoc/dialog_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dialog_handler.h" +#include "include/capi/cef_dialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDialogHandlerCppToC + : public CefCppToC { + public: + explicit CefDialogHandlerCppToC(CefDialogHandler* cls); + virtual ~CefDialogHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DIALOG_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/dictionary_value_cpptoc.cc b/libcef_dll/cpptoc/dictionary_value_cpptoc.cc new file mode 100644 index 000000000..ff41d6172 --- /dev/null +++ b/libcef_dll/cpptoc/dictionary_value_cpptoc.cc @@ -0,0 +1,577 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/binary_value_cpptoc.h" +#include "libcef_dll/cpptoc/dictionary_value_cpptoc.h" +#include "libcef_dll/cpptoc/list_value_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_dictionary_value_t* cef_dictionary_value_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefDictionaryValue::Create(); + + // Return type: refptr_same + return CefDictionaryValueCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK dictionary_value_is_valid( + struct _cef_dictionary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_is_owned( + struct _cef_dictionary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->IsOwned(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_is_read_only( + struct _cef_dictionary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +struct _cef_dictionary_value_t* CEF_CALLBACK dictionary_value_copy( + struct _cef_dictionary_value_t* self, int exclude_empty_children) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDictionaryValueCppToC::Get( + self)->Copy( + exclude_empty_children?true:false); + + // Return type: refptr_same + return CefDictionaryValueCppToC::Wrap(_retval); +} + +size_t CEF_CALLBACK dictionary_value_get_size( + struct _cef_dictionary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefDictionaryValueCppToC::Get(self)->GetSize(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK dictionary_value_clear(struct _cef_dictionary_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->Clear(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_has_key(struct _cef_dictionary_value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->HasKey( + CefString(key)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_get_keys(struct _cef_dictionary_value_t* self, + cef_string_list_t keys) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: keys; type: string_vec_byref + DCHECK(keys); + if (!keys) + return 0; + + // Translate param: keys; type: string_vec_byref + std::vector keysList; + transfer_string_list_contents(keys, keysList); + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->GetKeys( + keysList); + + // Restore param: keys; type: string_vec_byref + cef_string_list_clear(keys); + transfer_string_list_contents(keysList, keys); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_remove(struct _cef_dictionary_value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->Remove( + CefString(key)); + + // Return type: bool + return _retval; +} + +cef_value_type_t CEF_CALLBACK dictionary_value_get_type( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return VTYPE_INVALID; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return VTYPE_INVALID; + + // Execute + cef_value_type_t _retval = CefDictionaryValueCppToC::Get(self)->GetType( + CefString(key)); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK dictionary_value_get_bool(struct _cef_dictionary_value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->GetBool( + CefString(key)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_get_int(struct _cef_dictionary_value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + int _retval = CefDictionaryValueCppToC::Get(self)->GetInt( + CefString(key)); + + // Return type: simple + return _retval; +} + +double CEF_CALLBACK dictionary_value_get_double( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + double _retval = CefDictionaryValueCppToC::Get(self)->GetDouble( + CefString(key)); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK dictionary_value_get_string( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return NULL; + + // Execute + CefString _retval = CefDictionaryValueCppToC::Get(self)->GetString( + CefString(key)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_binary_value_t* CEF_CALLBACK dictionary_value_get_binary( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return NULL; + + // Execute + CefRefPtr _retval = CefDictionaryValueCppToC::Get( + self)->GetBinary( + CefString(key)); + + // Return type: refptr_same + return CefBinaryValueCppToC::Wrap(_retval); +} + +struct _cef_dictionary_value_t* CEF_CALLBACK dictionary_value_get_dictionary( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return NULL; + + // Execute + CefRefPtr _retval = CefDictionaryValueCppToC::Get( + self)->GetDictionary( + CefString(key)); + + // Return type: refptr_same + return CefDictionaryValueCppToC::Wrap(_retval); +} + +struct _cef_list_value_t* CEF_CALLBACK dictionary_value_get_list( + struct _cef_dictionary_value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return NULL; + + // Execute + CefRefPtr _retval = CefDictionaryValueCppToC::Get( + self)->GetList( + CefString(key)); + + // Return type: refptr_same + return CefListValueCppToC::Wrap(_retval); +} + +int CEF_CALLBACK dictionary_value_set_null(struct _cef_dictionary_value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetNull( + CefString(key)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_bool(struct _cef_dictionary_value_t* self, + const cef_string_t* key, int value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetBool( + CefString(key), + value?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_int(struct _cef_dictionary_value_t* self, + const cef_string_t* key, int value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetInt( + CefString(key), + value); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_double( + struct _cef_dictionary_value_t* self, const cef_string_t* key, + double value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetDouble( + CefString(key), + value); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_string( + struct _cef_dictionary_value_t* self, const cef_string_t* key, + const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + // Unverified params: value + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetString( + CefString(key), + CefString(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_binary( + struct _cef_dictionary_value_t* self, const cef_string_t* key, + cef_binary_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetBinary( + CefString(key), + CefBinaryValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_dictionary( + struct _cef_dictionary_value_t* self, const cef_string_t* key, + struct _cef_dictionary_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetDictionary( + CefString(key), + CefDictionaryValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK dictionary_value_set_list(struct _cef_dictionary_value_t* self, + const cef_string_t* key, struct _cef_list_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key; type: string_byref_const + DCHECK(key); + if (!key) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefDictionaryValueCppToC::Get(self)->SetList( + CefString(key), + CefListValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDictionaryValueCppToC::CefDictionaryValueCppToC(CefDictionaryValue* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = dictionary_value_is_valid; + struct_.struct_.is_owned = dictionary_value_is_owned; + struct_.struct_.is_read_only = dictionary_value_is_read_only; + struct_.struct_.copy = dictionary_value_copy; + struct_.struct_.get_size = dictionary_value_get_size; + struct_.struct_.clear = dictionary_value_clear; + struct_.struct_.has_key = dictionary_value_has_key; + struct_.struct_.get_keys = dictionary_value_get_keys; + struct_.struct_.remove = dictionary_value_remove; + struct_.struct_.get_type = dictionary_value_get_type; + struct_.struct_.get_bool = dictionary_value_get_bool; + struct_.struct_.get_int = dictionary_value_get_int; + struct_.struct_.get_double = dictionary_value_get_double; + struct_.struct_.get_string = dictionary_value_get_string; + struct_.struct_.get_binary = dictionary_value_get_binary; + struct_.struct_.get_dictionary = dictionary_value_get_dictionary; + struct_.struct_.get_list = dictionary_value_get_list; + struct_.struct_.set_null = dictionary_value_set_null; + struct_.struct_.set_bool = dictionary_value_set_bool; + struct_.struct_.set_int = dictionary_value_set_int; + struct_.struct_.set_double = dictionary_value_set_double; + struct_.struct_.set_string = dictionary_value_set_string; + struct_.struct_.set_binary = dictionary_value_set_binary; + struct_.struct_.set_dictionary = dictionary_value_set_dictionary; + struct_.struct_.set_list = dictionary_value_set_list; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/dictionary_value_cpptoc.h b/libcef_dll/cpptoc/dictionary_value_cpptoc.h new file mode 100644 index 000000000..2f1416559 --- /dev/null +++ b/libcef_dll/cpptoc/dictionary_value_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DICTIONARY_VALUE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DICTIONARY_VALUE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDictionaryValueCppToC + : public CefCppToC { + public: + explicit CefDictionaryValueCppToC(CefDictionaryValue* cls); + virtual ~CefDictionaryValueCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DICTIONARY_VALUE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/display_handler_cpptoc.cc b/libcef_dll/cpptoc/display_handler_cpptoc.cc new file mode 100644 index 000000000..3b950f781 --- /dev/null +++ b/libcef_dll/cpptoc/display_handler_cpptoc.cc @@ -0,0 +1,155 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/display_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK display_handler_on_address_change( + struct _cef_display_handler_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame, const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefDisplayHandlerCppToC::Get(self)->OnAddressChange( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefString(url)); +} + +void CEF_CALLBACK display_handler_on_title_change( + struct _cef_display_handler_t* self, cef_browser_t* browser, + const cef_string_t* title) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Unverified params: title + + // Execute + CefDisplayHandlerCppToC::Get(self)->OnTitleChange( + CefBrowserCToCpp::Wrap(browser), + CefString(title)); +} + +int CEF_CALLBACK display_handler_on_tooltip(struct _cef_display_handler_t* self, + cef_browser_t* browser, cef_string_t* text) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Unverified params: text + + // Translate param: text; type: string_byref + CefString textStr(text); + + // Execute + bool _retval = CefDisplayHandlerCppToC::Get(self)->OnTooltip( + CefBrowserCToCpp::Wrap(browser), + textStr); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK display_handler_on_status_message( + struct _cef_display_handler_t* self, cef_browser_t* browser, + const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Unverified params: value + + // Execute + CefDisplayHandlerCppToC::Get(self)->OnStatusMessage( + CefBrowserCToCpp::Wrap(browser), + CefString(value)); +} + +int CEF_CALLBACK display_handler_on_console_message( + struct _cef_display_handler_t* self, cef_browser_t* browser, + const cef_string_t* message, const cef_string_t* source, int line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Unverified params: message, source + + // Execute + bool _retval = CefDisplayHandlerCppToC::Get(self)->OnConsoleMessage( + CefBrowserCToCpp::Wrap(browser), + CefString(message), + CefString(source), + line); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDisplayHandlerCppToC::CefDisplayHandlerCppToC(CefDisplayHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_address_change = display_handler_on_address_change; + struct_.struct_.on_title_change = display_handler_on_title_change; + struct_.struct_.on_tooltip = display_handler_on_tooltip; + struct_.struct_.on_status_message = display_handler_on_status_message; + struct_.struct_.on_console_message = display_handler_on_console_message; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/display_handler_cpptoc.h b/libcef_dll/cpptoc/display_handler_cpptoc.h new file mode 100644 index 000000000..305600d54 --- /dev/null +++ b/libcef_dll/cpptoc/display_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DISPLAY_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DISPLAY_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_display_handler.h" +#include "include/capi/cef_display_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDisplayHandlerCppToC + : public CefCppToC { + public: + explicit CefDisplayHandlerCppToC(CefDisplayHandler* cls); + virtual ~CefDisplayHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DISPLAY_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/domdocument_cpptoc.cc b/libcef_dll/cpptoc/domdocument_cpptoc.cc new file mode 100644 index 000000000..65b582722 --- /dev/null +++ b/libcef_dll/cpptoc/domdocument_cpptoc.cc @@ -0,0 +1,303 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domdocument_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_dom_document_type_t CEF_CALLBACK domdocument_get_type( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return DOM_DOCUMENT_TYPE_UNKNOWN; + + // Execute + cef_dom_document_type_t _retval = CefDOMDocumentCppToC::Get(self)->GetType(); + + // Return type: simple + return _retval; +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_document( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get(self)->GetDocument( + ); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_body( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get(self)->GetBody(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_head( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get(self)->GetHead(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +cef_string_userfree_t CEF_CALLBACK domdocument_get_title( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMDocumentCppToC::Get(self)->GetTitle(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_element_by_id( + struct _cef_domdocument_t* self, const cef_string_t* id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: id; type: string_byref_const + DCHECK(id); + if (!id) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get( + self)->GetElementById( + CefString(id)); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_focused_node( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get( + self)->GetFocusedNode(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +int CEF_CALLBACK domdocument_has_selection(struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMDocumentCppToC::Get(self)->HasSelection(); + + // Return type: bool + return _retval; +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_selection_start_node( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get( + self)->GetSelectionStartNode(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +int CEF_CALLBACK domdocument_get_selection_start_offset( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionStartOffset(); + + // Return type: simple + return _retval; +} + +struct _cef_domnode_t* CEF_CALLBACK domdocument_get_selection_end_node( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMDocumentCppToC::Get( + self)->GetSelectionEndNode(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +int CEF_CALLBACK domdocument_get_selection_end_offset( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionEndOffset(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domdocument_get_selection_as_markup( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionAsMarkup(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK domdocument_get_selection_as_text( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMDocumentCppToC::Get(self)->GetSelectionAsText(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK domdocument_get_base_url( + struct _cef_domdocument_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMDocumentCppToC::Get(self)->GetBaseURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK domdocument_get_complete_url( + struct _cef_domdocument_t* self, const cef_string_t* partialURL) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: partialURL; type: string_byref_const + DCHECK(partialURL); + if (!partialURL) + return NULL; + + // Execute + CefString _retval = CefDOMDocumentCppToC::Get(self)->GetCompleteURL( + CefString(partialURL)); + + // Return type: string + return _retval.DetachToUserFree(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDOMDocumentCppToC::CefDOMDocumentCppToC(CefDOMDocument* cls) + : CefCppToC(cls) { + struct_.struct_.get_type = domdocument_get_type; + struct_.struct_.get_document = domdocument_get_document; + struct_.struct_.get_body = domdocument_get_body; + struct_.struct_.get_head = domdocument_get_head; + struct_.struct_.get_title = domdocument_get_title; + struct_.struct_.get_element_by_id = domdocument_get_element_by_id; + struct_.struct_.get_focused_node = domdocument_get_focused_node; + struct_.struct_.has_selection = domdocument_has_selection; + struct_.struct_.get_selection_start_node = + domdocument_get_selection_start_node; + struct_.struct_.get_selection_start_offset = + domdocument_get_selection_start_offset; + struct_.struct_.get_selection_end_node = domdocument_get_selection_end_node; + struct_.struct_.get_selection_end_offset = + domdocument_get_selection_end_offset; + struct_.struct_.get_selection_as_markup = domdocument_get_selection_as_markup; + struct_.struct_.get_selection_as_text = domdocument_get_selection_as_text; + struct_.struct_.get_base_url = domdocument_get_base_url; + struct_.struct_.get_complete_url = domdocument_get_complete_url; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/domdocument_cpptoc.h b/libcef_dll/cpptoc/domdocument_cpptoc.h new file mode 100644 index 000000000..c922eb009 --- /dev/null +++ b/libcef_dll/cpptoc/domdocument_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOMDOCUMENT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOMDOCUMENT_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDOMDocumentCppToC + : public CefCppToC { + public: + explicit CefDOMDocumentCppToC(CefDOMDocument* cls); + virtual ~CefDOMDocumentCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOMDOCUMENT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/domevent_cpptoc.cc b/libcef_dll/cpptoc/domevent_cpptoc.cc new file mode 100644 index 000000000..dbe6220e2 --- /dev/null +++ b/libcef_dll/cpptoc/domevent_cpptoc.cc @@ -0,0 +1,159 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domdocument_cpptoc.h" +#include "libcef_dll/cpptoc/domevent_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_string_userfree_t CEF_CALLBACK domevent_get_type( + struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMEventCppToC::Get(self)->GetType(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_dom_event_category_t CEF_CALLBACK domevent_get_category( + struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return DOM_EVENT_CATEGORY_UNKNOWN; + + // Execute + cef_dom_event_category_t _retval = CefDOMEventCppToC::Get(self)->GetCategory( + ); + + // Return type: simple + return _retval; +} + +cef_dom_event_phase_t CEF_CALLBACK domevent_get_phase( + struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return DOM_EVENT_PHASE_UNKNOWN; + + // Execute + cef_dom_event_phase_t _retval = CefDOMEventCppToC::Get(self)->GetPhase(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK domevent_can_bubble(struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMEventCppToC::Get(self)->CanBubble(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK domevent_can_cancel(struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMEventCppToC::Get(self)->CanCancel(); + + // Return type: bool + return _retval; +} + +cef_domdocument_t* CEF_CALLBACK domevent_get_document( + struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMEventCppToC::Get(self)->GetDocument( + ); + + // Return type: refptr_same + return CefDOMDocumentCppToC::Wrap(_retval); +} + +cef_domnode_t* CEF_CALLBACK domevent_get_target(struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMEventCppToC::Get(self)->GetTarget(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +cef_domnode_t* CEF_CALLBACK domevent_get_current_target( + struct _cef_domevent_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMEventCppToC::Get( + self)->GetCurrentTarget(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDOMEventCppToC::CefDOMEventCppToC(CefDOMEvent* cls) + : CefCppToC(cls) { + struct_.struct_.get_type = domevent_get_type; + struct_.struct_.get_category = domevent_get_category; + struct_.struct_.get_phase = domevent_get_phase; + struct_.struct_.can_bubble = domevent_can_bubble; + struct_.struct_.can_cancel = domevent_can_cancel; + struct_.struct_.get_document = domevent_get_document; + struct_.struct_.get_target = domevent_get_target; + struct_.struct_.get_current_target = domevent_get_current_target; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/domevent_cpptoc.h b/libcef_dll/cpptoc/domevent_cpptoc.h new file mode 100644 index 000000000..c041ed0a1 --- /dev/null +++ b/libcef_dll/cpptoc/domevent_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDOMEventCppToC + : public CefCppToC { + public: + explicit CefDOMEventCppToC(CefDOMEvent* cls); + virtual ~CefDOMEventCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/domevent_listener_cpptoc.cc b/libcef_dll/cpptoc/domevent_listener_cpptoc.cc new file mode 100644 index 000000000..6065991ec --- /dev/null +++ b/libcef_dll/cpptoc/domevent_listener_cpptoc.cc @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domevent_listener_cpptoc.h" +#include "libcef_dll/ctocpp/domevent_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK domevent_listener_handle_event( + struct _cef_domevent_listener_t* self, cef_domevent_t* event) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: event; type: refptr_diff + DCHECK(event); + if (!event) + return; + + // Execute + CefDOMEventListenerCppToC::Get(self)->HandleEvent( + CefDOMEventCToCpp::Wrap(event)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDOMEventListenerCppToC::CefDOMEventListenerCppToC(CefDOMEventListener* cls) + : CefCppToC(cls) { + struct_.struct_.handle_event = domevent_listener_handle_event; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/domevent_listener_cpptoc.h b/libcef_dll/cpptoc/domevent_listener_cpptoc.h new file mode 100644 index 000000000..5f63c4e97 --- /dev/null +++ b/libcef_dll/cpptoc/domevent_listener_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_LISTENER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_LISTENER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDOMEventListenerCppToC + : public CefCppToC { + public: + explicit CefDOMEventListenerCppToC(CefDOMEventListener* cls); + virtual ~CefDOMEventListenerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOMEVENT_LISTENER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/domnode_cpptoc.cc b/libcef_dll/cpptoc/domnode_cpptoc.cc new file mode 100644 index 000000000..754d44646 --- /dev/null +++ b/libcef_dll/cpptoc/domnode_cpptoc.cc @@ -0,0 +1,493 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domdocument_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" +#include "libcef_dll/ctocpp/domevent_listener_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_dom_node_type_t CEF_CALLBACK domnode_get_type(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return DOM_NODE_TYPE_UNSUPPORTED; + + // Execute + cef_dom_node_type_t _retval = CefDOMNodeCppToC::Get(self)->GetType(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK domnode_is_text(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->IsText(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK domnode_is_element(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->IsElement(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK domnode_is_editable(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->IsEditable(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK domnode_is_form_control_element(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->IsFormControlElement(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_form_control_element_type( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetFormControlElementType(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK domnode_is_same(struct _cef_domnode_t* self, + struct _cef_domnode_t* that) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: that; type: refptr_same + DCHECK(that); + if (!that) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->IsSame( + CefDOMNodeCppToC::Unwrap(that)); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_name( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_value( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetValue(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK domnode_set_value(struct _cef_domnode_t* self, + const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: value; type: string_byref_const + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->SetValue( + CefString(value)); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_as_markup( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetAsMarkup(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_domdocument_t* CEF_CALLBACK domnode_get_document( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get(self)->GetDocument( + ); + + // Return type: refptr_same + return CefDOMDocumentCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domnode_get_parent( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get(self)->GetParent(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domnode_get_previous_sibling( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get( + self)->GetPreviousSibling(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domnode_get_next_sibling( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get(self)->GetNextSibling(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +int CEF_CALLBACK domnode_has_children(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->HasChildren(); + + // Return type: bool + return _retval; +} + +struct _cef_domnode_t* CEF_CALLBACK domnode_get_first_child( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get(self)->GetFirstChild(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +struct _cef_domnode_t* CEF_CALLBACK domnode_get_last_child( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDOMNodeCppToC::Get(self)->GetLastChild(); + + // Return type: refptr_same + return CefDOMNodeCppToC::Wrap(_retval); +} + +void CEF_CALLBACK domnode_add_event_listener(struct _cef_domnode_t* self, + const cef_string_t* eventType, struct _cef_domevent_listener_t* listener, + int useCapture) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: eventType; type: string_byref_const + DCHECK(eventType); + if (!eventType) + return; + // Verify param: listener; type: refptr_diff + DCHECK(listener); + if (!listener) + return; + + // Execute + CefDOMNodeCppToC::Get(self)->AddEventListener( + CefString(eventType), + CefDOMEventListenerCToCpp::Wrap(listener), + useCapture?true:false); +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_element_tag_name( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetElementTagName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK domnode_has_element_attributes(struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->HasElementAttributes(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK domnode_has_element_attribute(struct _cef_domnode_t* self, + const cef_string_t* attrName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: attrName; type: string_byref_const + DCHECK(attrName); + if (!attrName) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->HasElementAttribute( + CefString(attrName)); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_element_attribute( + struct _cef_domnode_t* self, const cef_string_t* attrName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: attrName; type: string_byref_const + DCHECK(attrName); + if (!attrName) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetElementAttribute( + CefString(attrName)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK domnode_get_element_attributes(struct _cef_domnode_t* self, + cef_string_map_t attrMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: attrMap; type: string_map_single_byref + DCHECK(attrMap); + if (!attrMap) + return; + + // Translate param: attrMap; type: string_map_single_byref + std::map attrMapMap; + transfer_string_map_contents(attrMap, attrMapMap); + + // Execute + CefDOMNodeCppToC::Get(self)->GetElementAttributes( + attrMapMap); + + // Restore param: attrMap; type: string_map_single_byref + cef_string_map_clear(attrMap); + transfer_string_map_contents(attrMapMap, attrMap); +} + +int CEF_CALLBACK domnode_set_element_attribute(struct _cef_domnode_t* self, + const cef_string_t* attrName, const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: attrName; type: string_byref_const + DCHECK(attrName); + if (!attrName) + return 0; + // Verify param: value; type: string_byref_const + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefDOMNodeCppToC::Get(self)->SetElementAttribute( + CefString(attrName), + CefString(value)); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_element_inner_text( + struct _cef_domnode_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDOMNodeCppToC::Get(self)->GetElementInnerText(); + + // Return type: string + return _retval.DetachToUserFree(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDOMNodeCppToC::CefDOMNodeCppToC(CefDOMNode* cls) + : CefCppToC(cls) { + struct_.struct_.get_type = domnode_get_type; + struct_.struct_.is_text = domnode_is_text; + struct_.struct_.is_element = domnode_is_element; + struct_.struct_.is_editable = domnode_is_editable; + struct_.struct_.is_form_control_element = domnode_is_form_control_element; + struct_.struct_.get_form_control_element_type = + domnode_get_form_control_element_type; + struct_.struct_.is_same = domnode_is_same; + struct_.struct_.get_name = domnode_get_name; + struct_.struct_.get_value = domnode_get_value; + struct_.struct_.set_value = domnode_set_value; + struct_.struct_.get_as_markup = domnode_get_as_markup; + struct_.struct_.get_document = domnode_get_document; + struct_.struct_.get_parent = domnode_get_parent; + struct_.struct_.get_previous_sibling = domnode_get_previous_sibling; + struct_.struct_.get_next_sibling = domnode_get_next_sibling; + struct_.struct_.has_children = domnode_has_children; + struct_.struct_.get_first_child = domnode_get_first_child; + struct_.struct_.get_last_child = domnode_get_last_child; + struct_.struct_.add_event_listener = domnode_add_event_listener; + struct_.struct_.get_element_tag_name = domnode_get_element_tag_name; + struct_.struct_.has_element_attributes = domnode_has_element_attributes; + struct_.struct_.has_element_attribute = domnode_has_element_attribute; + struct_.struct_.get_element_attribute = domnode_get_element_attribute; + struct_.struct_.get_element_attributes = domnode_get_element_attributes; + struct_.struct_.set_element_attribute = domnode_set_element_attribute; + struct_.struct_.get_element_inner_text = domnode_get_element_inner_text; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/domnode_cpptoc.h b/libcef_dll/cpptoc/domnode_cpptoc.h new file mode 100644 index 000000000..0de62bac4 --- /dev/null +++ b/libcef_dll/cpptoc/domnode_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOMNODE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOMNODE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDOMNodeCppToC + : public CefCppToC { + public: + explicit CefDOMNodeCppToC(CefDOMNode* cls); + virtual ~CefDOMNodeCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOMNODE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/domvisitor_cpptoc.cc b/libcef_dll/cpptoc/domvisitor_cpptoc.cc new file mode 100644 index 000000000..1cb49108b --- /dev/null +++ b/libcef_dll/cpptoc/domvisitor_cpptoc.cc @@ -0,0 +1,48 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domvisitor_cpptoc.h" +#include "libcef_dll/ctocpp/domdocument_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK domvisitor_visit(struct _cef_domvisitor_t* self, + struct _cef_domdocument_t* document) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: document; type: refptr_diff + DCHECK(document); + if (!document) + return; + + // Execute + CefDOMVisitorCppToC::Get(self)->Visit( + CefDOMDocumentCToCpp::Wrap(document)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDOMVisitorCppToC::CefDOMVisitorCppToC(CefDOMVisitor* cls) + : CefCppToC(cls) { + struct_.struct_.visit = domvisitor_visit; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/domvisitor_cpptoc.h b/libcef_dll/cpptoc/domvisitor_cpptoc.h new file mode 100644 index 000000000..c5196b2db --- /dev/null +++ b/libcef_dll/cpptoc/domvisitor_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOMVISITOR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOMVISITOR_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDOMVisitorCppToC + : public CefCppToC { + public: + explicit CefDOMVisitorCppToC(CefDOMVisitor* cls); + virtual ~CefDOMVisitorCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOMVISITOR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/download_handler_cpptoc.cc b/libcef_dll/cpptoc/download_handler_cpptoc.cc new file mode 100644 index 000000000..277b632b9 --- /dev/null +++ b/libcef_dll/cpptoc/download_handler_cpptoc.cc @@ -0,0 +1,100 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/download_handler_cpptoc.h" +#include "libcef_dll/ctocpp/before_download_callback_ctocpp.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/download_item_ctocpp.h" +#include "libcef_dll/ctocpp/download_item_callback_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK download_handler_on_before_download( + struct _cef_download_handler_t* self, cef_browser_t* browser, + struct _cef_download_item_t* download_item, + const cef_string_t* suggested_name, + cef_before_download_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: download_item; type: refptr_diff + DCHECK(download_item); + if (!download_item) + return; + // Verify param: suggested_name; type: string_byref_const + DCHECK(suggested_name); + if (!suggested_name) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return; + + // Execute + CefDownloadHandlerCppToC::Get(self)->OnBeforeDownload( + CefBrowserCToCpp::Wrap(browser), + CefDownloadItemCToCpp::Wrap(download_item), + CefString(suggested_name), + CefBeforeDownloadCallbackCToCpp::Wrap(callback)); +} + +void CEF_CALLBACK download_handler_on_download_updated( + struct _cef_download_handler_t* self, cef_browser_t* browser, + struct _cef_download_item_t* download_item, + cef_download_item_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: download_item; type: refptr_diff + DCHECK(download_item); + if (!download_item) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return; + + // Execute + CefDownloadHandlerCppToC::Get(self)->OnDownloadUpdated( + CefBrowserCToCpp::Wrap(browser), + CefDownloadItemCToCpp::Wrap(download_item), + CefDownloadItemCallbackCToCpp::Wrap(callback)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDownloadHandlerCppToC::CefDownloadHandlerCppToC(CefDownloadHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_download = download_handler_on_before_download; + struct_.struct_.on_download_updated = download_handler_on_download_updated; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/download_handler_cpptoc.h b/libcef_dll/cpptoc/download_handler_cpptoc.h new file mode 100644 index 000000000..dbb13f3b3 --- /dev/null +++ b/libcef_dll/cpptoc/download_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDownloadHandlerCppToC + : public CefCppToC { + public: + explicit CefDownloadHandlerCppToC(CefDownloadHandler* cls); + virtual ~CefDownloadHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/download_item_callback_cpptoc.cc b/libcef_dll/cpptoc/download_item_callback_cpptoc.cc new file mode 100644 index 000000000..6870c347c --- /dev/null +++ b/libcef_dll/cpptoc/download_item_callback_cpptoc.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/download_item_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK download_item_callback_cancel( + struct _cef_download_item_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefDownloadItemCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDownloadItemCallbackCppToC::CefDownloadItemCallbackCppToC( + CefDownloadItemCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cancel = download_item_callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/download_item_callback_cpptoc.h b/libcef_dll/cpptoc/download_item_callback_cpptoc.h new file mode 100644 index 000000000..eb779fae5 --- /dev/null +++ b/libcef_dll/cpptoc/download_item_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDownloadItemCallbackCppToC + : public CefCppToC { + public: + explicit CefDownloadItemCallbackCppToC(CefDownloadItemCallback* cls); + virtual ~CefDownloadItemCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/download_item_cpptoc.cc b/libcef_dll/cpptoc/download_item_cpptoc.cc new file mode 100644 index 000000000..9612c29d8 --- /dev/null +++ b/libcef_dll/cpptoc/download_item_cpptoc.cc @@ -0,0 +1,284 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/download_item_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK download_item_is_valid(struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDownloadItemCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK download_item_is_in_progress( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDownloadItemCppToC::Get(self)->IsInProgress(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK download_item_is_complete(struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDownloadItemCppToC::Get(self)->IsComplete(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK download_item_is_canceled(struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDownloadItemCppToC::Get(self)->IsCanceled(); + + // Return type: bool + return _retval; +} + +int64 CEF_CALLBACK download_item_get_current_speed( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefDownloadItemCppToC::Get(self)->GetCurrentSpeed(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK download_item_get_percent_complete( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefDownloadItemCppToC::Get(self)->GetPercentComplete(); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK download_item_get_total_bytes( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefDownloadItemCppToC::Get(self)->GetTotalBytes(); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK download_item_get_received_bytes( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefDownloadItemCppToC::Get(self)->GetReceivedBytes(); + + // Return type: simple + return _retval; +} + +cef_time_t CEF_CALLBACK download_item_get_start_time( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CefTime(); + + // Execute + cef_time_t _retval = CefDownloadItemCppToC::Get(self)->GetStartTime(); + + // Return type: simple + return _retval; +} + +cef_time_t CEF_CALLBACK download_item_get_end_time( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CefTime(); + + // Execute + cef_time_t _retval = CefDownloadItemCppToC::Get(self)->GetEndTime(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK download_item_get_full_path( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDownloadItemCppToC::Get(self)->GetFullPath(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +uint32 CEF_CALLBACK download_item_get_id(struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + uint32 _retval = CefDownloadItemCppToC::Get(self)->GetId(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK download_item_get_url( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDownloadItemCppToC::Get(self)->GetURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK download_item_get_suggested_file_name( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDownloadItemCppToC::Get(self)->GetSuggestedFileName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK download_item_get_content_disposition( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDownloadItemCppToC::Get(self)->GetContentDisposition(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK download_item_get_mime_type( + struct _cef_download_item_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDownloadItemCppToC::Get(self)->GetMimeType(); + + // Return type: string + return _retval.DetachToUserFree(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDownloadItemCppToC::CefDownloadItemCppToC(CefDownloadItem* cls) + : CefCppToC( + cls) { + struct_.struct_.is_valid = download_item_is_valid; + struct_.struct_.is_in_progress = download_item_is_in_progress; + struct_.struct_.is_complete = download_item_is_complete; + struct_.struct_.is_canceled = download_item_is_canceled; + struct_.struct_.get_current_speed = download_item_get_current_speed; + struct_.struct_.get_percent_complete = download_item_get_percent_complete; + struct_.struct_.get_total_bytes = download_item_get_total_bytes; + struct_.struct_.get_received_bytes = download_item_get_received_bytes; + struct_.struct_.get_start_time = download_item_get_start_time; + struct_.struct_.get_end_time = download_item_get_end_time; + struct_.struct_.get_full_path = download_item_get_full_path; + struct_.struct_.get_id = download_item_get_id; + struct_.struct_.get_url = download_item_get_url; + struct_.struct_.get_suggested_file_name = + download_item_get_suggested_file_name; + struct_.struct_.get_content_disposition = + download_item_get_content_disposition; + struct_.struct_.get_mime_type = download_item_get_mime_type; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/download_item_cpptoc.h b/libcef_dll/cpptoc/download_item_cpptoc.h new file mode 100644 index 000000000..61f134b96 --- /dev/null +++ b/libcef_dll/cpptoc/download_item_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_download_item.h" +#include "include/capi/cef_download_item_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDownloadItemCppToC + : public CefCppToC { + public: + explicit CefDownloadItemCppToC(CefDownloadItem* cls); + virtual ~CefDownloadItemCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DOWNLOAD_ITEM_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/drag_data_cpptoc.cc b/libcef_dll/cpptoc/drag_data_cpptoc.cc new file mode 100644 index 000000000..456ddfe84 --- /dev/null +++ b/libcef_dll/cpptoc/drag_data_cpptoc.cc @@ -0,0 +1,401 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/cpptoc/stream_writer_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_drag_data_t* cef_drag_data_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefDragData::Create(); + + // Return type: refptr_same + return CefDragDataCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +struct _cef_drag_data_t* CEF_CALLBACK drag_data_clone( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefDragDataCppToC::Get(self)->Clone(); + + // Return type: refptr_same + return CefDragDataCppToC::Wrap(_retval); +} + +int CEF_CALLBACK drag_data_is_read_only(struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDragDataCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK drag_data_is_link(struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDragDataCppToC::Get(self)->IsLink(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK drag_data_is_fragment(struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDragDataCppToC::Get(self)->IsFragment(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK drag_data_is_file(struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefDragDataCppToC::Get(self)->IsFile(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_link_url( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetLinkURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_link_title( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetLinkTitle(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_link_metadata( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetLinkMetadata(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_fragment_text( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentText(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_fragment_html( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentHtml(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_fragment_base_url( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetFragmentBaseURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK drag_data_get_file_name( + struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefDragDataCppToC::Get(self)->GetFileName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +size_t CEF_CALLBACK drag_data_get_file_contents(struct _cef_drag_data_t* self, + struct _cef_stream_writer_t* writer) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: writer + + // Execute + size_t _retval = CefDragDataCppToC::Get(self)->GetFileContents( + CefStreamWriterCppToC::Unwrap(writer)); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK drag_data_get_file_names(struct _cef_drag_data_t* self, + cef_string_list_t names) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: names; type: string_vec_byref + DCHECK(names); + if (!names) + return 0; + + // Translate param: names; type: string_vec_byref + std::vector namesList; + transfer_string_list_contents(names, namesList); + + // Execute + bool _retval = CefDragDataCppToC::Get(self)->GetFileNames( + namesList); + + // Restore param: names; type: string_vec_byref + cef_string_list_clear(names); + transfer_string_list_contents(namesList, names); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK drag_data_set_link_url(struct _cef_drag_data_t* self, + const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: url + + // Execute + CefDragDataCppToC::Get(self)->SetLinkURL( + CefString(url)); +} + +void CEF_CALLBACK drag_data_set_link_title(struct _cef_drag_data_t* self, + const cef_string_t* title) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: title + + // Execute + CefDragDataCppToC::Get(self)->SetLinkTitle( + CefString(title)); +} + +void CEF_CALLBACK drag_data_set_link_metadata(struct _cef_drag_data_t* self, + const cef_string_t* data) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: data + + // Execute + CefDragDataCppToC::Get(self)->SetLinkMetadata( + CefString(data)); +} + +void CEF_CALLBACK drag_data_set_fragment_text(struct _cef_drag_data_t* self, + const cef_string_t* text) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: text + + // Execute + CefDragDataCppToC::Get(self)->SetFragmentText( + CefString(text)); +} + +void CEF_CALLBACK drag_data_set_fragment_html(struct _cef_drag_data_t* self, + const cef_string_t* html) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: html + + // Execute + CefDragDataCppToC::Get(self)->SetFragmentHtml( + CefString(html)); +} + +void CEF_CALLBACK drag_data_set_fragment_base_url(struct _cef_drag_data_t* self, + const cef_string_t* base_url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: base_url + + // Execute + CefDragDataCppToC::Get(self)->SetFragmentBaseURL( + CefString(base_url)); +} + +void CEF_CALLBACK drag_data_reset_file_contents(struct _cef_drag_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefDragDataCppToC::Get(self)->ResetFileContents(); +} + +void CEF_CALLBACK drag_data_add_file(struct _cef_drag_data_t* self, + const cef_string_t* path, const cef_string_t* display_name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + // Unverified params: display_name + + // Execute + CefDragDataCppToC::Get(self)->AddFile( + CefString(path), + CefString(display_name)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDragDataCppToC::CefDragDataCppToC(CefDragData* cls) + : CefCppToC(cls) { + struct_.struct_.clone = drag_data_clone; + struct_.struct_.is_read_only = drag_data_is_read_only; + struct_.struct_.is_link = drag_data_is_link; + struct_.struct_.is_fragment = drag_data_is_fragment; + struct_.struct_.is_file = drag_data_is_file; + struct_.struct_.get_link_url = drag_data_get_link_url; + struct_.struct_.get_link_title = drag_data_get_link_title; + struct_.struct_.get_link_metadata = drag_data_get_link_metadata; + struct_.struct_.get_fragment_text = drag_data_get_fragment_text; + struct_.struct_.get_fragment_html = drag_data_get_fragment_html; + struct_.struct_.get_fragment_base_url = drag_data_get_fragment_base_url; + struct_.struct_.get_file_name = drag_data_get_file_name; + struct_.struct_.get_file_contents = drag_data_get_file_contents; + struct_.struct_.get_file_names = drag_data_get_file_names; + struct_.struct_.set_link_url = drag_data_set_link_url; + struct_.struct_.set_link_title = drag_data_set_link_title; + struct_.struct_.set_link_metadata = drag_data_set_link_metadata; + struct_.struct_.set_fragment_text = drag_data_set_fragment_text; + struct_.struct_.set_fragment_html = drag_data_set_fragment_html; + struct_.struct_.set_fragment_base_url = drag_data_set_fragment_base_url; + struct_.struct_.reset_file_contents = drag_data_reset_file_contents; + struct_.struct_.add_file = drag_data_add_file; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/drag_data_cpptoc.h b/libcef_dll/cpptoc/drag_data_cpptoc.h new file mode 100644 index 000000000..2fe9fe2e0 --- /dev/null +++ b/libcef_dll/cpptoc/drag_data_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DRAG_DATA_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DRAG_DATA_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_drag_data.h" +#include "include/capi/cef_drag_data_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefDragDataCppToC + : public CefCppToC { + public: + explicit CefDragDataCppToC(CefDragData* cls); + virtual ~CefDragDataCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DRAG_DATA_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/drag_handler_cpptoc.cc b/libcef_dll/cpptoc/drag_handler_cpptoc.cc new file mode 100644 index 000000000..35a67ef9d --- /dev/null +++ b/libcef_dll/cpptoc/drag_handler_cpptoc.cc @@ -0,0 +1,59 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/drag_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/drag_data_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK drag_handler_on_drag_enter(struct _cef_drag_handler_t* self, + cef_browser_t* browser, cef_drag_data_t* dragData, + cef_drag_operations_mask_t mask) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: dragData; type: refptr_diff + DCHECK(dragData); + if (!dragData) + return 0; + + // Execute + bool _retval = CefDragHandlerCppToC::Get(self)->OnDragEnter( + CefBrowserCToCpp::Wrap(browser), + CefDragDataCToCpp::Wrap(dragData), + mask); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDragHandlerCppToC::CefDragHandlerCppToC(CefDragHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_drag_enter = drag_handler_on_drag_enter; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/drag_handler_cpptoc.h b/libcef_dll/cpptoc/drag_handler_cpptoc.h new file mode 100644 index 000000000..91aee16e4 --- /dev/null +++ b/libcef_dll/cpptoc/drag_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DRAG_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DRAG_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_drag_handler.h" +#include "include/capi/cef_drag_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDragHandlerCppToC + : public CefCppToC { + public: + explicit CefDragHandlerCppToC(CefDragHandler* cls); + virtual ~CefDragHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DRAG_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc new file mode 100644 index 000000000..5fced58ce --- /dev/null +++ b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.cc @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/end_tracing_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK end_tracing_callback_on_end_tracing_complete( + struct _cef_end_tracing_callback_t* self, + const cef_string_t* tracing_file) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: tracing_file; type: string_byref_const + DCHECK(tracing_file); + if (!tracing_file) + return; + + // Execute + CefEndTracingCallbackCppToC::Get(self)->OnEndTracingComplete( + CefString(tracing_file)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefEndTracingCallbackCppToC::CefEndTracingCallbackCppToC( + CefEndTracingCallback* cls) + : CefCppToC(cls) { + struct_.struct_.on_end_tracing_complete = + end_tracing_callback_on_end_tracing_complete; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.h new file mode 100644 index 000000000..6e0f4aade --- /dev/null +++ b/libcef_dll/cpptoc/end_tracing_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_END_TRACING_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_END_TRACING_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_trace.h" +#include "include/capi/cef_trace_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefEndTracingCallbackCppToC + : public CefCppToC { + public: + explicit CefEndTracingCallbackCppToC(CefEndTracingCallback* cls); + virtual ~CefEndTracingCallbackCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_END_TRACING_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc new file mode 100644 index 000000000..bbf81be04 --- /dev/null +++ b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.cc @@ -0,0 +1,67 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK file_dialog_callback_cont( + struct _cef_file_dialog_callback_t* self, cef_string_list_t file_paths) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: file_paths; type: string_vec_byref_const + DCHECK(file_paths); + if (!file_paths) + return; + + // Translate param: file_paths; type: string_vec_byref_const + std::vector file_pathsList; + transfer_string_list_contents(file_paths, file_pathsList); + + // Execute + CefFileDialogCallbackCppToC::Get(self)->Continue( + file_pathsList); +} + +void CEF_CALLBACK file_dialog_callback_cancel( + struct _cef_file_dialog_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFileDialogCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefFileDialogCallbackCppToC::CefFileDialogCallbackCppToC( + CefFileDialogCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = file_dialog_callback_cont; + struct_.struct_.cancel = file_dialog_callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.h new file mode 100644 index 000000000..b2adbc696 --- /dev/null +++ b/libcef_dll/cpptoc/file_dialog_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dialog_handler.h" +#include "include/capi/cef_dialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefFileDialogCallbackCppToC + : public CefCppToC { + public: + explicit CefFileDialogCallbackCppToC(CefFileDialogCallback* cls); + virtual ~CefFileDialogCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_FILE_DIALOG_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/focus_handler_cpptoc.cc b/libcef_dll/cpptoc/focus_handler_cpptoc.cc new file mode 100644 index 000000000..9276afcbd --- /dev/null +++ b/libcef_dll/cpptoc/focus_handler_cpptoc.cc @@ -0,0 +1,90 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/focus_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK focus_handler_on_take_focus(struct _cef_focus_handler_t* self, + cef_browser_t* browser, int next) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefFocusHandlerCppToC::Get(self)->OnTakeFocus( + CefBrowserCToCpp::Wrap(browser), + next?true:false); +} + +int CEF_CALLBACK focus_handler_on_set_focus(struct _cef_focus_handler_t* self, + cef_browser_t* browser, cef_focus_source_t source) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + + // Execute + bool _retval = CefFocusHandlerCppToC::Get(self)->OnSetFocus( + CefBrowserCToCpp::Wrap(browser), + source); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK focus_handler_on_got_focus(struct _cef_focus_handler_t* self, + cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefFocusHandlerCppToC::Get(self)->OnGotFocus( + CefBrowserCToCpp::Wrap(browser)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefFocusHandlerCppToC::CefFocusHandlerCppToC(CefFocusHandler* cls) + : CefCppToC( + cls) { + struct_.struct_.on_take_focus = focus_handler_on_take_focus; + struct_.struct_.on_set_focus = focus_handler_on_set_focus; + struct_.struct_.on_got_focus = focus_handler_on_got_focus; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/focus_handler_cpptoc.h b/libcef_dll/cpptoc/focus_handler_cpptoc.h new file mode 100644 index 000000000..96734c863 --- /dev/null +++ b/libcef_dll/cpptoc/focus_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_FOCUS_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_FOCUS_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_focus_handler.h" +#include "include/capi/cef_focus_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefFocusHandlerCppToC + : public CefCppToC { + public: + explicit CefFocusHandlerCppToC(CefFocusHandler* cls); + virtual ~CefFocusHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_FOCUS_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/frame_cpptoc.cc b/libcef_dll/cpptoc/frame_cpptoc.cc new file mode 100644 index 000000000..048e1a178 --- /dev/null +++ b/libcef_dll/cpptoc/frame_cpptoc.cc @@ -0,0 +1,401 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/v8context_cpptoc.h" +#include "libcef_dll/ctocpp/domvisitor_ctocpp.h" +#include "libcef_dll/ctocpp/string_visitor_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK frame_is_valid(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefFrameCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK frame_undo(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Undo(); +} + +void CEF_CALLBACK frame_redo(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Redo(); +} + +void CEF_CALLBACK frame_cut(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Cut(); +} + +void CEF_CALLBACK frame_copy(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Copy(); +} + +void CEF_CALLBACK frame_paste(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Paste(); +} + +void CEF_CALLBACK frame_del(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->Delete(); +} + +void CEF_CALLBACK frame_select_all(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->SelectAll(); +} + +void CEF_CALLBACK frame_view_source(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefFrameCppToC::Get(self)->ViewSource(); +} + +void CEF_CALLBACK frame_get_source(struct _cef_frame_t* self, + struct _cef_string_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return; + + // Execute + CefFrameCppToC::Get(self)->GetSource( + CefStringVisitorCToCpp::Wrap(visitor)); +} + +void CEF_CALLBACK frame_get_text(struct _cef_frame_t* self, + struct _cef_string_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return; + + // Execute + CefFrameCppToC::Get(self)->GetText( + CefStringVisitorCToCpp::Wrap(visitor)); +} + +void CEF_CALLBACK frame_load_request(struct _cef_frame_t* self, + struct _cef_request_t* request) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: request; type: refptr_same + DCHECK(request); + if (!request) + return; + + // Execute + CefFrameCppToC::Get(self)->LoadRequest( + CefRequestCppToC::Unwrap(request)); +} + +void CEF_CALLBACK frame_load_url(struct _cef_frame_t* self, + const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefFrameCppToC::Get(self)->LoadURL( + CefString(url)); +} + +void CEF_CALLBACK frame_load_string(struct _cef_frame_t* self, + const cef_string_t* string_val, const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: string_val; type: string_byref_const + DCHECK(string_val); + if (!string_val) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefFrameCppToC::Get(self)->LoadString( + CefString(string_val), + CefString(url)); +} + +void CEF_CALLBACK frame_execute_java_script(struct _cef_frame_t* self, + const cef_string_t* code, const cef_string_t* script_url, + int start_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: code; type: string_byref_const + DCHECK(code); + if (!code) + return; + // Unverified params: script_url + + // Execute + CefFrameCppToC::Get(self)->ExecuteJavaScript( + CefString(code), + CefString(script_url), + start_line); +} + +int CEF_CALLBACK frame_is_main(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefFrameCppToC::Get(self)->IsMain(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK frame_is_focused(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefFrameCppToC::Get(self)->IsFocused(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK frame_get_name(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefFrameCppToC::Get(self)->GetName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int64 CEF_CALLBACK frame_get_identifier(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefFrameCppToC::Get(self)->GetIdentifier(); + + // Return type: simple + return _retval; +} + +struct _cef_frame_t* CEF_CALLBACK frame_get_parent(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefFrameCppToC::Get(self)->GetParent(); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +cef_string_userfree_t CEF_CALLBACK frame_get_url(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefFrameCppToC::Get(self)->GetURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_browser_t* CEF_CALLBACK frame_get_browser(struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefFrameCppToC::Get(self)->GetBrowser(); + + // Return type: refptr_same + return CefBrowserCppToC::Wrap(_retval); +} + +struct _cef_v8context_t* CEF_CALLBACK frame_get_v8context( + struct _cef_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefFrameCppToC::Get(self)->GetV8Context(); + + // Return type: refptr_same + return CefV8ContextCppToC::Wrap(_retval); +} + +void CEF_CALLBACK frame_visit_dom(struct _cef_frame_t* self, + cef_domvisitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return; + + // Execute + CefFrameCppToC::Get(self)->VisitDOM( + CefDOMVisitorCToCpp::Wrap(visitor)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefFrameCppToC::CefFrameCppToC(CefFrame* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = frame_is_valid; + struct_.struct_.undo = frame_undo; + struct_.struct_.redo = frame_redo; + struct_.struct_.cut = frame_cut; + struct_.struct_.copy = frame_copy; + struct_.struct_.paste = frame_paste; + struct_.struct_.del = frame_del; + struct_.struct_.select_all = frame_select_all; + struct_.struct_.view_source = frame_view_source; + struct_.struct_.get_source = frame_get_source; + struct_.struct_.get_text = frame_get_text; + struct_.struct_.load_request = frame_load_request; + struct_.struct_.load_url = frame_load_url; + struct_.struct_.load_string = frame_load_string; + struct_.struct_.execute_java_script = frame_execute_java_script; + struct_.struct_.is_main = frame_is_main; + struct_.struct_.is_focused = frame_is_focused; + struct_.struct_.get_name = frame_get_name; + struct_.struct_.get_identifier = frame_get_identifier; + struct_.struct_.get_parent = frame_get_parent; + struct_.struct_.get_url = frame_get_url; + struct_.struct_.get_browser = frame_get_browser; + struct_.struct_.get_v8context = frame_get_v8context; + struct_.struct_.visit_dom = frame_visit_dom; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/frame_cpptoc.h b/libcef_dll/cpptoc/frame_cpptoc.h new file mode 100644 index 000000000..8a5f6ca1c --- /dev/null +++ b/libcef_dll/cpptoc/frame_cpptoc.h @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_FRAME_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_FRAME_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_frame.h" +#include "include/capi/cef_frame_capi.h" +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefFrameCppToC + : public CefCppToC { + public: + explicit CefFrameCppToC(CefFrame* cls); + virtual ~CefFrameCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_FRAME_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc b/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc new file mode 100644 index 000000000..2c6ed6d73 --- /dev/null +++ b/libcef_dll/cpptoc/geolocation_callback_cpptoc.cc @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/geolocation_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK geolocation_callback_cont( + struct _cef_geolocation_callback_t* self, int allow) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefGeolocationCallbackCppToC::Get(self)->Continue( + allow?true:false); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefGeolocationCallbackCppToC::CefGeolocationCallbackCppToC( + CefGeolocationCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = geolocation_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/geolocation_callback_cpptoc.h b/libcef_dll/cpptoc/geolocation_callback_cpptoc.h new file mode 100644 index 000000000..23b3248d8 --- /dev/null +++ b/libcef_dll/cpptoc/geolocation_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_geolocation_handler.h" +#include "include/capi/cef_geolocation_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefGeolocationCallbackCppToC + : public CefCppToC { + public: + explicit CefGeolocationCallbackCppToC(CefGeolocationCallback* cls); + virtual ~CefGeolocationCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc b/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc new file mode 100644 index 000000000..1983aec2f --- /dev/null +++ b/libcef_dll/cpptoc/geolocation_handler_cpptoc.cc @@ -0,0 +1,95 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/geolocation_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/geolocation_callback_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK geolocation_handler_on_request_geolocation_permission( + struct _cef_geolocation_handler_t* self, cef_browser_t* browser, + const cef_string_t* requesting_url, int request_id, + cef_geolocation_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: requesting_url; type: string_byref_const + DCHECK(requesting_url); + if (!requesting_url) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefGeolocationHandlerCppToC::Get( + self)->OnRequestGeolocationPermission( + CefBrowserCToCpp::Wrap(browser), + CefString(requesting_url), + request_id, + CefGeolocationCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK geolocation_handler_on_cancel_geolocation_permission( + struct _cef_geolocation_handler_t* self, cef_browser_t* browser, + const cef_string_t* requesting_url, int request_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: requesting_url; type: string_byref_const + DCHECK(requesting_url); + if (!requesting_url) + return; + + // Execute + CefGeolocationHandlerCppToC::Get(self)->OnCancelGeolocationPermission( + CefBrowserCToCpp::Wrap(browser), + CefString(requesting_url), + request_id); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefGeolocationHandlerCppToC::CefGeolocationHandlerCppToC( + CefGeolocationHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_request_geolocation_permission = + geolocation_handler_on_request_geolocation_permission; + struct_.struct_.on_cancel_geolocation_permission = + geolocation_handler_on_cancel_geolocation_permission; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/geolocation_handler_cpptoc.h b/libcef_dll/cpptoc/geolocation_handler_cpptoc.h new file mode 100644 index 000000000..a82ad420b --- /dev/null +++ b/libcef_dll/cpptoc/geolocation_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_geolocation_handler.h" +#include "include/capi/cef_geolocation_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefGeolocationHandlerCppToC + : public CefCppToC { + public: + explicit CefGeolocationHandlerCppToC(CefGeolocationHandler* cls); + virtual ~CefGeolocationHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_GEOLOCATION_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc new file mode 100644 index 000000000..8036c6008 --- /dev/null +++ b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.cc @@ -0,0 +1,57 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/get_geolocation_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK get_geolocation_callback_on_location_update( + struct _cef_get_geolocation_callback_t* self, + const struct _cef_geoposition_t* position) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: position; type: struct_byref_const + DCHECK(position); + if (!position) + return; + + // Translate param: position; type: struct_byref_const + CefGeoposition positionObj; + if (position) + positionObj.Set(*position, false); + + // Execute + CefGetGeolocationCallbackCppToC::Get(self)->OnLocationUpdate( + positionObj); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefGetGeolocationCallbackCppToC::CefGetGeolocationCallbackCppToC( + CefGetGeolocationCallback* cls) + : CefCppToC(cls) { + struct_.struct_.on_location_update = + get_geolocation_callback_on_location_update; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = + 0; +#endif + diff --git a/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.h b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.h new file mode 100644 index 000000000..30d03775a --- /dev/null +++ b/libcef_dll/cpptoc/get_geolocation_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_GET_GEOLOCATION_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_GET_GEOLOCATION_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_geolocation.h" +#include "include/capi/cef_geolocation_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefGetGeolocationCallbackCppToC + : public CefCppToC { + public: + explicit CefGetGeolocationCallbackCppToC(CefGetGeolocationCallback* cls); + virtual ~CefGetGeolocationCallbackCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_GET_GEOLOCATION_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc new file mode 100644 index 000000000..ab0471b6a --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK jsdialog_callback_cont(struct _cef_jsdialog_callback_t* self, + int success, const cef_string_t* user_input) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: user_input + + // Execute + CefJSDialogCallbackCppToC::Get(self)->Continue( + success?true:false, + CefString(user_input)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefJSDialogCallbackCppToC::CefJSDialogCallbackCppToC(CefJSDialogCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = jsdialog_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h new file mode 100644 index 000000000..1f4561658 --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefJSDialogCallbackCppToC + : public CefCppToC { + public: + explicit CefJSDialogCallbackCppToC(CefJSDialogCallback* cls); + virtual ~CefJSDialogCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc new file mode 100644 index 000000000..a0b835392 --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc @@ -0,0 +1,151 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK jsdialog_handler_on_jsdialog( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser, + const cef_string_t* origin_url, const cef_string_t* accept_lang, + cef_jsdialog_type_t dialog_type, const cef_string_t* message_text, + const cef_string_t* default_prompt_text, cef_jsdialog_callback_t* callback, + int* suppress_message) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Verify param: suppress_message; type: bool_byref + DCHECK(suppress_message); + if (!suppress_message) + return 0; + // Unverified params: origin_url, accept_lang, message_text, + // default_prompt_text + + // Translate param: suppress_message; type: bool_byref + bool suppress_messageBool = ( + suppress_message && *suppress_message)?true:false; + + // Execute + bool _retval = CefJSDialogHandlerCppToC::Get(self)->OnJSDialog( + CefBrowserCToCpp::Wrap(browser), + CefString(origin_url), + CefString(accept_lang), + dialog_type, + CefString(message_text), + CefString(default_prompt_text), + CefJSDialogCallbackCToCpp::Wrap(callback), + suppress_messageBool); + + // Restore param: suppress_message; type: bool_byref + if (suppress_message) + *suppress_message = suppress_messageBool?true:false; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK jsdialog_handler_on_before_unload_dialog( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser, + const cef_string_t* message_text, int is_reload, + cef_jsdialog_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Unverified params: message_text + + // Execute + bool _retval = CefJSDialogHandlerCppToC::Get(self)->OnBeforeUnloadDialog( + CefBrowserCToCpp::Wrap(browser), + CefString(message_text), + is_reload?true:false, + CefJSDialogCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK jsdialog_handler_on_reset_dialog_state( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefJSDialogHandlerCppToC::Get(self)->OnResetDialogState( + CefBrowserCToCpp::Wrap(browser)); +} + +void CEF_CALLBACK jsdialog_handler_on_dialog_closed( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefJSDialogHandlerCppToC::Get(self)->OnDialogClosed( + CefBrowserCToCpp::Wrap(browser)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefJSDialogHandlerCppToC::CefJSDialogHandlerCppToC(CefJSDialogHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_jsdialog = jsdialog_handler_on_jsdialog; + struct_.struct_.on_before_unload_dialog = + jsdialog_handler_on_before_unload_dialog; + struct_.struct_.on_reset_dialog_state = + jsdialog_handler_on_reset_dialog_state; + struct_.struct_.on_dialog_closed = jsdialog_handler_on_dialog_closed; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h new file mode 100644 index 000000000..0097c80d3 --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefJSDialogHandlerCppToC + : public CefCppToC { + public: + explicit CefJSDialogHandlerCppToC(CefJSDialogHandler* cls); + virtual ~CefJSDialogHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc b/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc new file mode 100644 index 000000000..a8822f10c --- /dev/null +++ b/libcef_dll/cpptoc/keyboard_handler_cpptoc.cc @@ -0,0 +1,110 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK keyboard_handler_on_pre_key_event( + struct _cef_keyboard_handler_t* self, cef_browser_t* browser, + const struct _cef_key_event_t* event, cef_event_handle_t os_event, + int* is_keyboard_shortcut) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return 0; + // Verify param: is_keyboard_shortcut; type: bool_byaddr + DCHECK(is_keyboard_shortcut); + if (!is_keyboard_shortcut) + return 0; + + // Translate param: event; type: struct_byref_const + CefKeyEvent eventObj; + if (event) + eventObj.Set(*event, false); + // Translate param: is_keyboard_shortcut; type: bool_byaddr + bool is_keyboard_shortcutBool = ( + is_keyboard_shortcut && *is_keyboard_shortcut)?true:false; + + // Execute + bool _retval = CefKeyboardHandlerCppToC::Get(self)->OnPreKeyEvent( + CefBrowserCToCpp::Wrap(browser), + eventObj, + os_event, + &is_keyboard_shortcutBool); + + // Restore param: is_keyboard_shortcut; type: bool_byaddr + if (is_keyboard_shortcut) + *is_keyboard_shortcut = is_keyboard_shortcutBool?true:false; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK keyboard_handler_on_key_event( + struct _cef_keyboard_handler_t* self, cef_browser_t* browser, + const struct _cef_key_event_t* event, cef_event_handle_t os_event) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return 0; + + // Translate param: event; type: struct_byref_const + CefKeyEvent eventObj; + if (event) + eventObj.Set(*event, false); + + // Execute + bool _retval = CefKeyboardHandlerCppToC::Get(self)->OnKeyEvent( + CefBrowserCToCpp::Wrap(browser), + eventObj, + os_event); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefKeyboardHandlerCppToC::CefKeyboardHandlerCppToC(CefKeyboardHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_pre_key_event = keyboard_handler_on_pre_key_event; + struct_.struct_.on_key_event = keyboard_handler_on_key_event; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/keyboard_handler_cpptoc.h b/libcef_dll/cpptoc/keyboard_handler_cpptoc.h new file mode 100644 index 000000000..bb861b6c7 --- /dev/null +++ b/libcef_dll/cpptoc/keyboard_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_KEYBOARD_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_KEYBOARD_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_keyboard_handler.h" +#include "include/capi/cef_keyboard_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefKeyboardHandlerCppToC + : public CefCppToC { + public: + explicit CefKeyboardHandlerCppToC(CefKeyboardHandler* cls); + virtual ~CefKeyboardHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_KEYBOARD_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/life_span_handler_cpptoc.cc b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc new file mode 100644 index 000000000..d7ee3e68c --- /dev/null +++ b/libcef_dll/cpptoc/life_span_handler_cpptoc.cc @@ -0,0 +1,211 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/client_cpptoc.h" +#include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK life_span_handler_on_before_popup( + struct _cef_life_span_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, const cef_string_t* target_url, + const cef_string_t* target_frame_name, + const struct _cef_popup_features_t* popupFeatures, + cef_window_info_t* windowInfo, cef_client_t** client, + struct _cef_browser_settings_t* settings, int* no_javascript_access) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: popupFeatures; type: struct_byref_const + DCHECK(popupFeatures); + if (!popupFeatures) + return 0; + // Verify param: windowInfo; type: struct_byref + DCHECK(windowInfo); + if (!windowInfo) + return 0; + // Verify param: client; type: refptr_same_byref + DCHECK(client); + if (!client) + return 0; + // Verify param: settings; type: struct_byref + DCHECK(settings); + if (!settings) + return 0; + // Verify param: no_javascript_access; type: bool_byaddr + DCHECK(no_javascript_access); + if (!no_javascript_access) + return 0; + // Unverified params: target_url, target_frame_name + + // Translate param: popupFeatures; type: struct_byref_const + CefPopupFeatures popupFeaturesObj; + if (popupFeatures) + popupFeaturesObj.Set(*popupFeatures, false); + // Translate param: windowInfo; type: struct_byref + CefWindowInfo windowInfoObj; + if (windowInfo) + windowInfoObj.AttachTo(*windowInfo); + // Translate param: client; type: refptr_same_byref + CefRefPtr clientPtr; + if (client && *client) + clientPtr = CefClientCppToC::Unwrap(*client); + CefClient* clientOrig = clientPtr.get(); + // Translate param: settings; type: struct_byref + CefBrowserSettings settingsObj; + if (settings) + settingsObj.AttachTo(*settings); + // Translate param: no_javascript_access; type: bool_byaddr + bool no_javascript_accessBool = ( + no_javascript_access && *no_javascript_access)?true:false; + + // Execute + bool _retval = CefLifeSpanHandlerCppToC::Get(self)->OnBeforePopup( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefString(target_url), + CefString(target_frame_name), + popupFeaturesObj, + windowInfoObj, + clientPtr, + settingsObj, + &no_javascript_accessBool); + + // Restore param: windowInfo; type: struct_byref + if (windowInfo) + windowInfoObj.DetachTo(*windowInfo); + // Restore param: client; type: refptr_same_byref + if (client) { + if (clientPtr.get()) { + if (clientPtr.get() != clientOrig) { + *client = CefClientCppToC::Wrap(clientPtr); + } + } else { + *client = NULL; + } + } + // Restore param: settings; type: struct_byref + if (settings) + settingsObj.DetachTo(*settings); + // Restore param: no_javascript_access; type: bool_byaddr + if (no_javascript_access) + *no_javascript_access = no_javascript_accessBool?true:false; + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK life_span_handler_on_after_created( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefLifeSpanHandlerCppToC::Get(self)->OnAfterCreated( + CefBrowserCToCpp::Wrap(browser)); +} + +int CEF_CALLBACK life_span_handler_run_modal( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + + // Execute + bool _retval = CefLifeSpanHandlerCppToC::Get(self)->RunModal( + CefBrowserCToCpp::Wrap(browser)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK life_span_handler_do_close( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + + // Execute + bool _retval = CefLifeSpanHandlerCppToC::Get(self)->DoClose( + CefBrowserCToCpp::Wrap(browser)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK life_span_handler_on_before_close( + struct _cef_life_span_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefLifeSpanHandlerCppToC::Get(self)->OnBeforeClose( + CefBrowserCToCpp::Wrap(browser)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefLifeSpanHandlerCppToC::CefLifeSpanHandlerCppToC(CefLifeSpanHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_popup = life_span_handler_on_before_popup; + struct_.struct_.on_after_created = life_span_handler_on_after_created; + struct_.struct_.run_modal = life_span_handler_run_modal; + struct_.struct_.do_close = life_span_handler_do_close; + struct_.struct_.on_before_close = life_span_handler_on_before_close; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/life_span_handler_cpptoc.h b/libcef_dll/cpptoc/life_span_handler_cpptoc.h new file mode 100644 index 000000000..01021dca6 --- /dev/null +++ b/libcef_dll/cpptoc/life_span_handler_cpptoc.h @@ -0,0 +1,39 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_LIFE_SPAN_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_LIFE_SPAN_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_life_span_handler.h" +#include "include/capi/cef_life_span_handler_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefLifeSpanHandlerCppToC + : public CefCppToC { + public: + explicit CefLifeSpanHandlerCppToC(CefLifeSpanHandler* cls); + virtual ~CefLifeSpanHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_LIFE_SPAN_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/list_value_cpptoc.cc b/libcef_dll/cpptoc/list_value_cpptoc.cc new file mode 100644 index 000000000..638bcad11 --- /dev/null +++ b/libcef_dll/cpptoc/list_value_cpptoc.cc @@ -0,0 +1,528 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/binary_value_cpptoc.h" +#include "libcef_dll/cpptoc/dictionary_value_cpptoc.h" +#include "libcef_dll/cpptoc/list_value_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_list_value_t* cef_list_value_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefListValue::Create(); + + // Return type: refptr_same + return CefListValueCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK list_value_is_valid(struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_is_owned(struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->IsOwned(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_is_read_only(struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +struct _cef_list_value_t* CEF_CALLBACK list_value_copy( + struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefListValueCppToC::Get(self)->Copy(); + + // Return type: refptr_same + return CefListValueCppToC::Wrap(_retval); +} + +int CEF_CALLBACK list_value_set_size(struct _cef_list_value_t* self, + size_t size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetSize( + size); + + // Return type: bool + return _retval; +} + +size_t CEF_CALLBACK list_value_get_size(struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefListValueCppToC::Get(self)->GetSize(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK list_value_clear(struct _cef_list_value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->Clear(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_remove(struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->Remove( + index); + + // Return type: bool + return _retval; +} + +cef_value_type_t CEF_CALLBACK list_value_get_type( + struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return VTYPE_INVALID; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return VTYPE_INVALID; + + // Execute + cef_value_type_t _retval = CefListValueCppToC::Get(self)->GetType( + index); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK list_value_get_bool(struct _cef_list_value_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->GetBool( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_get_int(struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + int _retval = CefListValueCppToC::Get(self)->GetInt( + index); + + // Return type: simple + return _retval; +} + +double CEF_CALLBACK list_value_get_double(struct _cef_list_value_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + double _retval = CefListValueCppToC::Get(self)->GetDouble( + index); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK list_value_get_string( + struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefString _retval = CefListValueCppToC::Get(self)->GetString( + index); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_binary_value_t* CEF_CALLBACK list_value_get_binary( + struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefRefPtr _retval = CefListValueCppToC::Get(self)->GetBinary( + index); + + // Return type: refptr_same + return CefBinaryValueCppToC::Wrap(_retval); +} + +cef_dictionary_value_t* CEF_CALLBACK list_value_get_dictionary( + struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefRefPtr _retval = CefListValueCppToC::Get( + self)->GetDictionary( + index); + + // Return type: refptr_same + return CefDictionaryValueCppToC::Wrap(_retval); +} + +struct _cef_list_value_t* CEF_CALLBACK list_value_get_list( + struct _cef_list_value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefRefPtr _retval = CefListValueCppToC::Get(self)->GetList( + index); + + // Return type: refptr_same + return CefListValueCppToC::Wrap(_retval); +} + +int CEF_CALLBACK list_value_set_null(struct _cef_list_value_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetNull( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_bool(struct _cef_list_value_t* self, int index, + int value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetBool( + index, + value?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_int(struct _cef_list_value_t* self, int index, + int value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetInt( + index, + value); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_double(struct _cef_list_value_t* self, + int index, double value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetDouble( + index, + value); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_string(struct _cef_list_value_t* self, + int index, const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + // Unverified params: value + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetString( + index, + CefString(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_binary(struct _cef_list_value_t* self, + int index, cef_binary_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetBinary( + index, + CefBinaryValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_dictionary(struct _cef_list_value_t* self, + int index, cef_dictionary_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetDictionary( + index, + CefDictionaryValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK list_value_set_list(struct _cef_list_value_t* self, int index, + struct _cef_list_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefListValueCppToC::Get(self)->SetList( + index, + CefListValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefListValueCppToC::CefListValueCppToC(CefListValue* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = list_value_is_valid; + struct_.struct_.is_owned = list_value_is_owned; + struct_.struct_.is_read_only = list_value_is_read_only; + struct_.struct_.copy = list_value_copy; + struct_.struct_.set_size = list_value_set_size; + struct_.struct_.get_size = list_value_get_size; + struct_.struct_.clear = list_value_clear; + struct_.struct_.remove = list_value_remove; + struct_.struct_.get_type = list_value_get_type; + struct_.struct_.get_bool = list_value_get_bool; + struct_.struct_.get_int = list_value_get_int; + struct_.struct_.get_double = list_value_get_double; + struct_.struct_.get_string = list_value_get_string; + struct_.struct_.get_binary = list_value_get_binary; + struct_.struct_.get_dictionary = list_value_get_dictionary; + struct_.struct_.get_list = list_value_get_list; + struct_.struct_.set_null = list_value_set_null; + struct_.struct_.set_bool = list_value_set_bool; + struct_.struct_.set_int = list_value_set_int; + struct_.struct_.set_double = list_value_set_double; + struct_.struct_.set_string = list_value_set_string; + struct_.struct_.set_binary = list_value_set_binary; + struct_.struct_.set_dictionary = list_value_set_dictionary; + struct_.struct_.set_list = list_value_set_list; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/list_value_cpptoc.h b/libcef_dll/cpptoc/list_value_cpptoc.h new file mode 100644 index 000000000..9ce7d2748 --- /dev/null +++ b/libcef_dll/cpptoc/list_value_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_LIST_VALUE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_LIST_VALUE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefListValueCppToC + : public CefCppToC { + public: + explicit CefListValueCppToC(CefListValue* cls); + virtual ~CefListValueCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_LIST_VALUE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/load_handler_cpptoc.cc b/libcef_dll/cpptoc/load_handler_cpptoc.cc new file mode 100644 index 000000000..e3829f23f --- /dev/null +++ b/libcef_dll/cpptoc/load_handler_cpptoc.cc @@ -0,0 +1,133 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/load_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK load_handler_on_loading_state_change( + struct _cef_load_handler_t* self, cef_browser_t* browser, int isLoading, + int canGoBack, int canGoForward) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefLoadHandlerCppToC::Get(self)->OnLoadingStateChange( + CefBrowserCToCpp::Wrap(browser), + isLoading?true:false, + canGoBack?true:false, + canGoForward?true:false); +} + +void CEF_CALLBACK load_handler_on_load_start(struct _cef_load_handler_t* self, + cef_browser_t* browser, cef_frame_t* frame) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + + // Execute + CefLoadHandlerCppToC::Get(self)->OnLoadStart( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame)); +} + +void CEF_CALLBACK load_handler_on_load_end(struct _cef_load_handler_t* self, + cef_browser_t* browser, cef_frame_t* frame, int httpStatusCode) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + + // Execute + CefLoadHandlerCppToC::Get(self)->OnLoadEnd( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + httpStatusCode); +} + +void CEF_CALLBACK load_handler_on_load_error(struct _cef_load_handler_t* self, + cef_browser_t* browser, cef_frame_t* frame, cef_errorcode_t errorCode, + const cef_string_t* errorText, const cef_string_t* failedUrl) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: failedUrl; type: string_byref_const + DCHECK(failedUrl); + if (!failedUrl) + return; + // Unverified params: errorText + + // Execute + CefLoadHandlerCppToC::Get(self)->OnLoadError( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + errorCode, + CefString(errorText), + CefString(failedUrl)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefLoadHandlerCppToC::CefLoadHandlerCppToC(CefLoadHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_loading_state_change = + load_handler_on_loading_state_change; + struct_.struct_.on_load_start = load_handler_on_load_start; + struct_.struct_.on_load_end = load_handler_on_load_end; + struct_.struct_.on_load_error = load_handler_on_load_error; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/load_handler_cpptoc.h b/libcef_dll/cpptoc/load_handler_cpptoc.h new file mode 100644 index 000000000..b17f33e84 --- /dev/null +++ b/libcef_dll/cpptoc/load_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_LOAD_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_LOAD_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_load_handler.h" +#include "include/capi/cef_load_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefLoadHandlerCppToC + : public CefCppToC { + public: + explicit CefLoadHandlerCppToC(CefLoadHandler* cls); + virtual ~CefLoadHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_LOAD_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/menu_model_cpptoc.cc b/libcef_dll/cpptoc/menu_model_cpptoc.cc new file mode 100644 index 000000000..ae45e3a5c --- /dev/null +++ b/libcef_dll/cpptoc/menu_model_cpptoc.cc @@ -0,0 +1,1020 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/menu_model_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK menu_model_clear(struct _cef_menu_model_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->Clear(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_count(struct _cef_menu_model_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefMenuModelCppToC::Get(self)->GetCount(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_add_separator(struct _cef_menu_model_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->AddSeparator(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_add_item(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->AddItem( + command_id, + CefString(label)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_add_check_item(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->AddCheckItem( + command_id, + CefString(label)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_add_radio_item(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label, int group_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->AddRadioItem( + command_id, + CefString(label), + group_id); + + // Return type: bool + return _retval; +} + +struct _cef_menu_model_t* CEF_CALLBACK menu_model_add_sub_menu( + struct _cef_menu_model_t* self, int command_id, + const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return NULL; + + // Execute + CefRefPtr _retval = CefMenuModelCppToC::Get(self)->AddSubMenu( + command_id, + CefString(label)); + + // Return type: refptr_same + return CefMenuModelCppToC::Wrap(_retval); +} + +int CEF_CALLBACK menu_model_insert_separator_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->InsertSeparatorAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_insert_item_at(struct _cef_menu_model_t* self, + int index, int command_id, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->InsertItemAt( + index, + command_id, + CefString(label)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_insert_check_item_at(struct _cef_menu_model_t* self, + int index, int command_id, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->InsertCheckItemAt( + index, + command_id, + CefString(label)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_insert_radio_item_at(struct _cef_menu_model_t* self, + int index, int command_id, const cef_string_t* label, int group_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->InsertRadioItemAt( + index, + command_id, + CefString(label), + group_id); + + // Return type: bool + return _retval; +} + +struct _cef_menu_model_t* CEF_CALLBACK menu_model_insert_sub_menu_at( + struct _cef_menu_model_t* self, int index, int command_id, + const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return NULL; + + // Execute + CefRefPtr _retval = CefMenuModelCppToC::Get( + self)->InsertSubMenuAt( + index, + command_id, + CefString(label)); + + // Return type: refptr_same + return CefMenuModelCppToC::Wrap(_retval); +} + +int CEF_CALLBACK menu_model_remove(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->Remove( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_remove_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->RemoveAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_index_of(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefMenuModelCppToC::Get(self)->GetIndexOf( + command_id); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_get_command_id_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefMenuModelCppToC::Get(self)->GetCommandIdAt( + index); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_set_command_id_at(struct _cef_menu_model_t* self, + int index, int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetCommandIdAt( + index, + command_id); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK menu_model_get_label( + struct _cef_menu_model_t* self, int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefMenuModelCppToC::Get(self)->GetLabel( + command_id); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK menu_model_get_label_at( + struct _cef_menu_model_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefMenuModelCppToC::Get(self)->GetLabelAt( + index); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK menu_model_set_label(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetLabel( + command_id, + CefString(label)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_label_at(struct _cef_menu_model_t* self, + int index, const cef_string_t* label) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: label; type: string_byref_const + DCHECK(label); + if (!label) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetLabelAt( + index, + CefString(label)); + + // Return type: bool + return _retval; +} + +cef_menu_item_type_t CEF_CALLBACK menu_model_get_type( + struct _cef_menu_model_t* self, int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return MENUITEMTYPE_NONE; + + // Execute + cef_menu_item_type_t _retval = CefMenuModelCppToC::Get(self)->GetType( + command_id); + + // Return type: simple + return _retval; +} + +cef_menu_item_type_t CEF_CALLBACK menu_model_get_type_at( + struct _cef_menu_model_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return MENUITEMTYPE_NONE; + + // Execute + cef_menu_item_type_t _retval = CefMenuModelCppToC::Get(self)->GetTypeAt( + index); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_get_group_id(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefMenuModelCppToC::Get(self)->GetGroupId( + command_id); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_get_group_id_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefMenuModelCppToC::Get(self)->GetGroupIdAt( + index); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK menu_model_set_group_id(struct _cef_menu_model_t* self, + int command_id, int group_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetGroupId( + command_id, + group_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_group_id_at(struct _cef_menu_model_t* self, + int index, int group_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetGroupIdAt( + index, + group_id); + + // Return type: bool + return _retval; +} + +struct _cef_menu_model_t* CEF_CALLBACK menu_model_get_sub_menu( + struct _cef_menu_model_t* self, int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefMenuModelCppToC::Get(self)->GetSubMenu( + command_id); + + // Return type: refptr_same + return CefMenuModelCppToC::Wrap(_retval); +} + +struct _cef_menu_model_t* CEF_CALLBACK menu_model_get_sub_menu_at( + struct _cef_menu_model_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefMenuModelCppToC::Get(self)->GetSubMenuAt( + index); + + // Return type: refptr_same + return CefMenuModelCppToC::Wrap(_retval); +} + +int CEF_CALLBACK menu_model_is_visible(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsVisible( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_is_visible_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsVisibleAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_visible(struct _cef_menu_model_t* self, + int command_id, int visible) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetVisible( + command_id, + visible?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_visible_at(struct _cef_menu_model_t* self, + int index, int visible) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetVisibleAt( + index, + visible?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_is_enabled(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsEnabled( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_is_enabled_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsEnabledAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_enabled(struct _cef_menu_model_t* self, + int command_id, int enabled) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetEnabled( + command_id, + enabled?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_enabled_at(struct _cef_menu_model_t* self, + int index, int enabled) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetEnabledAt( + index, + enabled?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_is_checked(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsChecked( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_is_checked_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->IsCheckedAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_checked(struct _cef_menu_model_t* self, + int command_id, int checked) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetChecked( + command_id, + checked?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_checked_at(struct _cef_menu_model_t* self, + int index, int checked) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetCheckedAt( + index, + checked?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_has_accelerator(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->HasAccelerator( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_has_accelerator_at(struct _cef_menu_model_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->HasAcceleratorAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_accelerator(struct _cef_menu_model_t* self, + int command_id, int key_code, int shift_pressed, int ctrl_pressed, + int alt_pressed) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetAccelerator( + command_id, + key_code, + shift_pressed?true:false, + ctrl_pressed?true:false, + alt_pressed?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_accelerator_at(struct _cef_menu_model_t* self, + int index, int key_code, int shift_pressed, int ctrl_pressed, + int alt_pressed) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetAcceleratorAt( + index, + key_code, + shift_pressed?true:false, + ctrl_pressed?true:false, + alt_pressed?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_remove_accelerator(struct _cef_menu_model_t* self, + int command_id) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->RemoveAccelerator( + command_id); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_remove_accelerator_at( + struct _cef_menu_model_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->RemoveAcceleratorAt( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_accelerator(struct _cef_menu_model_t* self, + int command_id, int* key_code, int* shift_pressed, int* ctrl_pressed, + int* alt_pressed) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key_code; type: simple_byref + DCHECK(key_code); + if (!key_code) + return 0; + // Verify param: shift_pressed; type: bool_byref + DCHECK(shift_pressed); + if (!shift_pressed) + return 0; + // Verify param: ctrl_pressed; type: bool_byref + DCHECK(ctrl_pressed); + if (!ctrl_pressed) + return 0; + // Verify param: alt_pressed; type: bool_byref + DCHECK(alt_pressed); + if (!alt_pressed) + return 0; + + // Translate param: key_code; type: simple_byref + int key_codeVal = key_code?*key_code:0; + // Translate param: shift_pressed; type: bool_byref + bool shift_pressedBool = (shift_pressed && *shift_pressed)?true:false; + // Translate param: ctrl_pressed; type: bool_byref + bool ctrl_pressedBool = (ctrl_pressed && *ctrl_pressed)?true:false; + // Translate param: alt_pressed; type: bool_byref + bool alt_pressedBool = (alt_pressed && *alt_pressed)?true:false; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->GetAccelerator( + command_id, + key_codeVal, + shift_pressedBool, + ctrl_pressedBool, + alt_pressedBool); + + // Restore param: key_code; type: simple_byref + if (key_code) + *key_code = key_codeVal; + // Restore param: shift_pressed; type: bool_byref + if (shift_pressed) + *shift_pressed = shift_pressedBool?true:false; + // Restore param: ctrl_pressed; type: bool_byref + if (ctrl_pressed) + *ctrl_pressed = ctrl_pressedBool?true:false; + // Restore param: alt_pressed; type: bool_byref + if (alt_pressed) + *alt_pressed = alt_pressedBool?true:false; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_accelerator_at(struct _cef_menu_model_t* self, + int index, int* key_code, int* shift_pressed, int* ctrl_pressed, + int* alt_pressed) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: key_code; type: simple_byref + DCHECK(key_code); + if (!key_code) + return 0; + // Verify param: shift_pressed; type: bool_byref + DCHECK(shift_pressed); + if (!shift_pressed) + return 0; + // Verify param: ctrl_pressed; type: bool_byref + DCHECK(ctrl_pressed); + if (!ctrl_pressed) + return 0; + // Verify param: alt_pressed; type: bool_byref + DCHECK(alt_pressed); + if (!alt_pressed) + return 0; + + // Translate param: key_code; type: simple_byref + int key_codeVal = key_code?*key_code:0; + // Translate param: shift_pressed; type: bool_byref + bool shift_pressedBool = (shift_pressed && *shift_pressed)?true:false; + // Translate param: ctrl_pressed; type: bool_byref + bool ctrl_pressedBool = (ctrl_pressed && *ctrl_pressed)?true:false; + // Translate param: alt_pressed; type: bool_byref + bool alt_pressedBool = (alt_pressed && *alt_pressed)?true:false; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->GetAcceleratorAt( + index, + key_codeVal, + shift_pressedBool, + ctrl_pressedBool, + alt_pressedBool); + + // Restore param: key_code; type: simple_byref + if (key_code) + *key_code = key_codeVal; + // Restore param: shift_pressed; type: bool_byref + if (shift_pressed) + *shift_pressed = shift_pressedBool?true:false; + // Restore param: ctrl_pressed; type: bool_byref + if (ctrl_pressed) + *ctrl_pressed = ctrl_pressedBool?true:false; + // Restore param: alt_pressed; type: bool_byref + if (alt_pressed) + *alt_pressed = alt_pressedBool?true:false; + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefMenuModelCppToC::CefMenuModelCppToC(CefMenuModel* cls) + : CefCppToC(cls) { + struct_.struct_.clear = menu_model_clear; + struct_.struct_.get_count = menu_model_get_count; + struct_.struct_.add_separator = menu_model_add_separator; + struct_.struct_.add_item = menu_model_add_item; + struct_.struct_.add_check_item = menu_model_add_check_item; + struct_.struct_.add_radio_item = menu_model_add_radio_item; + struct_.struct_.add_sub_menu = menu_model_add_sub_menu; + struct_.struct_.insert_separator_at = menu_model_insert_separator_at; + struct_.struct_.insert_item_at = menu_model_insert_item_at; + struct_.struct_.insert_check_item_at = menu_model_insert_check_item_at; + struct_.struct_.insert_radio_item_at = menu_model_insert_radio_item_at; + struct_.struct_.insert_sub_menu_at = menu_model_insert_sub_menu_at; + struct_.struct_.remove = menu_model_remove; + struct_.struct_.remove_at = menu_model_remove_at; + struct_.struct_.get_index_of = menu_model_get_index_of; + struct_.struct_.get_command_id_at = menu_model_get_command_id_at; + struct_.struct_.set_command_id_at = menu_model_set_command_id_at; + struct_.struct_.get_label = menu_model_get_label; + struct_.struct_.get_label_at = menu_model_get_label_at; + struct_.struct_.set_label = menu_model_set_label; + struct_.struct_.set_label_at = menu_model_set_label_at; + struct_.struct_.get_type = menu_model_get_type; + struct_.struct_.get_type_at = menu_model_get_type_at; + struct_.struct_.get_group_id = menu_model_get_group_id; + struct_.struct_.get_group_id_at = menu_model_get_group_id_at; + struct_.struct_.set_group_id = menu_model_set_group_id; + struct_.struct_.set_group_id_at = menu_model_set_group_id_at; + struct_.struct_.get_sub_menu = menu_model_get_sub_menu; + struct_.struct_.get_sub_menu_at = menu_model_get_sub_menu_at; + struct_.struct_.is_visible = menu_model_is_visible; + struct_.struct_.is_visible_at = menu_model_is_visible_at; + struct_.struct_.set_visible = menu_model_set_visible; + struct_.struct_.set_visible_at = menu_model_set_visible_at; + struct_.struct_.is_enabled = menu_model_is_enabled; + struct_.struct_.is_enabled_at = menu_model_is_enabled_at; + struct_.struct_.set_enabled = menu_model_set_enabled; + struct_.struct_.set_enabled_at = menu_model_set_enabled_at; + struct_.struct_.is_checked = menu_model_is_checked; + struct_.struct_.is_checked_at = menu_model_is_checked_at; + struct_.struct_.set_checked = menu_model_set_checked; + struct_.struct_.set_checked_at = menu_model_set_checked_at; + struct_.struct_.has_accelerator = menu_model_has_accelerator; + struct_.struct_.has_accelerator_at = menu_model_has_accelerator_at; + struct_.struct_.set_accelerator = menu_model_set_accelerator; + struct_.struct_.set_accelerator_at = menu_model_set_accelerator_at; + struct_.struct_.remove_accelerator = menu_model_remove_accelerator; + struct_.struct_.remove_accelerator_at = menu_model_remove_accelerator_at; + struct_.struct_.get_accelerator = menu_model_get_accelerator; + struct_.struct_.get_accelerator_at = menu_model_get_accelerator_at; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/menu_model_cpptoc.h b/libcef_dll/cpptoc/menu_model_cpptoc.h new file mode 100644 index 000000000..f70595df9 --- /dev/null +++ b/libcef_dll/cpptoc/menu_model_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_MENU_MODEL_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_MENU_MODEL_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_menu_model.h" +#include "include/capi/cef_menu_model_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefMenuModelCppToC + : public CefCppToC { + public: + explicit CefMenuModelCppToC(CefMenuModel* cls); + virtual ~CefMenuModelCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_MENU_MODEL_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/permission_handler_cpptoc.cc b/libcef_dll/cpptoc/permission_handler_cpptoc.cc new file mode 100644 index 000000000..5558de8eb --- /dev/null +++ b/libcef_dll/cpptoc/permission_handler_cpptoc.cc @@ -0,0 +1,67 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/permission_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK permission_handler_on_before_script_extension_load( + struct _cef_permission_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, const cef_string_t* extensionName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: extensionName; type: string_byref_const + DCHECK(extensionName); + if (!extensionName) + return 0; + + // Execute + bool _retval = CefPermissionHandlerCppToC::Get( + self)->OnBeforeScriptExtensionLoad( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefString(extensionName)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPermissionHandlerCppToC::CefPermissionHandlerCppToC( + CefPermissionHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_script_extension_load = + permission_handler_on_before_script_extension_load; +} + +#ifndef NDEBUG +template<> long CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/permission_handler_cpptoc.h b/libcef_dll/cpptoc/permission_handler_cpptoc.h new file mode 100644 index 000000000..6c8d2f86d --- /dev/null +++ b/libcef_dll/cpptoc/permission_handler_cpptoc.h @@ -0,0 +1,41 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_permission_handler.h" +#include "include/capi/cef_permission_handler_capi.h" +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_frame.h" +#include "include/capi/cef_frame_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefPermissionHandlerCppToC + : public CefCppToC { + public: + explicit CefPermissionHandlerCppToC(CefPermissionHandler* cls); + virtual ~CefPermissionHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/post_data_cpptoc.cc b/libcef_dll/cpptoc/post_data_cpptoc.cc new file mode 100644 index 000000000..3cc147e8d --- /dev/null +++ b/libcef_dll/cpptoc/post_data_cpptoc.cc @@ -0,0 +1,164 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/cpptoc/post_data_cpptoc.h" +#include "libcef_dll/cpptoc/post_data_element_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_post_data_t* cef_post_data_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefPostData::Create(); + + // Return type: refptr_same + return CefPostDataCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK post_data_is_read_only(struct _cef_post_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPostDataCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +size_t CEF_CALLBACK post_data_get_element_count(struct _cef_post_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefPostDataCppToC::Get(self)->GetElementCount(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK post_data_get_elements(struct _cef_post_data_t* self, + size_t* elementsCount, struct _cef_post_data_element_t** elements) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: elements; type: refptr_vec_same_byref + DCHECK(elementsCount && (*elementsCount == 0 || elements)); + if (!elementsCount || (*elementsCount > 0 && !elements)) + return; + + // Translate param: elements; type: refptr_vec_same_byref + std::vector > elementsList; + if (elementsCount && *elementsCount > 0 && elements) { + for (size_t i = 0; i < *elementsCount; ++i) { + elementsList.push_back(CefPostDataElementCppToC::Unwrap(elements[i])); + } + } + + // Execute + CefPostDataCppToC::Get(self)->GetElements( + elementsList); + + // Restore param: elements; type: refptr_vec_same_byref + if (elementsCount && elements) { + *elementsCount = std::min(elementsList.size(), *elementsCount); + if (*elementsCount > 0) { + for (size_t i = 0; i < *elementsCount; ++i) { + elements[i] = CefPostDataElementCppToC::Wrap(elementsList[i]); + } + } + } +} + +int CEF_CALLBACK post_data_remove_element(struct _cef_post_data_t* self, + struct _cef_post_data_element_t* element) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: element; type: refptr_same + DCHECK(element); + if (!element) + return 0; + + // Execute + bool _retval = CefPostDataCppToC::Get(self)->RemoveElement( + CefPostDataElementCppToC::Unwrap(element)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK post_data_add_element(struct _cef_post_data_t* self, + struct _cef_post_data_element_t* element) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: element; type: refptr_same + DCHECK(element); + if (!element) + return 0; + + // Execute + bool _retval = CefPostDataCppToC::Get(self)->AddElement( + CefPostDataElementCppToC::Unwrap(element)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK post_data_remove_elements(struct _cef_post_data_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPostDataCppToC::Get(self)->RemoveElements(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPostDataCppToC::CefPostDataCppToC(CefPostData* cls) + : CefCppToC(cls) { + struct_.struct_.is_read_only = post_data_is_read_only; + struct_.struct_.get_element_count = post_data_get_element_count; + struct_.struct_.get_elements = post_data_get_elements; + struct_.struct_.remove_element = post_data_remove_element; + struct_.struct_.add_element = post_data_add_element; + struct_.struct_.remove_elements = post_data_remove_elements; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/post_data_cpptoc.h b/libcef_dll/cpptoc/post_data_cpptoc.h new file mode 100644 index 000000000..4990e1e7a --- /dev/null +++ b/libcef_dll/cpptoc/post_data_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_POST_DATA_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_POST_DATA_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefPostDataCppToC + : public CefCppToC { + public: + explicit CefPostDataCppToC(CefPostData* cls); + virtual ~CefPostDataCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_POST_DATA_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/post_data_element_cpptoc.cc b/libcef_dll/cpptoc/post_data_element_cpptoc.cc new file mode 100644 index 000000000..9feb5a674 --- /dev/null +++ b/libcef_dll/cpptoc/post_data_element_cpptoc.cc @@ -0,0 +1,180 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/post_data_element_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_post_data_element_t* cef_post_data_element_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefPostDataElement::Create(); + + // Return type: refptr_same + return CefPostDataElementCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK post_data_element_is_read_only( + struct _cef_post_data_element_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPostDataElementCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK post_data_element_set_to_empty( + struct _cef_post_data_element_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPostDataElementCppToC::Get(self)->SetToEmpty(); +} + +void CEF_CALLBACK post_data_element_set_to_file( + struct _cef_post_data_element_t* self, const cef_string_t* fileName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: fileName; type: string_byref_const + DCHECK(fileName); + if (!fileName) + return; + + // Execute + CefPostDataElementCppToC::Get(self)->SetToFile( + CefString(fileName)); +} + +void CEF_CALLBACK post_data_element_set_to_bytes( + struct _cef_post_data_element_t* self, size_t size, const void* bytes) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: bytes; type: simple_byaddr + DCHECK(bytes); + if (!bytes) + return; + + // Execute + CefPostDataElementCppToC::Get(self)->SetToBytes( + size, + bytes); +} + +cef_postdataelement_type_t CEF_CALLBACK post_data_element_get_type( + struct _cef_post_data_element_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return PDE_TYPE_EMPTY; + + // Execute + cef_postdataelement_type_t _retval = CefPostDataElementCppToC::Get( + self)->GetType(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK post_data_element_get_file( + struct _cef_post_data_element_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefPostDataElementCppToC::Get(self)->GetFile(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +size_t CEF_CALLBACK post_data_element_get_bytes_count( + struct _cef_post_data_element_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefPostDataElementCppToC::Get(self)->GetBytesCount(); + + // Return type: simple + return _retval; +} + +size_t CEF_CALLBACK post_data_element_get_bytes( + struct _cef_post_data_element_t* self, size_t size, void* bytes) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: bytes; type: simple_byaddr + DCHECK(bytes); + if (!bytes) + return 0; + + // Execute + size_t _retval = CefPostDataElementCppToC::Get(self)->GetBytes( + size, + bytes); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPostDataElementCppToC::CefPostDataElementCppToC(CefPostDataElement* cls) + : CefCppToC(cls) { + struct_.struct_.is_read_only = post_data_element_is_read_only; + struct_.struct_.set_to_empty = post_data_element_set_to_empty; + struct_.struct_.set_to_file = post_data_element_set_to_file; + struct_.struct_.set_to_bytes = post_data_element_set_to_bytes; + struct_.struct_.get_type = post_data_element_get_type; + struct_.struct_.get_file = post_data_element_get_file; + struct_.struct_.get_bytes_count = post_data_element_get_bytes_count; + struct_.struct_.get_bytes = post_data_element_get_bytes; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/post_data_element_cpptoc.h b/libcef_dll/cpptoc/post_data_element_cpptoc.h new file mode 100644 index 000000000..5abd54509 --- /dev/null +++ b/libcef_dll/cpptoc/post_data_element_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_POST_DATA_ELEMENT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_POST_DATA_ELEMENT_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefPostDataElementCppToC + : public CefCppToC { + public: + explicit CefPostDataElementCppToC(CefPostDataElement* cls); + virtual ~CefPostDataElementCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_POST_DATA_ELEMENT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc new file mode 100644 index 000000000..d85827829 --- /dev/null +++ b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.cc @@ -0,0 +1,64 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/print_dialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/print_settings_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK print_dialog_callback_cont( + struct _cef_print_dialog_callback_t* self, + struct _cef_print_settings_t* settings) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: settings; type: refptr_same + DCHECK(settings); + if (!settings) + return; + + // Execute + CefPrintDialogCallbackCppToC::Get(self)->Continue( + CefPrintSettingsCppToC::Unwrap(settings)); +} + +void CEF_CALLBACK print_dialog_callback_cancel( + struct _cef_print_dialog_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintDialogCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPrintDialogCallbackCppToC::CefPrintDialogCallbackCppToC( + CefPrintDialogCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = print_dialog_callback_cont; + struct_.struct_.cancel = print_dialog_callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.h new file mode 100644 index 000000000..c8330768f --- /dev/null +++ b/libcef_dll/cpptoc/print_dialog_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_DIALOG_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PRINT_DIALOG_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefPrintDialogCallbackCppToC + : public CefCppToC { + public: + explicit CefPrintDialogCallbackCppToC(CefPrintDialogCallback* cls); + virtual ~CefPrintDialogCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PRINT_DIALOG_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/print_handler_cpptoc.cc b/libcef_dll/cpptoc/print_handler_cpptoc.cc new file mode 100644 index 000000000..193759e6b --- /dev/null +++ b/libcef_dll/cpptoc/print_handler_cpptoc.cc @@ -0,0 +1,121 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/print_handler_cpptoc.h" +#include "libcef_dll/ctocpp/print_dialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/print_job_callback_ctocpp.h" +#include "libcef_dll/ctocpp/print_settings_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK print_handler_on_print_settings( + struct _cef_print_handler_t* self, struct _cef_print_settings_t* settings, + int get_defaults) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: settings; type: refptr_diff + DCHECK(settings); + if (!settings) + return; + + // Execute + CefPrintHandlerCppToC::Get(self)->OnPrintSettings( + CefPrintSettingsCToCpp::Wrap(settings), + get_defaults?true:false); +} + +int CEF_CALLBACK print_handler_on_print_dialog( + struct _cef_print_handler_t* self, int has_selection, + cef_print_dialog_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintDialog( + has_selection?true:false, + CefPrintDialogCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK print_handler_on_print_job(struct _cef_print_handler_t* self, + const cef_string_t* document_name, const cef_string_t* pdf_file_path, + cef_print_job_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: document_name; type: string_byref_const + DCHECK(document_name); + if (!document_name) + return 0; + // Verify param: pdf_file_path; type: string_byref_const + DCHECK(pdf_file_path); + if (!pdf_file_path) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintJob( + CefString(document_name), + CefString(pdf_file_path), + CefPrintJobCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK print_handler_on_print_reset( + struct _cef_print_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintHandlerCppToC::Get(self)->OnPrintReset(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPrintHandlerCppToC::CefPrintHandlerCppToC(CefPrintHandler* cls) + : CefCppToC( + cls) { + struct_.struct_.on_print_settings = print_handler_on_print_settings; + struct_.struct_.on_print_dialog = print_handler_on_print_dialog; + struct_.struct_.on_print_job = print_handler_on_print_job; + struct_.struct_.on_print_reset = print_handler_on_print_reset; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/print_handler_cpptoc.h b/libcef_dll/cpptoc/print_handler_cpptoc.h new file mode 100644 index 000000000..775d1166a --- /dev/null +++ b/libcef_dll/cpptoc/print_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PRINT_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefPrintHandlerCppToC + : public CefCppToC { + public: + explicit CefPrintHandlerCppToC(CefPrintHandler* cls); + virtual ~CefPrintHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PRINT_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/print_job_callback_cpptoc.cc b/libcef_dll/cpptoc/print_job_callback_cpptoc.cc new file mode 100644 index 000000000..ee1bf65fb --- /dev/null +++ b/libcef_dll/cpptoc/print_job_callback_cpptoc.cc @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/print_job_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK print_job_callback_cont( + struct _cef_print_job_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintJobCallbackCppToC::Get(self)->Continue(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPrintJobCallbackCppToC::CefPrintJobCallbackCppToC(CefPrintJobCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = print_job_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/print_job_callback_cpptoc.h b/libcef_dll/cpptoc/print_job_callback_cpptoc.h new file mode 100644 index 000000000..ca30cc4d6 --- /dev/null +++ b/libcef_dll/cpptoc/print_job_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_JOB_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PRINT_JOB_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefPrintJobCallbackCppToC + : public CefCppToC { + public: + explicit CefPrintJobCallbackCppToC(CefPrintJobCallback* cls); + virtual ~CefPrintJobCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PRINT_JOB_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/print_settings_cpptoc.cc b/libcef_dll/cpptoc/print_settings_cpptoc.cc new file mode 100644 index 000000000..c2bcbb7f6 --- /dev/null +++ b/libcef_dll/cpptoc/print_settings_cpptoc.cc @@ -0,0 +1,447 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/cpptoc/print_settings_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_print_settings_t* cef_print_settings_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefPrintSettings::Create(); + + // Return type: refptr_same + return CefPrintSettingsCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK print_settings_is_valid(struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPrintSettingsCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK print_settings_is_read_only( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPrintSettingsCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +struct _cef_print_settings_t* CEF_CALLBACK print_settings_copy( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefPrintSettingsCppToC::Get(self)->Copy( + ); + + // Return type: refptr_same + return CefPrintSettingsCppToC::Wrap(_retval); +} + +void CEF_CALLBACK print_settings_set_orientation( + struct _cef_print_settings_t* self, int landscape) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetOrientation( + landscape?true:false); +} + +int CEF_CALLBACK print_settings_is_landscape( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPrintSettingsCppToC::Get(self)->IsLandscape(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK print_settings_set_printer_printable_area( + struct _cef_print_settings_t* self, + const cef_size_t* physical_size_device_units, + const cef_rect_t* printable_area_device_units, int landscape_needs_flip) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: physical_size_device_units; type: simple_byref_const + DCHECK(physical_size_device_units); + if (!physical_size_device_units) + return; + // Verify param: printable_area_device_units; type: simple_byref_const + DCHECK(printable_area_device_units); + if (!printable_area_device_units) + return; + + // Translate param: physical_size_device_units; type: simple_byref_const + CefSize physical_size_device_unitsVal = + physical_size_device_units?*physical_size_device_units:CefSize(); + // Translate param: printable_area_device_units; type: simple_byref_const + CefRect printable_area_device_unitsVal = + printable_area_device_units?*printable_area_device_units:CefRect(); + + // Execute + CefPrintSettingsCppToC::Get(self)->SetPrinterPrintableArea( + physical_size_device_unitsVal, + printable_area_device_unitsVal, + landscape_needs_flip?true:false); +} + +void CEF_CALLBACK print_settings_set_device_name( + struct _cef_print_settings_t* self, const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: name + + // Execute + CefPrintSettingsCppToC::Get(self)->SetDeviceName( + CefString(name)); +} + +cef_string_userfree_t CEF_CALLBACK print_settings_get_device_name( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefPrintSettingsCppToC::Get(self)->GetDeviceName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK print_settings_set_dpi(struct _cef_print_settings_t* self, + int dpi) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetDPI( + dpi); +} + +int CEF_CALLBACK print_settings_get_dpi(struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefPrintSettingsCppToC::Get(self)->GetDPI(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK print_settings_set_page_ranges( + struct _cef_print_settings_t* self, size_t rangesCount, + cef_page_range_t const* ranges) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: ranges; type: simple_vec_byref_const + DCHECK(rangesCount == 0 || ranges); + if (rangesCount > 0 && !ranges) + return; + + // Translate param: ranges; type: simple_vec_byref_const + std::vector rangesList; + if (rangesCount > 0) { + for (size_t i = 0; i < rangesCount; ++i) { + rangesList.push_back(ranges[i]); + } + } + + // Execute + CefPrintSettingsCppToC::Get(self)->SetPageRanges( + rangesList); +} + +size_t CEF_CALLBACK print_settings_get_page_ranges_count( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefPrintSettingsCppToC::Get(self)->GetPageRangesCount(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK print_settings_get_page_ranges( + struct _cef_print_settings_t* self, size_t* rangesCount, + cef_page_range_t* ranges) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: ranges; type: simple_vec_byref + DCHECK(rangesCount && (*rangesCount == 0 || ranges)); + if (!rangesCount || (*rangesCount > 0 && !ranges)) + return; + + // Translate param: ranges; type: simple_vec_byref + std::vector rangesList; + if (rangesCount && *rangesCount > 0 && ranges) { + for (size_t i = 0; i < *rangesCount; ++i) { + rangesList.push_back(ranges[i]); + } + } + + // Execute + CefPrintSettingsCppToC::Get(self)->GetPageRanges( + rangesList); + + // Restore param: ranges; type: simple_vec_byref + if (rangesCount && ranges) { + *rangesCount = std::min(rangesList.size(), *rangesCount); + if (*rangesCount > 0) { + for (size_t i = 0; i < *rangesCount; ++i) { + ranges[i] = rangesList[i]; + } + } + } +} + +void CEF_CALLBACK print_settings_set_selection_only( + struct _cef_print_settings_t* self, int selection_only) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetSelectionOnly( + selection_only?true:false); +} + +int CEF_CALLBACK print_settings_is_selection_only( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPrintSettingsCppToC::Get(self)->IsSelectionOnly(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK print_settings_set_collate(struct _cef_print_settings_t* self, + int collate) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetCollate( + collate?true:false); +} + +int CEF_CALLBACK print_settings_will_collate( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefPrintSettingsCppToC::Get(self)->WillCollate(); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK print_settings_set_color_model( + struct _cef_print_settings_t* self, cef_color_model_t model) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetColorModel( + model); +} + +cef_color_model_t CEF_CALLBACK print_settings_get_color_model( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return COLOR_MODEL_UNKNOWN; + + // Execute + cef_color_model_t _retval = CefPrintSettingsCppToC::Get(self)->GetColorModel( + ); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK print_settings_set_copies(struct _cef_print_settings_t* self, + int copies) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetCopies( + copies); +} + +int CEF_CALLBACK print_settings_get_copies(struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefPrintSettingsCppToC::Get(self)->GetCopies(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK print_settings_set_duplex_mode( + struct _cef_print_settings_t* self, cef_duplex_mode_t mode) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefPrintSettingsCppToC::Get(self)->SetDuplexMode( + mode); +} + +cef_duplex_mode_t CEF_CALLBACK print_settings_get_duplex_mode( + struct _cef_print_settings_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return DUPLEX_MODE_UNKNOWN; + + // Execute + cef_duplex_mode_t _retval = CefPrintSettingsCppToC::Get(self)->GetDuplexMode( + ); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefPrintSettingsCppToC::CefPrintSettingsCppToC(CefPrintSettings* cls) + : CefCppToC( + cls) { + struct_.struct_.is_valid = print_settings_is_valid; + struct_.struct_.is_read_only = print_settings_is_read_only; + struct_.struct_.copy = print_settings_copy; + struct_.struct_.set_orientation = print_settings_set_orientation; + struct_.struct_.is_landscape = print_settings_is_landscape; + struct_.struct_.set_printer_printable_area = + print_settings_set_printer_printable_area; + struct_.struct_.set_device_name = print_settings_set_device_name; + struct_.struct_.get_device_name = print_settings_get_device_name; + struct_.struct_.set_dpi = print_settings_set_dpi; + struct_.struct_.get_dpi = print_settings_get_dpi; + struct_.struct_.set_page_ranges = print_settings_set_page_ranges; + struct_.struct_.get_page_ranges_count = print_settings_get_page_ranges_count; + struct_.struct_.get_page_ranges = print_settings_get_page_ranges; + struct_.struct_.set_selection_only = print_settings_set_selection_only; + struct_.struct_.is_selection_only = print_settings_is_selection_only; + struct_.struct_.set_collate = print_settings_set_collate; + struct_.struct_.will_collate = print_settings_will_collate; + struct_.struct_.set_color_model = print_settings_set_color_model; + struct_.struct_.get_color_model = print_settings_get_color_model; + struct_.struct_.set_copies = print_settings_set_copies; + struct_.struct_.get_copies = print_settings_get_copies; + struct_.struct_.set_duplex_mode = print_settings_set_duplex_mode; + struct_.struct_.get_duplex_mode = print_settings_get_duplex_mode; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/print_settings_cpptoc.h b/libcef_dll/cpptoc/print_settings_cpptoc.h new file mode 100644 index 000000000..01dac3a42 --- /dev/null +++ b/libcef_dll/cpptoc/print_settings_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PRINT_SETTINGS_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PRINT_SETTINGS_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_print_settings.h" +#include "include/capi/cef_print_settings_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefPrintSettingsCppToC + : public CefCppToC { + public: + explicit CefPrintSettingsCppToC(CefPrintSettings* cls); + virtual ~CefPrintSettingsCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PRINT_SETTINGS_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/process_message_cpptoc.cc b/libcef_dll/cpptoc/process_message_cpptoc.cc new file mode 100644 index 000000000..8ee09c899 --- /dev/null +++ b/libcef_dll/cpptoc/process_message_cpptoc.cc @@ -0,0 +1,132 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/list_value_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_process_message_t* cef_process_message_create( + const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return NULL; + + // Execute + CefRefPtr _retval = CefProcessMessage::Create( + CefString(name)); + + // Return type: refptr_same + return CefProcessMessageCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK process_message_is_valid(struct _cef_process_message_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefProcessMessageCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK process_message_is_read_only( + struct _cef_process_message_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefProcessMessageCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +struct _cef_process_message_t* CEF_CALLBACK process_message_copy( + struct _cef_process_message_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefProcessMessageCppToC::Get( + self)->Copy(); + + // Return type: refptr_same + return CefProcessMessageCppToC::Wrap(_retval); +} + +cef_string_userfree_t CEF_CALLBACK process_message_get_name( + struct _cef_process_message_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefProcessMessageCppToC::Get(self)->GetName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +struct _cef_list_value_t* CEF_CALLBACK process_message_get_argument_list( + struct _cef_process_message_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefProcessMessageCppToC::Get( + self)->GetArgumentList(); + + // Return type: refptr_same + return CefListValueCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefProcessMessageCppToC::CefProcessMessageCppToC(CefProcessMessage* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = process_message_is_valid; + struct_.struct_.is_read_only = process_message_is_read_only; + struct_.struct_.copy = process_message_copy; + struct_.struct_.get_name = process_message_get_name; + struct_.struct_.get_argument_list = process_message_get_argument_list; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/process_message_cpptoc.h b/libcef_dll/cpptoc/process_message_cpptoc.h new file mode 100644 index 000000000..d051520ed --- /dev/null +++ b/libcef_dll/cpptoc/process_message_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_PROCESS_MESSAGE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_PROCESS_MESSAGE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_process_message.h" +#include "include/capi/cef_process_message_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefProcessMessageCppToC + : public CefCppToC { + public: + explicit CefProcessMessageCppToC(CefProcessMessage* cls); + virtual ~CefProcessMessageCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_PROCESS_MESSAGE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/quota_callback_cpptoc.cc b/libcef_dll/cpptoc/quota_callback_cpptoc.cc new file mode 100644 index 000000000..e3f0217c6 --- /dev/null +++ b/libcef_dll/cpptoc/quota_callback_cpptoc.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/quota_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK quota_callback_cont(struct _cef_quota_callback_t* self, + int allow) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefQuotaCallbackCppToC::Get(self)->Continue( + allow?true:false); +} + +void CEF_CALLBACK quota_callback_cancel(struct _cef_quota_callback_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefQuotaCallbackCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefQuotaCallbackCppToC::CefQuotaCallbackCppToC(CefQuotaCallback* cls) + : CefCppToC( + cls) { + struct_.struct_.cont = quota_callback_cont; + struct_.struct_.cancel = quota_callback_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/quota_callback_cpptoc.h b/libcef_dll/cpptoc/quota_callback_cpptoc.h new file mode 100644 index 000000000..7f3f19872 --- /dev/null +++ b/libcef_dll/cpptoc/quota_callback_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_QUOTA_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_QUOTA_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefQuotaCallbackCppToC + : public CefCppToC { + public: + explicit CefQuotaCallbackCppToC(CefQuotaCallback* cls); + virtual ~CefQuotaCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_QUOTA_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/read_handler_cpptoc.cc b/libcef_dll/cpptoc/read_handler_cpptoc.cc new file mode 100644 index 000000000..f6279ae0a --- /dev/null +++ b/libcef_dll/cpptoc/read_handler_cpptoc.cc @@ -0,0 +1,115 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/read_handler_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +size_t CEF_CALLBACK read_handler_read(struct _cef_read_handler_t* self, + void* ptr, size_t size, size_t n) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = CefReadHandlerCppToC::Get(self)->Read( + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK read_handler_seek(struct _cef_read_handler_t* self, + int64 offset, int whence) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefReadHandlerCppToC::Get(self)->Seek( + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK read_handler_tell(struct _cef_read_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefReadHandlerCppToC::Get(self)->Tell(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK read_handler_eof(struct _cef_read_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefReadHandlerCppToC::Get(self)->Eof(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK read_handler_may_block(struct _cef_read_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefReadHandlerCppToC::Get(self)->MayBlock(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefReadHandlerCppToC::CefReadHandlerCppToC(CefReadHandler* cls) + : CefCppToC(cls) { + struct_.struct_.read = read_handler_read; + struct_.struct_.seek = read_handler_seek; + struct_.struct_.tell = read_handler_tell; + struct_.struct_.eof = read_handler_eof; + struct_.struct_.may_block = read_handler_may_block; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/read_handler_cpptoc.h b/libcef_dll/cpptoc/read_handler_cpptoc.h new file mode 100644 index 000000000..eabe85782 --- /dev/null +++ b/libcef_dll/cpptoc/read_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_READ_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_READ_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefReadHandlerCppToC + : public CefCppToC { + public: + explicit CefReadHandlerCppToC(CefReadHandler* cls); + virtual ~CefReadHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_READ_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc new file mode 100644 index 000000000..203322453 --- /dev/null +++ b/libcef_dll/cpptoc/render_handler_cpptoc.cc @@ -0,0 +1,359 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/render_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/drag_data_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK render_handler_get_root_screen_rect( + struct _cef_render_handler_t* self, cef_browser_t* browser, + cef_rect_t* rect) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: rect; type: simple_byref + DCHECK(rect); + if (!rect) + return 0; + + // Translate param: rect; type: simple_byref + CefRect rectVal = rect?*rect:CefRect(); + + // Execute + bool _retval = CefRenderHandlerCppToC::Get(self)->GetRootScreenRect( + CefBrowserCToCpp::Wrap(browser), + rectVal); + + // Restore param: rect; type: simple_byref + if (rect) + *rect = rectVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK render_handler_get_view_rect( + struct _cef_render_handler_t* self, cef_browser_t* browser, + cef_rect_t* rect) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: rect; type: simple_byref + DCHECK(rect); + if (!rect) + return 0; + + // Translate param: rect; type: simple_byref + CefRect rectVal = rect?*rect:CefRect(); + + // Execute + bool _retval = CefRenderHandlerCppToC::Get(self)->GetViewRect( + CefBrowserCToCpp::Wrap(browser), + rectVal); + + // Restore param: rect; type: simple_byref + if (rect) + *rect = rectVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK render_handler_get_screen_point( + struct _cef_render_handler_t* self, cef_browser_t* browser, int viewX, + int viewY, int* screenX, int* screenY) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: screenX; type: simple_byref + DCHECK(screenX); + if (!screenX) + return 0; + // Verify param: screenY; type: simple_byref + DCHECK(screenY); + if (!screenY) + return 0; + + // Translate param: screenX; type: simple_byref + int screenXVal = screenX?*screenX:0; + // Translate param: screenY; type: simple_byref + int screenYVal = screenY?*screenY:0; + + // Execute + bool _retval = CefRenderHandlerCppToC::Get(self)->GetScreenPoint( + CefBrowserCToCpp::Wrap(browser), + viewX, + viewY, + screenXVal, + screenYVal); + + // Restore param: screenX; type: simple_byref + if (screenX) + *screenX = screenXVal; + // Restore param: screenY; type: simple_byref + if (screenY) + *screenY = screenYVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK render_handler_get_screen_info( + struct _cef_render_handler_t* self, cef_browser_t* browser, + struct _cef_screen_info_t* screen_info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: screen_info; type: struct_byref + DCHECK(screen_info); + if (!screen_info) + return 0; + + // Translate param: screen_info; type: struct_byref + CefScreenInfo screen_infoObj; + if (screen_info) + screen_infoObj.AttachTo(*screen_info); + + // Execute + bool _retval = CefRenderHandlerCppToC::Get(self)->GetScreenInfo( + CefBrowserCToCpp::Wrap(browser), + screen_infoObj); + + // Restore param: screen_info; type: struct_byref + if (screen_info) + screen_infoObj.DetachTo(*screen_info); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK render_handler_on_popup_show( + struct _cef_render_handler_t* self, cef_browser_t* browser, int show) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderHandlerCppToC::Get(self)->OnPopupShow( + CefBrowserCToCpp::Wrap(browser), + show?true:false); +} + +void CEF_CALLBACK render_handler_on_popup_size( + struct _cef_render_handler_t* self, cef_browser_t* browser, + const cef_rect_t* rect) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: rect; type: simple_byref_const + DCHECK(rect); + if (!rect) + return; + + // Translate param: rect; type: simple_byref_const + CefRect rectVal = rect?*rect:CefRect(); + + // Execute + CefRenderHandlerCppToC::Get(self)->OnPopupSize( + CefBrowserCToCpp::Wrap(browser), + rectVal); +} + +void CEF_CALLBACK render_handler_on_paint(struct _cef_render_handler_t* self, + cef_browser_t* browser, cef_paint_element_type_t type, + size_t dirtyRectsCount, cef_rect_t const* dirtyRects, const void* buffer, + int width, int height) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: dirtyRects; type: simple_vec_byref_const + DCHECK(dirtyRectsCount == 0 || dirtyRects); + if (dirtyRectsCount > 0 && !dirtyRects) + return; + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return; + + // Translate param: dirtyRects; type: simple_vec_byref_const + std::vector dirtyRectsList; + if (dirtyRectsCount > 0) { + for (size_t i = 0; i < dirtyRectsCount; ++i) { + dirtyRectsList.push_back(dirtyRects[i]); + } + } + + // Execute + CefRenderHandlerCppToC::Get(self)->OnPaint( + CefBrowserCToCpp::Wrap(browser), + type, + dirtyRectsList, + buffer, + width, + height); +} + +void CEF_CALLBACK render_handler_on_cursor_change( + struct _cef_render_handler_t* self, cef_browser_t* browser, + cef_cursor_handle_t cursor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderHandlerCppToC::Get(self)->OnCursorChange( + CefBrowserCToCpp::Wrap(browser), + cursor); +} + +int CEF_CALLBACK render_handler_start_dragging( + struct _cef_render_handler_t* self, cef_browser_t* browser, + cef_drag_data_t* drag_data, cef_drag_operations_mask_t allowed_ops, int x, + int y) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: drag_data; type: refptr_diff + DCHECK(drag_data); + if (!drag_data) + return 0; + + // Execute + bool _retval = CefRenderHandlerCppToC::Get(self)->StartDragging( + CefBrowserCToCpp::Wrap(browser), + CefDragDataCToCpp::Wrap(drag_data), + allowed_ops, + x, + y); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK render_handler_update_drag_cursor( + struct _cef_render_handler_t* self, cef_browser_t* browser, + cef_drag_operations_mask_t operation) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderHandlerCppToC::Get(self)->UpdateDragCursor( + CefBrowserCToCpp::Wrap(browser), + operation); +} + +void CEF_CALLBACK render_handler_on_scroll_offset_changed( + struct _cef_render_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderHandlerCppToC::Get(self)->OnScrollOffsetChanged( + CefBrowserCToCpp::Wrap(browser)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRenderHandlerCppToC::CefRenderHandlerCppToC(CefRenderHandler* cls) + : CefCppToC( + cls) { + struct_.struct_.get_root_screen_rect = render_handler_get_root_screen_rect; + struct_.struct_.get_view_rect = render_handler_get_view_rect; + struct_.struct_.get_screen_point = render_handler_get_screen_point; + struct_.struct_.get_screen_info = render_handler_get_screen_info; + struct_.struct_.on_popup_show = render_handler_on_popup_show; + struct_.struct_.on_popup_size = render_handler_on_popup_size; + struct_.struct_.on_paint = render_handler_on_paint; + struct_.struct_.on_cursor_change = render_handler_on_cursor_change; + struct_.struct_.start_dragging = render_handler_start_dragging; + struct_.struct_.update_drag_cursor = render_handler_update_drag_cursor; + struct_.struct_.on_scroll_offset_changed = + render_handler_on_scroll_offset_changed; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.h b/libcef_dll/cpptoc/render_handler_cpptoc.h new file mode 100644 index 000000000..3c0498af7 --- /dev/null +++ b/libcef_dll/cpptoc/render_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RENDER_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RENDER_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_render_handler.h" +#include "include/capi/cef_render_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefRenderHandlerCppToC + : public CefCppToC { + public: + explicit CefRenderHandlerCppToC(CefRenderHandler* cls); + virtual ~CefRenderHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RENDER_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc new file mode 100644 index 000000000..78a8bd9bb --- /dev/null +++ b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc @@ -0,0 +1,321 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/load_handler_cpptoc.h" +#include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/list_value_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/v8context_ctocpp.h" +#include "libcef_dll/ctocpp/v8exception_ctocpp.h" +#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK render_process_handler_on_render_thread_created( + struct _cef_render_process_handler_t* self, + struct _cef_list_value_t* extra_info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: extra_info; type: refptr_diff + DCHECK(extra_info); + if (!extra_info) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnRenderThreadCreated( + CefListValueCToCpp::Wrap(extra_info)); +} + +void CEF_CALLBACK render_process_handler_on_web_kit_initialized( + struct _cef_render_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnWebKitInitialized(); +} + +void CEF_CALLBACK render_process_handler_on_browser_created( + struct _cef_render_process_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnBrowserCreated( + CefBrowserCToCpp::Wrap(browser)); +} + +void CEF_CALLBACK render_process_handler_on_browser_destroyed( + struct _cef_render_process_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnBrowserDestroyed( + CefBrowserCToCpp::Wrap(browser)); +} + +cef_load_handler_t* CEF_CALLBACK render_process_handler_get_load_handler( + struct _cef_render_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefRenderProcessHandlerCppToC::Get( + self)->GetLoadHandler(); + + // Return type: refptr_same + return CefLoadHandlerCppToC::Wrap(_retval); +} + +int CEF_CALLBACK render_process_handler_on_before_navigation( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, struct _cef_request_t* request, + cef_navigation_type_t navigation_type, int is_redirect) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return 0; + + // Execute + bool _retval = CefRenderProcessHandlerCppToC::Get(self)->OnBeforeNavigation( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefRequestCToCpp::Wrap(request), + navigation_type, + is_redirect?true:false); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK render_process_handler_on_context_created( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, struct _cef_v8context_t* context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: context; type: refptr_diff + DCHECK(context); + if (!context) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnContextCreated( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefV8ContextCToCpp::Wrap(context)); +} + +void CEF_CALLBACK render_process_handler_on_context_released( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, struct _cef_v8context_t* context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: context; type: refptr_diff + DCHECK(context); + if (!context) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnContextReleased( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefV8ContextCToCpp::Wrap(context)); +} + +void CEF_CALLBACK render_process_handler_on_uncaught_exception( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, struct _cef_v8context_t* context, + struct _cef_v8exception_t* exception, + struct _cef_v8stack_trace_t* stackTrace) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: context; type: refptr_diff + DCHECK(context); + if (!context) + return; + // Verify param: exception; type: refptr_diff + DCHECK(exception); + if (!exception) + return; + // Verify param: stackTrace; type: refptr_diff + DCHECK(stackTrace); + if (!stackTrace) + return; + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnUncaughtException( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefV8ContextCToCpp::Wrap(context), + CefV8ExceptionCToCpp::Wrap(exception), + CefV8StackTraceCToCpp::Wrap(stackTrace)); +} + +void CEF_CALLBACK render_process_handler_on_focused_node_changed( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, cef_domnode_t* node) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Unverified params: frame, node + + // Execute + CefRenderProcessHandlerCppToC::Get(self)->OnFocusedNodeChanged( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefDOMNodeCToCpp::Wrap(node)); +} + +int CEF_CALLBACK render_process_handler_on_process_message_received( + struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_process_id_t source_process, cef_process_message_t* message) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: message; type: refptr_diff + DCHECK(message); + if (!message) + return 0; + + // Execute + bool _retval = CefRenderProcessHandlerCppToC::Get( + self)->OnProcessMessageReceived( + CefBrowserCToCpp::Wrap(browser), + source_process, + CefProcessMessageCToCpp::Wrap(message)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC( + CefRenderProcessHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_render_thread_created = + render_process_handler_on_render_thread_created; + struct_.struct_.on_web_kit_initialized = + render_process_handler_on_web_kit_initialized; + struct_.struct_.on_browser_created = + render_process_handler_on_browser_created; + struct_.struct_.on_browser_destroyed = + render_process_handler_on_browser_destroyed; + struct_.struct_.get_load_handler = render_process_handler_get_load_handler; + struct_.struct_.on_before_navigation = + render_process_handler_on_before_navigation; + struct_.struct_.on_context_created = + render_process_handler_on_context_created; + struct_.struct_.on_context_released = + render_process_handler_on_context_released; + struct_.struct_.on_uncaught_exception = + render_process_handler_on_uncaught_exception; + struct_.struct_.on_focused_node_changed = + render_process_handler_on_focused_node_changed; + struct_.struct_.on_process_message_received = + render_process_handler_on_process_message_received; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/render_process_handler_cpptoc.h b/libcef_dll/cpptoc/render_process_handler_cpptoc.h new file mode 100644 index 000000000..e21e54715 --- /dev/null +++ b/libcef_dll/cpptoc/render_process_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RENDER_PROCESS_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RENDER_PROCESS_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_render_process_handler.h" +#include "include/capi/cef_render_process_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefRenderProcessHandlerCppToC + : public CefCppToC { + public: + explicit CefRenderProcessHandlerCppToC(CefRenderProcessHandler* cls); + virtual ~CefRenderProcessHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RENDER_PROCESS_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_context_cpptoc.cc b/libcef_dll/cpptoc/request_context_cpptoc.cc new file mode 100644 index 000000000..2761fedbf --- /dev/null +++ b/libcef_dll/cpptoc/request_context_cpptoc.cc @@ -0,0 +1,112 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/request_context_cpptoc.h" +#include "libcef_dll/ctocpp/request_context_handler_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefRequestContext::GetGlobalContext(); + + // Return type: refptr_same + return CefRequestContextCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_request_context_t* cef_request_context_create_context( + struct _cef_request_context_handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: handler + + // Execute + CefRefPtr _retval = CefRequestContext::CreateContext( + CefRequestContextHandlerCToCpp::Wrap(handler)); + + // Return type: refptr_same + return CefRequestContextCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK request_context_is_same(struct _cef_request_context_t* self, + struct _cef_request_context_t* other) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: other; type: refptr_same + DCHECK(other); + if (!other) + return 0; + + // Execute + bool _retval = CefRequestContextCppToC::Get(self)->IsSame( + CefRequestContextCppToC::Unwrap(other)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK request_context_is_global( + struct _cef_request_context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefRequestContextCppToC::Get(self)->IsGlobal(); + + // Return type: bool + return _retval; +} + +struct _cef_request_context_handler_t* CEF_CALLBACK request_context_get_handler( + struct _cef_request_context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefRequestContextCppToC::Get( + self)->GetHandler(); + + // Return type: refptr_diff + return CefRequestContextHandlerCToCpp::Unwrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRequestContextCppToC::CefRequestContextCppToC(CefRequestContext* cls) + : CefCppToC(cls) { + struct_.struct_.is_same = request_context_is_same; + struct_.struct_.is_global = request_context_is_global; + struct_.struct_.get_handler = request_context_get_handler; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/request_context_cpptoc.h b/libcef_dll/cpptoc/request_context_cpptoc.h new file mode 100644 index 000000000..c6a0e5d2c --- /dev/null +++ b/libcef_dll/cpptoc/request_context_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request_context.h" +#include "include/capi/cef_request_context_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefRequestContextCppToC + : public CefCppToC { + public: + explicit CefRequestContextCppToC(CefRequestContext* cls); + virtual ~CefRequestContextCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_context_handler_cpptoc.cc b/libcef_dll/cpptoc/request_context_handler_cpptoc.cc new file mode 100644 index 000000000..eea653351 --- /dev/null +++ b/libcef_dll/cpptoc/request_context_handler_cpptoc.cc @@ -0,0 +1,50 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/request_context_handler_cpptoc.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_cookie_manager_t* CEF_CALLBACK request_context_handler_get_cookie_manager( + struct _cef_request_context_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefRequestContextHandlerCppToC::Get( + self)->GetCookieManager(); + + // Return type: refptr_diff + return CefCookieManagerCToCpp::Unwrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRequestContextHandlerCppToC::CefRequestContextHandlerCppToC( + CefRequestContextHandler* cls) + : CefCppToC(cls) { + struct_.struct_.get_cookie_manager = + request_context_handler_get_cookie_manager; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/request_context_handler_cpptoc.h b/libcef_dll/cpptoc/request_context_handler_cpptoc.h new file mode 100644 index 000000000..60d27f742 --- /dev/null +++ b/libcef_dll/cpptoc/request_context_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request_context_handler.h" +#include "include/capi/cef_request_context_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefRequestContextHandlerCppToC + : public CefCppToC { + public: + explicit CefRequestContextHandlerCppToC(CefRequestContextHandler* cls); + virtual ~CefRequestContextHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_REQUEST_CONTEXT_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_cpptoc.cc b/libcef_dll/cpptoc/request_cpptoc.cc new file mode 100644 index 000000000..7d723bb5f --- /dev/null +++ b/libcef_dll/cpptoc/request_cpptoc.cc @@ -0,0 +1,341 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/post_data_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_request_t* cef_request_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefRequest::Create(); + + // Return type: refptr_same + return CefRequestCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK request_is_read_only(struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefRequestCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK request_get_url( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefRequestCppToC::Get(self)->GetURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK request_set_url(struct _cef_request_t* self, + const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefRequestCppToC::Get(self)->SetURL( + CefString(url)); +} + +cef_string_userfree_t CEF_CALLBACK request_get_method( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefRequestCppToC::Get(self)->GetMethod(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK request_set_method(struct _cef_request_t* self, + const cef_string_t* method) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: method; type: string_byref_const + DCHECK(method); + if (!method) + return; + + // Execute + CefRequestCppToC::Get(self)->SetMethod( + CefString(method)); +} + +struct _cef_post_data_t* CEF_CALLBACK request_get_post_data( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefRequestCppToC::Get(self)->GetPostData(); + + // Return type: refptr_same + return CefPostDataCppToC::Wrap(_retval); +} + +void CEF_CALLBACK request_set_post_data(struct _cef_request_t* self, + struct _cef_post_data_t* postData) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: postData; type: refptr_same + DCHECK(postData); + if (!postData) + return; + + // Execute + CefRequestCppToC::Get(self)->SetPostData( + CefPostDataCppToC::Unwrap(postData)); +} + +void CEF_CALLBACK request_get_header_map(struct _cef_request_t* self, + cef_string_multimap_t headerMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: headerMap; type: string_map_multi_byref + DCHECK(headerMap); + if (!headerMap) + return; + + // Translate param: headerMap; type: string_map_multi_byref + std::multimap headerMapMultimap; + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + CefRequestCppToC::Get(self)->GetHeaderMap( + headerMapMultimap); + + // Restore param: headerMap; type: string_map_multi_byref + cef_string_multimap_clear(headerMap); + transfer_string_multimap_contents(headerMapMultimap, headerMap); +} + +void CEF_CALLBACK request_set_header_map(struct _cef_request_t* self, + cef_string_multimap_t headerMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: headerMap; type: string_map_multi_byref_const + DCHECK(headerMap); + if (!headerMap) + return; + + // Translate param: headerMap; type: string_map_multi_byref_const + std::multimap headerMapMultimap; + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + CefRequestCppToC::Get(self)->SetHeaderMap( + headerMapMultimap); +} + +void CEF_CALLBACK request_set(struct _cef_request_t* self, + const cef_string_t* url, const cef_string_t* method, + struct _cef_post_data_t* postData, cef_string_multimap_t headerMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + // Verify param: method; type: string_byref_const + DCHECK(method); + if (!method) + return; + // Verify param: headerMap; type: string_map_multi_byref_const + DCHECK(headerMap); + if (!headerMap) + return; + // Unverified params: postData + + // Translate param: headerMap; type: string_map_multi_byref_const + std::multimap headerMapMultimap; + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + CefRequestCppToC::Get(self)->Set( + CefString(url), + CefString(method), + CefPostDataCppToC::Unwrap(postData), + headerMapMultimap); +} + +int CEF_CALLBACK request_get_flags(struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return UR_FLAG_NONE; + + // Execute + int _retval = CefRequestCppToC::Get(self)->GetFlags(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK request_set_flags(struct _cef_request_t* self, int flags) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefRequestCppToC::Get(self)->SetFlags( + flags); +} + +cef_string_userfree_t CEF_CALLBACK request_get_first_party_for_cookies( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefRequestCppToC::Get(self)->GetFirstPartyForCookies(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK request_set_first_party_for_cookies( + struct _cef_request_t* self, const cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + + // Execute + CefRequestCppToC::Get(self)->SetFirstPartyForCookies( + CefString(url)); +} + +cef_resource_type_t CEF_CALLBACK request_get_resource_type( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return RT_SUB_RESOURCE; + + // Execute + cef_resource_type_t _retval = CefRequestCppToC::Get(self)->GetResourceType(); + + // Return type: simple + return _retval; +} + +cef_transition_type_t CEF_CALLBACK request_get_transition_type( + struct _cef_request_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return TT_EXPLICIT; + + // Execute + cef_transition_type_t _retval = CefRequestCppToC::Get( + self)->GetTransitionType(); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRequestCppToC::CefRequestCppToC(CefRequest* cls) + : CefCppToC(cls) { + struct_.struct_.is_read_only = request_is_read_only; + struct_.struct_.get_url = request_get_url; + struct_.struct_.set_url = request_set_url; + struct_.struct_.get_method = request_get_method; + struct_.struct_.set_method = request_set_method; + struct_.struct_.get_post_data = request_get_post_data; + struct_.struct_.set_post_data = request_set_post_data; + struct_.struct_.get_header_map = request_get_header_map; + struct_.struct_.set_header_map = request_set_header_map; + struct_.struct_.set = request_set; + struct_.struct_.get_flags = request_get_flags; + struct_.struct_.set_flags = request_set_flags; + struct_.struct_.get_first_party_for_cookies = + request_get_first_party_for_cookies; + struct_.struct_.set_first_party_for_cookies = + request_set_first_party_for_cookies; + struct_.struct_.get_resource_type = request_get_resource_type; + struct_.struct_.get_transition_type = request_get_transition_type; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/request_cpptoc.h b/libcef_dll/cpptoc/request_cpptoc.h new file mode 100644 index 000000000..adbf037fc --- /dev/null +++ b/libcef_dll/cpptoc/request_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_REQUEST_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefRequestCppToC + : public CefCppToC { + public: + explicit CefRequestCppToC(CefRequest* cls); + virtual ~CefRequestCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_REQUEST_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_handler_cpptoc.cc b/libcef_dll/cpptoc/request_handler_cpptoc.cc new file mode 100644 index 000000000..779f28ec0 --- /dev/null +++ b/libcef_dll/cpptoc/request_handler_cpptoc.cc @@ -0,0 +1,398 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/request_handler_cpptoc.h" +#include "libcef_dll/cpptoc/resource_handler_cpptoc.h" +#include "libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h" +#include "libcef_dll/ctocpp/auth_callback_ctocpp.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/quota_callback_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK request_handler_on_before_browse( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, cef_request_t* request, int is_redirect) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return 0; + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->OnBeforeBrowse( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefRequestCToCpp::Wrap(request), + is_redirect?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK request_handler_on_before_resource_load( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, cef_request_t* request) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return 0; + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->OnBeforeResourceLoad( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefRequestCToCpp::Wrap(request)); + + // Return type: bool + return _retval; +} + +struct _cef_resource_handler_t* CEF_CALLBACK request_handler_get_resource_handler( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, cef_request_t* request) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return NULL; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return NULL; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return NULL; + + // Execute + CefRefPtr _retval = CefRequestHandlerCppToC::Get( + self)->GetResourceHandler( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefRequestCToCpp::Wrap(request)); + + // Return type: refptr_same + return CefResourceHandlerCppToC::Wrap(_retval); +} + +void CEF_CALLBACK request_handler_on_resource_redirect( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, const cef_string_t* old_url, cef_string_t* new_url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; + // Verify param: old_url; type: string_byref_const + DCHECK(old_url); + if (!old_url) + return; + // Verify param: new_url; type: string_byref + DCHECK(new_url); + if (!new_url) + return; + + // Translate param: new_url; type: string_byref + CefString new_urlStr(new_url); + + // Execute + CefRequestHandlerCppToC::Get(self)->OnResourceRedirect( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefString(old_url), + new_urlStr); +} + +int CEF_CALLBACK request_handler_get_auth_credentials( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, int isProxy, const cef_string_t* host, int port, + const cef_string_t* realm, const cef_string_t* scheme, + cef_auth_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; + // Verify param: host; type: string_byref_const + DCHECK(host); + if (!host) + return 0; + // Verify param: scheme; type: string_byref_const + DCHECK(scheme); + if (!scheme) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Unverified params: realm + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->GetAuthCredentials( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + isProxy?true:false, + CefString(host), + port, + CefString(realm), + CefString(scheme), + CefAuthCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK request_handler_on_quota_request( + struct _cef_request_handler_t* self, cef_browser_t* browser, + const cef_string_t* origin_url, int64 new_size, + cef_quota_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: origin_url; type: string_byref_const + DCHECK(origin_url); + if (!origin_url) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->OnQuotaRequest( + CefBrowserCToCpp::Wrap(browser), + CefString(origin_url), + new_size, + CefQuotaCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK request_handler_on_protocol_execution( + struct _cef_request_handler_t* self, cef_browser_t* browser, + const cef_string_t* url, int* allow_os_execution) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return; + // Verify param: allow_os_execution; type: bool_byref + DCHECK(allow_os_execution); + if (!allow_os_execution) + return; + + // Translate param: allow_os_execution; type: bool_byref + bool allow_os_executionBool = ( + allow_os_execution && *allow_os_execution)?true:false; + + // Execute + CefRequestHandlerCppToC::Get(self)->OnProtocolExecution( + CefBrowserCToCpp::Wrap(browser), + CefString(url), + allow_os_executionBool); + + // Restore param: allow_os_execution; type: bool_byref + if (allow_os_execution) + *allow_os_execution = allow_os_executionBool?true:false; +} + +int CEF_CALLBACK request_handler_on_certificate_error( + struct _cef_request_handler_t* self, cef_errorcode_t cert_error, + const cef_string_t* request_url, + cef_allow_certificate_error_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: request_url; type: string_byref_const + DCHECK(request_url); + if (!request_url) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->OnCertificateError( + cert_error, + CefString(request_url), + CefAllowCertificateErrorCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK request_handler_on_before_plugin_load( + struct _cef_request_handler_t* self, cef_browser_t* browser, + const cef_string_t* url, const cef_string_t* policy_url, + struct _cef_web_plugin_info_t* info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: info; type: refptr_diff + DCHECK(info); + if (!info) + return 0; + // Unverified params: url, policy_url + + // Execute + bool _retval = CefRequestHandlerCppToC::Get(self)->OnBeforePluginLoad( + CefBrowserCToCpp::Wrap(browser), + CefString(url), + CefString(policy_url), + CefWebPluginInfoCToCpp::Wrap(info)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK request_handler_on_plugin_crashed( + struct _cef_request_handler_t* self, cef_browser_t* browser, + const cef_string_t* plugin_path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + // Verify param: plugin_path; type: string_byref_const + DCHECK(plugin_path); + if (!plugin_path) + return; + + // Execute + CefRequestHandlerCppToC::Get(self)->OnPluginCrashed( + CefBrowserCToCpp::Wrap(browser), + CefString(plugin_path)); +} + +void CEF_CALLBACK request_handler_on_render_process_terminated( + struct _cef_request_handler_t* self, cef_browser_t* browser, + cef_termination_status_t status) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefRequestHandlerCppToC::Get(self)->OnRenderProcessTerminated( + CefBrowserCToCpp::Wrap(browser), + status); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRequestHandlerCppToC::CefRequestHandlerCppToC(CefRequestHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_before_browse = request_handler_on_before_browse; + struct_.struct_.on_before_resource_load = + request_handler_on_before_resource_load; + struct_.struct_.get_resource_handler = request_handler_get_resource_handler; + struct_.struct_.on_resource_redirect = request_handler_on_resource_redirect; + struct_.struct_.get_auth_credentials = request_handler_get_auth_credentials; + struct_.struct_.on_quota_request = request_handler_on_quota_request; + struct_.struct_.on_protocol_execution = request_handler_on_protocol_execution; + struct_.struct_.on_certificate_error = request_handler_on_certificate_error; + struct_.struct_.on_before_plugin_load = request_handler_on_before_plugin_load; + struct_.struct_.on_plugin_crashed = request_handler_on_plugin_crashed; + struct_.struct_.on_render_process_terminated = + request_handler_on_render_process_terminated; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/request_handler_cpptoc.h b/libcef_dll/cpptoc/request_handler_cpptoc.h new file mode 100644 index 000000000..75a7b6d01 --- /dev/null +++ b/libcef_dll/cpptoc/request_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_REQUEST_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_REQUEST_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefRequestHandlerCppToC + : public CefCppToC { + public: + explicit CefRequestHandlerCppToC(CefRequestHandler* cls); + virtual ~CefRequestHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_REQUEST_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc new file mode 100644 index 000000000..cbce1fbbe --- /dev/null +++ b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK resource_bundle_handler_get_localized_string( + struct _cef_resource_bundle_handler_t* self, int message_id, + cef_string_t* string) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: string; type: string_byref + DCHECK(string); + if (!string) + return 0; + + // Translate param: string; type: string_byref + CefString stringStr(string); + + // Execute + bool _retval = CefResourceBundleHandlerCppToC::Get(self)->GetLocalizedString( + message_id, + stringStr); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK resource_bundle_handler_get_data_resource( + struct _cef_resource_bundle_handler_t* self, int resource_id, void** data, + size_t* data_size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: data; type: simple_byref + DCHECK(data); + if (!data) + return 0; + // Verify param: data_size; type: simple_byref + DCHECK(data_size); + if (!data_size) + return 0; + + // Translate param: data; type: simple_byref + void* dataVal = data?*data:NULL; + // Translate param: data_size; type: simple_byref + size_t data_sizeVal = data_size?*data_size:0; + + // Execute + bool _retval = CefResourceBundleHandlerCppToC::Get(self)->GetDataResource( + resource_id, + dataVal, + data_sizeVal); + + // Restore param: data; type: simple_byref + if (data) + *data = dataVal; + // Restore param: data_size; type: simple_byref + if (data_size) + *data_size = data_sizeVal; + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefResourceBundleHandlerCppToC::CefResourceBundleHandlerCppToC( + CefResourceBundleHandler* cls) + : CefCppToC(cls) { + struct_.struct_.get_localized_string = + resource_bundle_handler_get_localized_string; + struct_.struct_.get_data_resource = resource_bundle_handler_get_data_resource; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h new file mode 100644 index 000000000..7ebf47172 --- /dev/null +++ b/libcef_dll/cpptoc/resource_bundle_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_BUNDLE_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RESOURCE_BUNDLE_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_resource_bundle_handler.h" +#include "include/capi/cef_resource_bundle_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefResourceBundleHandlerCppToC + : public CefCppToC { + public: + explicit CefResourceBundleHandlerCppToC(CefResourceBundleHandler* cls); + virtual ~CefResourceBundleHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RESOURCE_BUNDLE_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/resource_handler_cpptoc.cc b/libcef_dll/cpptoc/resource_handler_cpptoc.cc new file mode 100644 index 000000000..2ce961548 --- /dev/null +++ b/libcef_dll/cpptoc/resource_handler_cpptoc.cc @@ -0,0 +1,203 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/resource_handler_cpptoc.h" +#include "libcef_dll/ctocpp/callback_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/response_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK resource_handler_process_request( + struct _cef_resource_handler_t* self, cef_request_t* request, + cef_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefResourceHandlerCppToC::Get(self)->ProcessRequest( + CefRequestCToCpp::Wrap(request), + CefCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK resource_handler_get_response_headers( + struct _cef_resource_handler_t* self, struct _cef_response_t* response, + int64* response_length, cef_string_t* redirectUrl) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: response; type: refptr_diff + DCHECK(response); + if (!response) + return; + // Verify param: response_length; type: simple_byref + DCHECK(response_length); + if (!response_length) + return; + // Verify param: redirectUrl; type: string_byref + DCHECK(redirectUrl); + if (!redirectUrl) + return; + + // Translate param: response_length; type: simple_byref + int64 response_lengthVal = response_length?*response_length:0; + // Translate param: redirectUrl; type: string_byref + CefString redirectUrlStr(redirectUrl); + + // Execute + CefResourceHandlerCppToC::Get(self)->GetResponseHeaders( + CefResponseCToCpp::Wrap(response), + response_lengthVal, + redirectUrlStr); + + // Restore param: response_length; type: simple_byref + if (response_length) + *response_length = response_lengthVal; +} + +int CEF_CALLBACK resource_handler_read_response( + struct _cef_resource_handler_t* self, void* data_out, int bytes_to_read, + int* bytes_read, cef_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: data_out; type: simple_byaddr + DCHECK(data_out); + if (!data_out) + return 0; + // Verify param: bytes_read; type: simple_byref + DCHECK(bytes_read); + if (!bytes_read) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Translate param: bytes_read; type: simple_byref + int bytes_readVal = bytes_read?*bytes_read:0; + + // Execute + bool _retval = CefResourceHandlerCppToC::Get(self)->ReadResponse( + data_out, + bytes_to_read, + bytes_readVal, + CefCallbackCToCpp::Wrap(callback)); + + // Restore param: bytes_read; type: simple_byref + if (bytes_read) + *bytes_read = bytes_readVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK resource_handler_can_get_cookie( + struct _cef_resource_handler_t* self, const struct _cef_cookie_t* cookie) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: cookie; type: struct_byref_const + DCHECK(cookie); + if (!cookie) + return 0; + + // Translate param: cookie; type: struct_byref_const + CefCookie cookieObj; + if (cookie) + cookieObj.Set(*cookie, false); + + // Execute + bool _retval = CefResourceHandlerCppToC::Get(self)->CanGetCookie( + cookieObj); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK resource_handler_can_set_cookie( + struct _cef_resource_handler_t* self, const struct _cef_cookie_t* cookie) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: cookie; type: struct_byref_const + DCHECK(cookie); + if (!cookie) + return 0; + + // Translate param: cookie; type: struct_byref_const + CefCookie cookieObj; + if (cookie) + cookieObj.Set(*cookie, false); + + // Execute + bool _retval = CefResourceHandlerCppToC::Get(self)->CanSetCookie( + cookieObj); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK resource_handler_cancel( + struct _cef_resource_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefResourceHandlerCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefResourceHandlerCppToC::CefResourceHandlerCppToC(CefResourceHandler* cls) + : CefCppToC(cls) { + struct_.struct_.process_request = resource_handler_process_request; + struct_.struct_.get_response_headers = resource_handler_get_response_headers; + struct_.struct_.read_response = resource_handler_read_response; + struct_.struct_.can_get_cookie = resource_handler_can_get_cookie; + struct_.struct_.can_set_cookie = resource_handler_can_set_cookie; + struct_.struct_.cancel = resource_handler_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/resource_handler_cpptoc.h b/libcef_dll/cpptoc/resource_handler_cpptoc.h new file mode 100644 index 000000000..7e59d6191 --- /dev/null +++ b/libcef_dll/cpptoc/resource_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RESOURCE_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RESOURCE_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_resource_handler.h" +#include "include/capi/cef_resource_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefResourceHandlerCppToC + : public CefCppToC { + public: + explicit CefResourceHandlerCppToC(CefResourceHandler* cls); + virtual ~CefResourceHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RESOURCE_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/response_cpptoc.cc b/libcef_dll/cpptoc/response_cpptoc.cc new file mode 100644 index 000000000..38f549d7f --- /dev/null +++ b/libcef_dll/cpptoc/response_cpptoc.cc @@ -0,0 +1,224 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/response_cpptoc.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_response_t* cef_response_create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefResponse::Create(); + + // Return type: refptr_same + return CefResponseCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK response_is_read_only(struct _cef_response_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefResponseCppToC::Get(self)->IsReadOnly(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK response_get_status(struct _cef_response_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefResponseCppToC::Get(self)->GetStatus(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK response_set_status(struct _cef_response_t* self, + int status) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefResponseCppToC::Get(self)->SetStatus( + status); +} + +cef_string_userfree_t CEF_CALLBACK response_get_status_text( + struct _cef_response_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefResponseCppToC::Get(self)->GetStatusText(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK response_set_status_text(struct _cef_response_t* self, + const cef_string_t* statusText) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: statusText; type: string_byref_const + DCHECK(statusText); + if (!statusText) + return; + + // Execute + CefResponseCppToC::Get(self)->SetStatusText( + CefString(statusText)); +} + +cef_string_userfree_t CEF_CALLBACK response_get_mime_type( + struct _cef_response_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefResponseCppToC::Get(self)->GetMimeType(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK response_set_mime_type(struct _cef_response_t* self, + const cef_string_t* mimeType) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: mimeType; type: string_byref_const + DCHECK(mimeType); + if (!mimeType) + return; + + // Execute + CefResponseCppToC::Get(self)->SetMimeType( + CefString(mimeType)); +} + +cef_string_userfree_t CEF_CALLBACK response_get_header( + struct _cef_response_t* self, const cef_string_t* name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return NULL; + + // Execute + CefString _retval = CefResponseCppToC::Get(self)->GetHeader( + CefString(name)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +void CEF_CALLBACK response_get_header_map(struct _cef_response_t* self, + cef_string_multimap_t headerMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: headerMap; type: string_map_multi_byref + DCHECK(headerMap); + if (!headerMap) + return; + + // Translate param: headerMap; type: string_map_multi_byref + std::multimap headerMapMultimap; + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + CefResponseCppToC::Get(self)->GetHeaderMap( + headerMapMultimap); + + // Restore param: headerMap; type: string_map_multi_byref + cef_string_multimap_clear(headerMap); + transfer_string_multimap_contents(headerMapMultimap, headerMap); +} + +void CEF_CALLBACK response_set_header_map(struct _cef_response_t* self, + cef_string_multimap_t headerMap) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: headerMap; type: string_map_multi_byref_const + DCHECK(headerMap); + if (!headerMap) + return; + + // Translate param: headerMap; type: string_map_multi_byref_const + std::multimap headerMapMultimap; + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + CefResponseCppToC::Get(self)->SetHeaderMap( + headerMapMultimap); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefResponseCppToC::CefResponseCppToC(CefResponse* cls) + : CefCppToC(cls) { + struct_.struct_.is_read_only = response_is_read_only; + struct_.struct_.get_status = response_get_status; + struct_.struct_.set_status = response_set_status; + struct_.struct_.get_status_text = response_get_status_text; + struct_.struct_.set_status_text = response_set_status_text; + struct_.struct_.get_mime_type = response_get_mime_type; + struct_.struct_.set_mime_type = response_set_mime_type; + struct_.struct_.get_header = response_get_header; + struct_.struct_.get_header_map = response_get_header_map; + struct_.struct_.set_header_map = response_set_header_map; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/response_cpptoc.h b/libcef_dll/cpptoc/response_cpptoc.h new file mode 100644 index 000000000..d045be776 --- /dev/null +++ b/libcef_dll/cpptoc/response_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RESPONSE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RESPONSE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_response.h" +#include "include/capi/cef_response_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefResponseCppToC + : public CefCppToC { + public: + explicit CefResponseCppToC(CefResponse* cls); + virtual ~CefResponseCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RESPONSE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc new file mode 100644 index 000000000..ef0f35924 --- /dev/null +++ b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc @@ -0,0 +1,61 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h" +#include "libcef_dll/ctocpp/browser_host_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK run_file_dialog_callback_cont( + struct _cef_run_file_dialog_callback_t* self, + struct _cef_browser_host_t* browser_host, cef_string_list_t file_paths) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser_host; type: refptr_diff + DCHECK(browser_host); + if (!browser_host) + return; + // Verify param: file_paths; type: string_vec_byref_const + DCHECK(file_paths); + if (!file_paths) + return; + + // Translate param: file_paths; type: string_vec_byref_const + std::vector file_pathsList; + transfer_string_list_contents(file_paths, file_pathsList); + + // Execute + CefRunFileDialogCallbackCppToC::Get(self)->OnFileDialogDismissed( + CefBrowserHostCToCpp::Wrap(browser_host), + file_pathsList); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefRunFileDialogCallbackCppToC::CefRunFileDialogCallbackCppToC( + CefRunFileDialogCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = run_file_dialog_callback_cont; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h new file mode 100644 index 000000000..6f0154624 --- /dev/null +++ b/libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h @@ -0,0 +1,39 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefRunFileDialogCallbackCppToC + : public CefCppToC { + public: + explicit CefRunFileDialogCallbackCppToC(CefRunFileDialogCallback* cls); + virtual ~CefRunFileDialogCallbackCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_RUN_FILE_DIALOG_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc new file mode 100644 index 000000000..0dbf1ee47 --- /dev/null +++ b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.cc @@ -0,0 +1,67 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/resource_handler_cpptoc.h" +#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_resource_handler_t* CEF_CALLBACK scheme_handler_factory_create( + struct _cef_scheme_handler_factory_t* self, cef_browser_t* browser, + cef_frame_t* frame, const cef_string_t* scheme_name, + cef_request_t* request) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: scheme_name; type: string_byref_const + DCHECK(scheme_name); + if (!scheme_name) + return NULL; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return NULL; + // Unverified params: browser, frame + + // Execute + CefRefPtr _retval = CefSchemeHandlerFactoryCppToC::Get( + self)->Create( + CefBrowserCToCpp::Wrap(browser), + CefFrameCToCpp::Wrap(frame), + CefString(scheme_name), + CefRequestCToCpp::Wrap(request)); + + // Return type: refptr_same + return CefResourceHandlerCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefSchemeHandlerFactoryCppToC::CefSchemeHandlerFactoryCppToC( + CefSchemeHandlerFactory* cls) + : CefCppToC(cls) { + struct_.struct_.create = scheme_handler_factory_create; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h new file mode 100644 index 000000000..82bfa1c68 --- /dev/null +++ b/libcef_dll/cpptoc/scheme_handler_factory_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_SCHEME_HANDLER_FACTORY_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_SCHEME_HANDLER_FACTORY_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefSchemeHandlerFactoryCppToC + : public CefCppToC { + public: + explicit CefSchemeHandlerFactoryCppToC(CefSchemeHandlerFactory* cls); + virtual ~CefSchemeHandlerFactoryCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_SCHEME_HANDLER_FACTORY_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc b/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc new file mode 100644 index 000000000..18a04edaa --- /dev/null +++ b/libcef_dll/cpptoc/scheme_registrar_cpptoc.cc @@ -0,0 +1,55 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK scheme_registrar_add_custom_scheme( + struct _cef_scheme_registrar_t* self, const cef_string_t* scheme_name, + int is_standard, int is_local, int is_display_isolated) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: scheme_name; type: string_byref_const + DCHECK(scheme_name); + if (!scheme_name) + return 0; + + // Execute + bool _retval = CefSchemeRegistrarCppToC::Get(self)->AddCustomScheme( + CefString(scheme_name), + is_standard?true:false, + is_local?true:false, + is_display_isolated?true:false); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefSchemeRegistrarCppToC::CefSchemeRegistrarCppToC(CefSchemeRegistrar* cls) + : CefCppToC(cls) { + struct_.struct_.add_custom_scheme = scheme_registrar_add_custom_scheme; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/scheme_registrar_cpptoc.h b/libcef_dll/cpptoc/scheme_registrar_cpptoc.h new file mode 100644 index 000000000..5d719bc0d --- /dev/null +++ b/libcef_dll/cpptoc/scheme_registrar_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefSchemeRegistrarCppToC + : public CefCppToC { + public: + explicit CefSchemeRegistrarCppToC(CefSchemeRegistrar* cls); + virtual ~CefSchemeRegistrarCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_SCHEME_REGISTRAR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/stream_reader_cpptoc.cc b/libcef_dll/cpptoc/stream_reader_cpptoc.cc new file mode 100644 index 000000000..c628bb8e5 --- /dev/null +++ b/libcef_dll/cpptoc/stream_reader_cpptoc.cc @@ -0,0 +1,172 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/stream_reader_cpptoc.h" +#include "libcef_dll/ctocpp/read_handler_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_file( + const cef_string_t* fileName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(fileName); + if (!fileName) + return NULL; + + // Execute + CefRefPtr _retval = CefStreamReader::CreateForFile( + CefString(fileName)); + + // Return type: refptr_same + return CefStreamReaderCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_data(void* data, + size_t size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return NULL; + + // Execute + CefRefPtr _retval = CefStreamReader::CreateForData( + data, + size); + + // Return type: refptr_same + return CefStreamReaderCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_stream_reader_t* cef_stream_reader_create_for_handler( + cef_read_handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: handler; type: refptr_diff + DCHECK(handler); + if (!handler) + return NULL; + + // Execute + CefRefPtr _retval = CefStreamReader::CreateForHandler( + CefReadHandlerCToCpp::Wrap(handler)); + + // Return type: refptr_same + return CefStreamReaderCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +size_t CEF_CALLBACK stream_reader_read(struct _cef_stream_reader_t* self, + void* ptr, size_t size, size_t n) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = CefStreamReaderCppToC::Get(self)->Read( + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_reader_seek(struct _cef_stream_reader_t* self, + int64 offset, int whence) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefStreamReaderCppToC::Get(self)->Seek( + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK stream_reader_tell(struct _cef_stream_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefStreamReaderCppToC::Get(self)->Tell(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_reader_eof(struct _cef_stream_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefStreamReaderCppToC::Get(self)->Eof(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_reader_may_block(struct _cef_stream_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefStreamReaderCppToC::Get(self)->MayBlock(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefStreamReaderCppToC::CefStreamReaderCppToC(CefStreamReader* cls) + : CefCppToC( + cls) { + struct_.struct_.read = stream_reader_read; + struct_.struct_.seek = stream_reader_seek; + struct_.struct_.tell = stream_reader_tell; + struct_.struct_.eof = stream_reader_eof; + struct_.struct_.may_block = stream_reader_may_block; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/stream_reader_cpptoc.h b/libcef_dll/cpptoc/stream_reader_cpptoc.h new file mode 100644 index 000000000..8eb3dcd48 --- /dev/null +++ b/libcef_dll/cpptoc/stream_reader_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_STREAM_READER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_STREAM_READER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefStreamReaderCppToC + : public CefCppToC { + public: + explicit CefStreamReaderCppToC(CefStreamReader* cls); + virtual ~CefStreamReaderCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_STREAM_READER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/stream_writer_cpptoc.cc b/libcef_dll/cpptoc/stream_writer_cpptoc.cc new file mode 100644 index 000000000..b362baf6a --- /dev/null +++ b/libcef_dll/cpptoc/stream_writer_cpptoc.cc @@ -0,0 +1,154 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/stream_writer_cpptoc.h" +#include "libcef_dll/ctocpp/write_handler_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_file( + const cef_string_t* fileName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(fileName); + if (!fileName) + return NULL; + + // Execute + CefRefPtr _retval = CefStreamWriter::CreateForFile( + CefString(fileName)); + + // Return type: refptr_same + return CefStreamWriterCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_handler( + cef_write_handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: handler; type: refptr_diff + DCHECK(handler); + if (!handler) + return NULL; + + // Execute + CefRefPtr _retval = CefStreamWriter::CreateForHandler( + CefWriteHandlerCToCpp::Wrap(handler)); + + // Return type: refptr_same + return CefStreamWriterCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +size_t CEF_CALLBACK stream_writer_write(struct _cef_stream_writer_t* self, + const void* ptr, size_t size, size_t n) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = CefStreamWriterCppToC::Get(self)->Write( + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_writer_seek(struct _cef_stream_writer_t* self, + int64 offset, int whence) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefStreamWriterCppToC::Get(self)->Seek( + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK stream_writer_tell(struct _cef_stream_writer_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefStreamWriterCppToC::Get(self)->Tell(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_writer_flush(struct _cef_stream_writer_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefStreamWriterCppToC::Get(self)->Flush(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK stream_writer_may_block(struct _cef_stream_writer_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefStreamWriterCppToC::Get(self)->MayBlock(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefStreamWriterCppToC::CefStreamWriterCppToC(CefStreamWriter* cls) + : CefCppToC( + cls) { + struct_.struct_.write = stream_writer_write; + struct_.struct_.seek = stream_writer_seek; + struct_.struct_.tell = stream_writer_tell; + struct_.struct_.flush = stream_writer_flush; + struct_.struct_.may_block = stream_writer_may_block; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/stream_writer_cpptoc.h b/libcef_dll/cpptoc/stream_writer_cpptoc.h new file mode 100644 index 000000000..f94ca001f --- /dev/null +++ b/libcef_dll/cpptoc/stream_writer_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_STREAM_WRITER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_STREAM_WRITER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefStreamWriterCppToC + : public CefCppToC { + public: + explicit CefStreamWriterCppToC(CefStreamWriter* cls); + virtual ~CefStreamWriterCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_STREAM_WRITER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/string_visitor_cpptoc.cc b/libcef_dll/cpptoc/string_visitor_cpptoc.cc new file mode 100644 index 000000000..a09cefcaa --- /dev/null +++ b/libcef_dll/cpptoc/string_visitor_cpptoc.cc @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/string_visitor_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK string_visitor_visit(struct _cef_string_visitor_t* self, + const cef_string_t* string) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: string + + // Execute + CefStringVisitorCppToC::Get(self)->Visit( + CefString(string)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefStringVisitorCppToC::CefStringVisitorCppToC(CefStringVisitor* cls) + : CefCppToC( + cls) { + struct_.struct_.visit = string_visitor_visit; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/string_visitor_cpptoc.h b/libcef_dll/cpptoc/string_visitor_cpptoc.h new file mode 100644 index 000000000..8b24a92cb --- /dev/null +++ b/libcef_dll/cpptoc/string_visitor_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_STRING_VISITOR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_STRING_VISITOR_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_string_visitor.h" +#include "include/capi/cef_string_visitor_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefStringVisitorCppToC + : public CefCppToC { + public: + explicit CefStringVisitorCppToC(CefStringVisitor* cls); + virtual ~CefStringVisitorCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_STRING_VISITOR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/task_cpptoc.cc b/libcef_dll/cpptoc/task_cpptoc.cc new file mode 100644 index 000000000..d85f58b9e --- /dev/null +++ b/libcef_dll/cpptoc/task_cpptoc.cc @@ -0,0 +1,41 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/task_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK task_execute(struct _cef_task_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefTaskCppToC::Get(self)->Execute(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefTaskCppToC::CefTaskCppToC(CefTask* cls) + : CefCppToC(cls) { + struct_.struct_.execute = task_execute; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/task_cpptoc.h b/libcef_dll/cpptoc/task_cpptoc.h new file mode 100644 index 000000000..118ef926b --- /dev/null +++ b/libcef_dll/cpptoc/task_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_TASK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_TASK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefTaskCppToC + : public CefCppToC { + public: + explicit CefTaskCppToC(CefTask* cls); + virtual ~CefTaskCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_TASK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/task_runner_cpptoc.cc b/libcef_dll/cpptoc/task_runner_cpptoc.cc new file mode 100644 index 000000000..7647e0fe9 --- /dev/null +++ b/libcef_dll/cpptoc/task_runner_cpptoc.cc @@ -0,0 +1,153 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/task_runner_cpptoc.h" +#include "libcef_dll/ctocpp/task_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefTaskRunner::GetForCurrentThread(); + + // Return type: refptr_same + return CefTaskRunnerCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_thread( + cef_thread_id_t threadId) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefTaskRunner::GetForThread( + threadId); + + // Return type: refptr_same + return CefTaskRunnerCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK task_runner_is_same(struct _cef_task_runner_t* self, + struct _cef_task_runner_t* that) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: that; type: refptr_same + DCHECK(that); + if (!that) + return 0; + + // Execute + bool _retval = CefTaskRunnerCppToC::Get(self)->IsSame( + CefTaskRunnerCppToC::Unwrap(that)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK task_runner_belongs_to_current_thread( + struct _cef_task_runner_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToCurrentThread(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK task_runner_belongs_to_thread(struct _cef_task_runner_t* self, + cef_thread_id_t threadId) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToThread( + threadId); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK task_runner_post_task(struct _cef_task_runner_t* self, + cef_task_t* task) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: task; type: refptr_diff + DCHECK(task); + if (!task) + return 0; + + // Execute + bool _retval = CefTaskRunnerCppToC::Get(self)->PostTask( + CefTaskCToCpp::Wrap(task)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK task_runner_post_delayed_task(struct _cef_task_runner_t* self, + cef_task_t* task, int64 delay_ms) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: task; type: refptr_diff + DCHECK(task); + if (!task) + return 0; + + // Execute + bool _retval = CefTaskRunnerCppToC::Get(self)->PostDelayedTask( + CefTaskCToCpp::Wrap(task), + delay_ms); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefTaskRunnerCppToC::CefTaskRunnerCppToC(CefTaskRunner* cls) + : CefCppToC(cls) { + struct_.struct_.is_same = task_runner_is_same; + struct_.struct_.belongs_to_current_thread = + task_runner_belongs_to_current_thread; + struct_.struct_.belongs_to_thread = task_runner_belongs_to_thread; + struct_.struct_.post_task = task_runner_post_task; + struct_.struct_.post_delayed_task = task_runner_post_delayed_task; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/task_runner_cpptoc.h b/libcef_dll/cpptoc/task_runner_cpptoc.h new file mode 100644 index 000000000..8d0c67143 --- /dev/null +++ b/libcef_dll/cpptoc/task_runner_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefTaskRunnerCppToC + : public CefCppToC { + public: + explicit CefTaskRunnerCppToC(CefTaskRunner* cls); + virtual ~CefTaskRunnerCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc new file mode 100644 index 000000000..8a770ec66 --- /dev/null +++ b/libcef_dll/cpptoc/urlrequest_client_cpptoc.cc @@ -0,0 +1,154 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" +#include "libcef_dll/ctocpp/auth_callback_ctocpp.h" +#include "libcef_dll/ctocpp/urlrequest_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK urlrequest_client_on_request_complete( + struct _cef_urlrequest_client_t* self, cef_urlrequest_t* request) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return; + + // Execute + CefURLRequestClientCppToC::Get(self)->OnRequestComplete( + CefURLRequestCToCpp::Wrap(request)); +} + +void CEF_CALLBACK urlrequest_client_on_upload_progress( + struct _cef_urlrequest_client_t* self, cef_urlrequest_t* request, + uint64 current, uint64 total) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return; + + // Execute + CefURLRequestClientCppToC::Get(self)->OnUploadProgress( + CefURLRequestCToCpp::Wrap(request), + current, + total); +} + +void CEF_CALLBACK urlrequest_client_on_download_progress( + struct _cef_urlrequest_client_t* self, cef_urlrequest_t* request, + uint64 current, uint64 total) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return; + + // Execute + CefURLRequestClientCppToC::Get(self)->OnDownloadProgress( + CefURLRequestCToCpp::Wrap(request), + current, + total); +} + +void CEF_CALLBACK urlrequest_client_on_download_data( + struct _cef_urlrequest_client_t* self, cef_urlrequest_t* request, + const void* data, size_t data_length) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: request; type: refptr_diff + DCHECK(request); + if (!request) + return; + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return; + + // Execute + CefURLRequestClientCppToC::Get(self)->OnDownloadData( + CefURLRequestCToCpp::Wrap(request), + data, + data_length); +} + +int CEF_CALLBACK urlrequest_client_get_auth_credentials( + struct _cef_urlrequest_client_t* self, int isProxy, + const cef_string_t* host, int port, const cef_string_t* realm, + const cef_string_t* scheme, cef_auth_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: host; type: string_byref_const + DCHECK(host); + if (!host) + return 0; + // Verify param: scheme; type: string_byref_const + DCHECK(scheme); + if (!scheme) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Unverified params: realm + + // Execute + bool _retval = CefURLRequestClientCppToC::Get(self)->GetAuthCredentials( + isProxy?true:false, + CefString(host), + port, + CefString(realm), + CefString(scheme), + CefAuthCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefURLRequestClientCppToC::CefURLRequestClientCppToC(CefURLRequestClient* cls) + : CefCppToC(cls) { + struct_.struct_.on_request_complete = urlrequest_client_on_request_complete; + struct_.struct_.on_upload_progress = urlrequest_client_on_upload_progress; + struct_.struct_.on_download_progress = urlrequest_client_on_download_progress; + struct_.struct_.on_download_data = urlrequest_client_on_download_data; + struct_.struct_.get_auth_credentials = urlrequest_client_get_auth_credentials; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/urlrequest_client_cpptoc.h b/libcef_dll/cpptoc/urlrequest_client_cpptoc.h new file mode 100644 index 000000000..ff185d684 --- /dev/null +++ b/libcef_dll/cpptoc/urlrequest_client_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CLIENT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CLIENT_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_urlrequest.h" +#include "include/capi/cef_urlrequest_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefURLRequestClientCppToC + : public CefCppToC { + public: + explicit CefURLRequestClientCppToC(CefURLRequestClient* cls); + virtual ~CefURLRequestClientCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CLIENT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/urlrequest_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_cpptoc.cc new file mode 100644 index 000000000..d2c08e2f5 --- /dev/null +++ b/libcef_dll/cpptoc/urlrequest_cpptoc.cc @@ -0,0 +1,152 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/response_cpptoc.h" +#include "libcef_dll/cpptoc/urlrequest_cpptoc.h" +#include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create(cef_request_t* request, + struct _cef_urlrequest_client_t* client) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_same + DCHECK(request); + if (!request) + return NULL; + // Verify param: client; type: refptr_diff + DCHECK(client); + if (!client) + return NULL; + + // Execute + CefRefPtr _retval = CefURLRequest::Create( + CefRequestCppToC::Unwrap(request), + CefURLRequestClientCToCpp::Wrap(client)); + + // Return type: refptr_same + return CefURLRequestCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_request_t* CEF_CALLBACK urlrequest_get_request( + struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefURLRequestCppToC::Get(self)->GetRequest(); + + // Return type: refptr_same + return CefRequestCppToC::Wrap(_retval); +} + +struct _cef_urlrequest_client_t* CEF_CALLBACK urlrequest_get_client( + struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefURLRequestCppToC::Get( + self)->GetClient(); + + // Return type: refptr_diff + return CefURLRequestClientCToCpp::Unwrap(_retval); +} + +cef_urlrequest_status_t CEF_CALLBACK urlrequest_get_request_status( + struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return UR_UNKNOWN; + + // Execute + cef_urlrequest_status_t _retval = CefURLRequestCppToC::Get( + self)->GetRequestStatus(); + + // Return type: simple + return _retval; +} + +cef_errorcode_t CEF_CALLBACK urlrequest_get_request_error( + struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return ERR_NONE; + + // Execute + cef_errorcode_t _retval = CefURLRequestCppToC::Get(self)->GetRequestError(); + + // Return type: simple + return _retval; +} + +cef_response_t* CEF_CALLBACK urlrequest_get_response( + struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefURLRequestCppToC::Get(self)->GetResponse( + ); + + // Return type: refptr_same + return CefResponseCppToC::Wrap(_retval); +} + +void CEF_CALLBACK urlrequest_cancel(struct _cef_urlrequest_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefURLRequestCppToC::Get(self)->Cancel(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefURLRequestCppToC::CefURLRequestCppToC(CefURLRequest* cls) + : CefCppToC(cls) { + struct_.struct_.get_request = urlrequest_get_request; + struct_.struct_.get_client = urlrequest_get_client; + struct_.struct_.get_request_status = urlrequest_get_request_status; + struct_.struct_.get_request_error = urlrequest_get_request_error; + struct_.struct_.get_response = urlrequest_get_response; + struct_.struct_.cancel = urlrequest_cancel; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/urlrequest_cpptoc.h b/libcef_dll/cpptoc/urlrequest_cpptoc.h new file mode 100644 index 000000000..6bd1d585a --- /dev/null +++ b/libcef_dll/cpptoc/urlrequest_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_urlrequest.h" +#include "include/capi/cef_urlrequest_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefURLRequestCppToC + : public CefCppToC { + public: + explicit CefURLRequestCppToC(CefURLRequest* cls); + virtual ~CefURLRequestCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_URLREQUEST_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8accessor_cpptoc.cc b/libcef_dll/cpptoc/v8accessor_cpptoc.cc new file mode 100644 index 000000000..20b101e13 --- /dev/null +++ b/libcef_dll/cpptoc/v8accessor_cpptoc.cc @@ -0,0 +1,126 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8accessor_cpptoc.h" +#include "libcef_dll/ctocpp/v8value_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK v8accessor_get(struct _cef_v8accessor_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + struct _cef_v8value_t** retval, cef_string_t* exception) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return 0; + // Verify param: object; type: refptr_diff + DCHECK(object); + if (!object) + return 0; + // Verify param: retval; type: refptr_diff_byref + DCHECK(retval); + if (!retval) + return 0; + // Verify param: exception; type: string_byref + DCHECK(exception); + if (!exception) + return 0; + + // Translate param: retval; type: refptr_diff_byref + CefRefPtr retvalPtr; + if (retval && *retval) + retvalPtr = CefV8ValueCToCpp::Wrap(*retval); + CefV8Value* retvalOrig = retvalPtr.get(); + // Translate param: exception; type: string_byref + CefString exceptionStr(exception); + + // Execute + bool _retval = CefV8AccessorCppToC::Get(self)->Get( + CefString(name), + CefV8ValueCToCpp::Wrap(object), + retvalPtr, + exceptionStr); + + // Restore param: retval; type: refptr_diff_byref + if (retval) { + if (retvalPtr.get()) { + if (retvalPtr.get() != retvalOrig) { + *retval = CefV8ValueCToCpp::Unwrap(retvalPtr); + } + } else { + *retval = NULL; + } + } + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8accessor_set(struct _cef_v8accessor_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + struct _cef_v8value_t* value, cef_string_t* exception) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return 0; + // Verify param: object; type: refptr_diff + DCHECK(object); + if (!object) + return 0; + // Verify param: value; type: refptr_diff + DCHECK(value); + if (!value) + return 0; + // Verify param: exception; type: string_byref + DCHECK(exception); + if (!exception) + return 0; + + // Translate param: exception; type: string_byref + CefString exceptionStr(exception); + + // Execute + bool _retval = CefV8AccessorCppToC::Get(self)->Set( + CefString(name), + CefV8ValueCToCpp::Wrap(object), + CefV8ValueCToCpp::Wrap(value), + exceptionStr); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8AccessorCppToC::CefV8AccessorCppToC(CefV8Accessor* cls) + : CefCppToC(cls) { + struct_.struct_.get = v8accessor_get; + struct_.struct_.set = v8accessor_set; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8accessor_cpptoc.h b/libcef_dll/cpptoc/v8accessor_cpptoc.h new file mode 100644 index 000000000..d73e8ca3b --- /dev/null +++ b/libcef_dll/cpptoc/v8accessor_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8ACCESSOR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8ACCESSOR_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefV8AccessorCppToC + : public CefCppToC { + public: + explicit CefV8AccessorCppToC(CefV8Accessor* cls); + virtual ~CefV8AccessorCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8ACCESSOR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8context_cpptoc.cc b/libcef_dll/cpptoc/v8context_cpptoc.cc new file mode 100644 index 000000000..41614beee --- /dev/null +++ b/libcef_dll/cpptoc/v8context_cpptoc.cc @@ -0,0 +1,261 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/task_runner_cpptoc.h" +#include "libcef_dll/cpptoc/v8context_cpptoc.h" +#include "libcef_dll/cpptoc/v8exception_cpptoc.h" +#include "libcef_dll/cpptoc/v8value_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Context::GetCurrentContext(); + + // Return type: refptr_same + return CefV8ContextCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Context::GetEnteredContext(); + + // Return type: refptr_same + return CefV8ContextCppToC::Wrap(_retval); +} + +CEF_EXPORT int cef_v8context_in_context() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + bool _retval = CefV8Context::InContext(); + + // Return type: bool + return _retval; +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_task_runner_t* CEF_CALLBACK v8context_get_task_runner( + struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ContextCppToC::Get( + self)->GetTaskRunner(); + + // Return type: refptr_same + return CefTaskRunnerCppToC::Wrap(_retval); +} + +int CEF_CALLBACK v8context_is_valid(struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ContextCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +cef_browser_t* CEF_CALLBACK v8context_get_browser( + struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ContextCppToC::Get(self)->GetBrowser(); + + // Return type: refptr_same + return CefBrowserCppToC::Wrap(_retval); +} + +cef_frame_t* CEF_CALLBACK v8context_get_frame(struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ContextCppToC::Get(self)->GetFrame(); + + // Return type: refptr_same + return CefFrameCppToC::Wrap(_retval); +} + +struct _cef_v8value_t* CEF_CALLBACK v8context_get_global( + struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ContextCppToC::Get(self)->GetGlobal(); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +int CEF_CALLBACK v8context_enter(struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ContextCppToC::Get(self)->Enter(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8context_exit(struct _cef_v8context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ContextCppToC::Get(self)->Exit(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8context_is_same(struct _cef_v8context_t* self, + struct _cef_v8context_t* that) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: that; type: refptr_same + DCHECK(that); + if (!that) + return 0; + + // Execute + bool _retval = CefV8ContextCppToC::Get(self)->IsSame( + CefV8ContextCppToC::Unwrap(that)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8context_eval(struct _cef_v8context_t* self, + const cef_string_t* code, struct _cef_v8value_t** retval, + struct _cef_v8exception_t** exception) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: code; type: string_byref_const + DCHECK(code); + if (!code) + return 0; + // Verify param: retval; type: refptr_same_byref + DCHECK(retval); + if (!retval) + return 0; + // Verify param: exception; type: refptr_same_byref + DCHECK(exception); + if (!exception) + return 0; + + // Translate param: retval; type: refptr_same_byref + CefRefPtr retvalPtr; + if (retval && *retval) + retvalPtr = CefV8ValueCppToC::Unwrap(*retval); + CefV8Value* retvalOrig = retvalPtr.get(); + // Translate param: exception; type: refptr_same_byref + CefRefPtr exceptionPtr; + if (exception && *exception) + exceptionPtr = CefV8ExceptionCppToC::Unwrap(*exception); + CefV8Exception* exceptionOrig = exceptionPtr.get(); + + // Execute + bool _retval = CefV8ContextCppToC::Get(self)->Eval( + CefString(code), + retvalPtr, + exceptionPtr); + + // Restore param: retval; type: refptr_same_byref + if (retval) { + if (retvalPtr.get()) { + if (retvalPtr.get() != retvalOrig) { + *retval = CefV8ValueCppToC::Wrap(retvalPtr); + } + } else { + *retval = NULL; + } + } + // Restore param: exception; type: refptr_same_byref + if (exception) { + if (exceptionPtr.get()) { + if (exceptionPtr.get() != exceptionOrig) { + *exception = CefV8ExceptionCppToC::Wrap(exceptionPtr); + } + } else { + *exception = NULL; + } + } + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8ContextCppToC::CefV8ContextCppToC(CefV8Context* cls) + : CefCppToC(cls) { + struct_.struct_.get_task_runner = v8context_get_task_runner; + struct_.struct_.is_valid = v8context_is_valid; + struct_.struct_.get_browser = v8context_get_browser; + struct_.struct_.get_frame = v8context_get_frame; + struct_.struct_.get_global = v8context_get_global; + struct_.struct_.enter = v8context_enter; + struct_.struct_.exit = v8context_exit; + struct_.struct_.is_same = v8context_is_same; + struct_.struct_.eval = v8context_eval; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8context_cpptoc.h b/libcef_dll/cpptoc/v8context_cpptoc.h new file mode 100644 index 000000000..278f0a7ec --- /dev/null +++ b/libcef_dll/cpptoc/v8context_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8CONTEXT_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8CONTEXT_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefV8ContextCppToC + : public CefCppToC { + public: + explicit CefV8ContextCppToC(CefV8Context* cls); + virtual ~CefV8ContextCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8CONTEXT_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8exception_cpptoc.cc b/libcef_dll/cpptoc/v8exception_cpptoc.cc new file mode 100644 index 000000000..77380a9f8 --- /dev/null +++ b/libcef_dll/cpptoc/v8exception_cpptoc.cc @@ -0,0 +1,154 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8exception_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_string_userfree_t CEF_CALLBACK v8exception_get_message( + struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8ExceptionCppToC::Get(self)->GetMessage(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK v8exception_get_source_line( + struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8ExceptionCppToC::Get(self)->GetSourceLine(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK v8exception_get_script_resource_name( + struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8ExceptionCppToC::Get(self)->GetScriptResourceName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK v8exception_get_line_number(struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ExceptionCppToC::Get(self)->GetLineNumber(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8exception_get_start_position( + struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ExceptionCppToC::Get(self)->GetStartPosition(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8exception_get_end_position(struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ExceptionCppToC::Get(self)->GetEndPosition(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8exception_get_start_column(struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ExceptionCppToC::Get(self)->GetStartColumn(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8exception_get_end_column(struct _cef_v8exception_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ExceptionCppToC::Get(self)->GetEndColumn(); + + // Return type: simple + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8ExceptionCppToC::CefV8ExceptionCppToC(CefV8Exception* cls) + : CefCppToC(cls) { + struct_.struct_.get_message = v8exception_get_message; + struct_.struct_.get_source_line = v8exception_get_source_line; + struct_.struct_.get_script_resource_name = + v8exception_get_script_resource_name; + struct_.struct_.get_line_number = v8exception_get_line_number; + struct_.struct_.get_start_position = v8exception_get_start_position; + struct_.struct_.get_end_position = v8exception_get_end_position; + struct_.struct_.get_start_column = v8exception_get_start_column; + struct_.struct_.get_end_column = v8exception_get_end_column; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8exception_cpptoc.h b/libcef_dll/cpptoc/v8exception_cpptoc.h new file mode 100644 index 000000000..5f9a789ea --- /dev/null +++ b/libcef_dll/cpptoc/v8exception_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8EXCEPTION_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8EXCEPTION_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefV8ExceptionCppToC + : public CefCppToC { + public: + explicit CefV8ExceptionCppToC(CefV8Exception* cls); + virtual ~CefV8ExceptionCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8EXCEPTION_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8handler_cpptoc.cc b/libcef_dll/cpptoc/v8handler_cpptoc.cc new file mode 100644 index 000000000..0b34e56ac --- /dev/null +++ b/libcef_dll/cpptoc/v8handler_cpptoc.cc @@ -0,0 +1,99 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8handler_cpptoc.h" +#include "libcef_dll/ctocpp/v8value_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK v8handler_execute(struct _cef_v8handler_t* self, + const cef_string_t* name, struct _cef_v8value_t* object, + size_t argumentsCount, struct _cef_v8value_t* const* arguments, + struct _cef_v8value_t** retval, cef_string_t* exception) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return 0; + // Verify param: object; type: refptr_diff + DCHECK(object); + if (!object) + return 0; + // Verify param: arguments; type: refptr_vec_diff_byref_const + DCHECK(argumentsCount == 0 || arguments); + if (argumentsCount > 0 && !arguments) + return 0; + // Verify param: retval; type: refptr_diff_byref + DCHECK(retval); + if (!retval) + return 0; + // Verify param: exception; type: string_byref + DCHECK(exception); + if (!exception) + return 0; + + // Translate param: arguments; type: refptr_vec_diff_byref_const + std::vector > argumentsList; + if (argumentsCount > 0) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList.push_back(CefV8ValueCToCpp::Wrap(arguments[i])); + } + } + // Translate param: retval; type: refptr_diff_byref + CefRefPtr retvalPtr; + if (retval && *retval) + retvalPtr = CefV8ValueCToCpp::Wrap(*retval); + CefV8Value* retvalOrig = retvalPtr.get(); + // Translate param: exception; type: string_byref + CefString exceptionStr(exception); + + // Execute + bool _retval = CefV8HandlerCppToC::Get(self)->Execute( + CefString(name), + CefV8ValueCToCpp::Wrap(object), + argumentsList, + retvalPtr, + exceptionStr); + + // Restore param: retval; type: refptr_diff_byref + if (retval) { + if (retvalPtr.get()) { + if (retvalPtr.get() != retvalOrig) { + *retval = CefV8ValueCToCpp::Unwrap(retvalPtr); + } + } else { + *retval = NULL; + } + } + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8HandlerCppToC::CefV8HandlerCppToC(CefV8Handler* cls) + : CefCppToC(cls) { + struct_.struct_.execute = v8handler_execute; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8handler_cpptoc.h b/libcef_dll/cpptoc/v8handler_cpptoc.h new file mode 100644 index 000000000..e2cbe1a79 --- /dev/null +++ b/libcef_dll/cpptoc/v8handler_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefV8HandlerCppToC + : public CefCppToC { + public: + explicit CefV8HandlerCppToC(CefV8Handler* cls); + virtual ~CefV8HandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc b/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc new file mode 100644 index 000000000..94b52dc72 --- /dev/null +++ b/libcef_dll/cpptoc/v8stack_frame_cpptoc.cc @@ -0,0 +1,157 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK v8stack_frame_is_valid(struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8StackFrameCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_script_name( + struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8StackFrameCppToC::Get(self)->GetScriptName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_script_name_or_source_url( + struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8StackFrameCppToC::Get( + self)->GetScriptNameOrSourceURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK v8stack_frame_get_function_name( + struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8StackFrameCppToC::Get(self)->GetFunctionName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK v8stack_frame_get_line_number( + struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8StackFrameCppToC::Get(self)->GetLineNumber(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8stack_frame_get_column(struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8StackFrameCppToC::Get(self)->GetColumn(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8stack_frame_is_eval(struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8StackFrameCppToC::Get(self)->IsEval(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8stack_frame_is_constructor( + struct _cef_v8stack_frame_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8StackFrameCppToC::Get(self)->IsConstructor(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8StackFrameCppToC::CefV8StackFrameCppToC(CefV8StackFrame* cls) + : CefCppToC( + cls) { + struct_.struct_.is_valid = v8stack_frame_is_valid; + struct_.struct_.get_script_name = v8stack_frame_get_script_name; + struct_.struct_.get_script_name_or_source_url = + v8stack_frame_get_script_name_or_source_url; + struct_.struct_.get_function_name = v8stack_frame_get_function_name; + struct_.struct_.get_line_number = v8stack_frame_get_line_number; + struct_.struct_.get_column = v8stack_frame_get_column; + struct_.struct_.is_eval = v8stack_frame_is_eval; + struct_.struct_.is_constructor = v8stack_frame_is_constructor; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8stack_frame_cpptoc.h b/libcef_dll/cpptoc/v8stack_frame_cpptoc.h new file mode 100644 index 000000000..843d3f258 --- /dev/null +++ b/libcef_dll/cpptoc/v8stack_frame_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefV8StackFrameCppToC + : public CefCppToC { + public: + explicit CefV8StackFrameCppToC(CefV8StackFrame* cls); + virtual ~CefV8StackFrameCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8STACK_FRAME_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc b/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc new file mode 100644 index 000000000..53dd94fa0 --- /dev/null +++ b/libcef_dll/cpptoc/v8stack_trace_cpptoc.cc @@ -0,0 +1,94 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h" +#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8StackTrace::GetCurrent( + frame_limit); + + // Return type: refptr_same + return CefV8StackTraceCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK v8stack_trace_is_valid(struct _cef_v8stack_trace_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8StackTraceCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8stack_trace_get_frame_count( + struct _cef_v8stack_trace_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8StackTraceCppToC::Get(self)->GetFrameCount(); + + // Return type: simple + return _retval; +} + +struct _cef_v8stack_frame_t* CEF_CALLBACK v8stack_trace_get_frame( + struct _cef_v8stack_trace_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8StackTraceCppToC::Get( + self)->GetFrame( + index); + + // Return type: refptr_same + return CefV8StackFrameCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8StackTraceCppToC::CefV8StackTraceCppToC(CefV8StackTrace* cls) + : CefCppToC( + cls) { + struct_.struct_.is_valid = v8stack_trace_is_valid; + struct_.struct_.get_frame_count = v8stack_trace_get_frame_count; + struct_.struct_.get_frame = v8stack_trace_get_frame; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8stack_trace_cpptoc.h b/libcef_dll/cpptoc/v8stack_trace_cpptoc.h new file mode 100644 index 000000000..a3c5ee552 --- /dev/null +++ b/libcef_dll/cpptoc/v8stack_trace_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefV8StackTraceCppToC + : public CefCppToC { + public: + explicit CefV8StackTraceCppToC(CefV8StackTrace* cls); + virtual ~CefV8StackTraceCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8STACK_TRACE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/v8value_cpptoc.cc b/libcef_dll/cpptoc/v8value_cpptoc.cc new file mode 100644 index 000000000..7cfacb499 --- /dev/null +++ b/libcef_dll/cpptoc/v8value_cpptoc.cc @@ -0,0 +1,973 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8context_cpptoc.h" +#include "libcef_dll/cpptoc/v8exception_cpptoc.h" +#include "libcef_dll/cpptoc/v8value_cpptoc.h" +#include "libcef_dll/ctocpp/base_ctocpp.h" +#include "libcef_dll/ctocpp/v8accessor_ctocpp.h" +#include "libcef_dll/ctocpp/v8handler_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_v8value_t* cef_v8value_create_undefined() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateUndefined(); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_null() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateNull(); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_bool(int value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateBool( + value?true:false); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_int(int32 value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateInt( + value); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_uint(uint32 value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateUInt( + value); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_double(double value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateDouble( + value); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: date; type: simple_byref_const + DCHECK(date); + if (!date) + return NULL; + + // Translate param: date; type: simple_byref_const + CefTime dateVal = date?*date:CefTime(); + + // Execute + CefRefPtr _retval = CefV8Value::CreateDate( + dateVal); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: value + + // Execute + CefRefPtr _retval = CefV8Value::CreateString( + CefString(value)); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_object( + cef_v8accessor_t* accessor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: accessor + + // Execute + CefRefPtr _retval = CefV8Value::CreateObject( + CefV8AccessorCToCpp::Wrap(accessor)); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_array(int length) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefV8Value::CreateArray( + length); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name, + cef_v8handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(name); + if (!name) + return NULL; + // Verify param: handler; type: refptr_diff + DCHECK(handler); + if (!handler) + return NULL; + + // Execute + CefRefPtr _retval = CefV8Value::CreateFunction( + CefString(name), + CefV8HandlerCToCpp::Wrap(handler)); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK v8value_is_valid(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsValid(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_undefined(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsUndefined(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_null(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsNull(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_bool(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsBool(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_int(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsInt(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_uint(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsUInt(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_double(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsDouble(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_date(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsDate(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_string(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsString(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_object(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsObject(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_array(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsArray(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_function(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsFunction(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_is_same(struct _cef_v8value_t* self, + struct _cef_v8value_t* that) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: that; type: refptr_same + DCHECK(that); + if (!that) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsSame( + CefV8ValueCppToC::Unwrap(that)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_get_bool_value(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->GetBoolValue(); + + // Return type: bool + return _retval; +} + +int32 CEF_CALLBACK v8value_get_int_value(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int32 _retval = CefV8ValueCppToC::Get(self)->GetIntValue(); + + // Return type: simple + return _retval; +} + +uint32 CEF_CALLBACK v8value_get_uint_value(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + uint32 _retval = CefV8ValueCppToC::Get(self)->GetUIntValue(); + + // Return type: simple + return _retval; +} + +double CEF_CALLBACK v8value_get_double_value(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + double _retval = CefV8ValueCppToC::Get(self)->GetDoubleValue(); + + // Return type: simple + return _retval; +} + +cef_time_t CEF_CALLBACK v8value_get_date_value(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CefTime(); + + // Execute + cef_time_t _retval = CefV8ValueCppToC::Get(self)->GetDateValue(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK v8value_get_string_value( + struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8ValueCppToC::Get(self)->GetStringValue(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK v8value_is_user_created(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->IsUserCreated(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_has_exception(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->HasException(); + + // Return type: bool + return _retval; +} + +cef_v8exception_t* CEF_CALLBACK v8value_get_exception( + struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get(self)->GetException( + ); + + // Return type: refptr_same + return CefV8ExceptionCppToC::Wrap(_retval); +} + +int CEF_CALLBACK v8value_clear_exception(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->ClearException(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_will_rethrow_exceptions(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->WillRethrowExceptions(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_set_rethrow_exceptions(struct _cef_v8value_t* self, + int rethrow) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->SetRethrowExceptions( + rethrow?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_has_value_bykey(struct _cef_v8value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: key + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->HasValue( + CefString(key)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_has_value_byindex(struct _cef_v8value_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->HasValue( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_delete_value_bykey(struct _cef_v8value_t* self, + const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: key + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->DeleteValue( + CefString(key)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_delete_value_byindex(struct _cef_v8value_t* self, + int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->DeleteValue( + index); + + // Return type: bool + return _retval; +} + +struct _cef_v8value_t* CEF_CALLBACK v8value_get_value_bykey( + struct _cef_v8value_t* self, const cef_string_t* key) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Unverified params: key + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get(self)->GetValue( + CefString(key)); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +struct _cef_v8value_t* CEF_CALLBACK v8value_get_value_byindex( + struct _cef_v8value_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get(self)->GetValue( + index); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +int CEF_CALLBACK v8value_set_value_bykey(struct _cef_v8value_t* self, + const cef_string_t* key, struct _cef_v8value_t* value, + cef_v8_propertyattribute_t attribute) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + // Unverified params: key + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->SetValue( + CefString(key), + CefV8ValueCppToC::Unwrap(value), + attribute); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_set_value_byindex(struct _cef_v8value_t* self, + int index, struct _cef_v8value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + // Verify param: value; type: refptr_same + DCHECK(value); + if (!value) + return 0; + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->SetValue( + index, + CefV8ValueCppToC::Unwrap(value)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_set_value_byaccessor(struct _cef_v8value_t* self, + const cef_string_t* key, cef_v8_accesscontrol_t settings, + cef_v8_propertyattribute_t attribute) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: key + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->SetValue( + CefString(key), + settings, + attribute); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_get_keys(struct _cef_v8value_t* self, + cef_string_list_t keys) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: keys; type: string_vec_byref + DCHECK(keys); + if (!keys) + return 0; + + // Translate param: keys; type: string_vec_byref + std::vector keysList; + transfer_string_list_contents(keys, keysList); + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->GetKeys( + keysList); + + // Restore param: keys; type: string_vec_byref + cef_string_list_clear(keys); + transfer_string_list_contents(keysList, keys); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK v8value_set_user_data(struct _cef_v8value_t* self, + cef_base_t* user_data) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: user_data + + // Execute + bool _retval = CefV8ValueCppToC::Get(self)->SetUserData( + CefBaseCToCpp::Wrap(user_data)); + + // Return type: bool + return _retval; +} + +cef_base_t* CEF_CALLBACK v8value_get_user_data(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get(self)->GetUserData(); + + // Return type: refptr_diff + return CefBaseCToCpp::Unwrap(_retval); +} + +int CEF_CALLBACK v8value_get_externally_allocated_memory( + struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ValueCppToC::Get(self)->GetExternallyAllocatedMemory(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8value_adjust_externally_allocated_memory( + struct _cef_v8value_t* self, int change_in_bytes) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ValueCppToC::Get(self)->AdjustExternallyAllocatedMemory( + change_in_bytes); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK v8value_get_array_length(struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefV8ValueCppToC::Get(self)->GetArrayLength(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK v8value_get_function_name( + struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefV8ValueCppToC::Get(self)->GetFunctionName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_v8handler_t* CEF_CALLBACK v8value_get_function_handler( + struct _cef_v8value_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get( + self)->GetFunctionHandler(); + + // Return type: refptr_diff + return CefV8HandlerCToCpp::Unwrap(_retval); +} + +struct _cef_v8value_t* CEF_CALLBACK v8value_execute_function( + struct _cef_v8value_t* self, struct _cef_v8value_t* object, + size_t argumentsCount, struct _cef_v8value_t* const* arguments) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: arguments; type: refptr_vec_same_byref_const + DCHECK(argumentsCount == 0 || arguments); + if (argumentsCount > 0 && !arguments) + return NULL; + // Unverified params: object + + // Translate param: arguments; type: refptr_vec_same_byref_const + std::vector > argumentsList; + if (argumentsCount > 0) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i])); + } + } + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get(self)->ExecuteFunction( + CefV8ValueCppToC::Unwrap(object), + argumentsList); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + +struct _cef_v8value_t* CEF_CALLBACK v8value_execute_function_with_context( + struct _cef_v8value_t* self, cef_v8context_t* context, + struct _cef_v8value_t* object, size_t argumentsCount, + struct _cef_v8value_t* const* arguments) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: context; type: refptr_same + DCHECK(context); + if (!context) + return NULL; + // Verify param: arguments; type: refptr_vec_same_byref_const + DCHECK(argumentsCount == 0 || arguments); + if (argumentsCount > 0 && !arguments) + return NULL; + // Unverified params: object + + // Translate param: arguments; type: refptr_vec_same_byref_const + std::vector > argumentsList; + if (argumentsCount > 0) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i])); + } + } + + // Execute + CefRefPtr _retval = CefV8ValueCppToC::Get( + self)->ExecuteFunctionWithContext( + CefV8ContextCppToC::Unwrap(context), + CefV8ValueCppToC::Unwrap(object), + argumentsList); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefV8ValueCppToC::CefV8ValueCppToC(CefV8Value* cls) + : CefCppToC(cls) { + struct_.struct_.is_valid = v8value_is_valid; + struct_.struct_.is_undefined = v8value_is_undefined; + struct_.struct_.is_null = v8value_is_null; + struct_.struct_.is_bool = v8value_is_bool; + struct_.struct_.is_int = v8value_is_int; + struct_.struct_.is_uint = v8value_is_uint; + struct_.struct_.is_double = v8value_is_double; + struct_.struct_.is_date = v8value_is_date; + struct_.struct_.is_string = v8value_is_string; + struct_.struct_.is_object = v8value_is_object; + struct_.struct_.is_array = v8value_is_array; + struct_.struct_.is_function = v8value_is_function; + struct_.struct_.is_same = v8value_is_same; + struct_.struct_.get_bool_value = v8value_get_bool_value; + struct_.struct_.get_int_value = v8value_get_int_value; + struct_.struct_.get_uint_value = v8value_get_uint_value; + struct_.struct_.get_double_value = v8value_get_double_value; + struct_.struct_.get_date_value = v8value_get_date_value; + struct_.struct_.get_string_value = v8value_get_string_value; + struct_.struct_.is_user_created = v8value_is_user_created; + struct_.struct_.has_exception = v8value_has_exception; + struct_.struct_.get_exception = v8value_get_exception; + struct_.struct_.clear_exception = v8value_clear_exception; + struct_.struct_.will_rethrow_exceptions = v8value_will_rethrow_exceptions; + struct_.struct_.set_rethrow_exceptions = v8value_set_rethrow_exceptions; + struct_.struct_.has_value_bykey = v8value_has_value_bykey; + struct_.struct_.has_value_byindex = v8value_has_value_byindex; + struct_.struct_.delete_value_bykey = v8value_delete_value_bykey; + struct_.struct_.delete_value_byindex = v8value_delete_value_byindex; + struct_.struct_.get_value_bykey = v8value_get_value_bykey; + struct_.struct_.get_value_byindex = v8value_get_value_byindex; + struct_.struct_.set_value_bykey = v8value_set_value_bykey; + struct_.struct_.set_value_byindex = v8value_set_value_byindex; + struct_.struct_.set_value_byaccessor = v8value_set_value_byaccessor; + struct_.struct_.get_keys = v8value_get_keys; + struct_.struct_.set_user_data = v8value_set_user_data; + struct_.struct_.get_user_data = v8value_get_user_data; + struct_.struct_.get_externally_allocated_memory = + v8value_get_externally_allocated_memory; + struct_.struct_.adjust_externally_allocated_memory = + v8value_adjust_externally_allocated_memory; + struct_.struct_.get_array_length = v8value_get_array_length; + struct_.struct_.get_function_name = v8value_get_function_name; + struct_.struct_.get_function_handler = v8value_get_function_handler; + struct_.struct_.execute_function = v8value_execute_function; + struct_.struct_.execute_function_with_context = + v8value_execute_function_with_context; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/v8value_cpptoc.h b/libcef_dll/cpptoc/v8value_cpptoc.h new file mode 100644 index 000000000..c7692f99d --- /dev/null +++ b/libcef_dll/cpptoc/v8value_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_V8VALUE_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_V8VALUE_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefV8ValueCppToC + : public CefCppToC { + public: + explicit CefV8ValueCppToC(CefV8Value* cls); + virtual ~CefV8ValueCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_V8VALUE_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc new file mode 100644 index 000000000..4df059388 --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_info_cpptoc.cc @@ -0,0 +1,94 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +cef_string_userfree_t CEF_CALLBACK web_plugin_info_get_name( + struct _cef_web_plugin_info_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK web_plugin_info_get_path( + struct _cef_web_plugin_info_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetPath(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK web_plugin_info_get_version( + struct _cef_web_plugin_info_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetVersion(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK web_plugin_info_get_description( + struct _cef_web_plugin_info_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefWebPluginInfoCppToC::Get(self)->GetDescription(); + + // Return type: string + return _retval.DetachToUserFree(); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefWebPluginInfoCppToC::CefWebPluginInfoCppToC(CefWebPluginInfo* cls) + : CefCppToC(cls) { + struct_.struct_.get_name = web_plugin_info_get_name; + struct_.struct_.get_path = web_plugin_info_get_path; + struct_.struct_.get_version = web_plugin_info_get_version; + struct_.struct_.get_description = web_plugin_info_get_description; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/web_plugin_info_cpptoc.h b/libcef_dll/cpptoc/web_plugin_info_cpptoc.h new file mode 100644 index 000000000..d18df6280 --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_info_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefWebPluginInfoCppToC + : public CefCppToC { + public: + explicit CefWebPluginInfoCppToC(CefWebPluginInfo* cls); + virtual ~CefWebPluginInfoCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc new file mode 100644 index 000000000..254e1466e --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h" +#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK web_plugin_info_visitor_visit( + struct _cef_web_plugin_info_visitor_t* self, cef_web_plugin_info_t* info, + int count, int total) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: info; type: refptr_diff + DCHECK(info); + if (!info) + return 0; + + // Execute + bool _retval = CefWebPluginInfoVisitorCppToC::Get(self)->Visit( + CefWebPluginInfoCToCpp::Wrap(info), + count, + total); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefWebPluginInfoVisitorCppToC::CefWebPluginInfoVisitorCppToC( + CefWebPluginInfoVisitor* cls) + : CefCppToC(cls) { + struct_.struct_.visit = web_plugin_info_visitor_visit; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h new file mode 100644 index 000000000..a3182ff1e --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefWebPluginInfoVisitorCppToC + : public CefCppToC { + public: + explicit CefWebPluginInfoVisitorCppToC(CefWebPluginInfoVisitor* cls); + virtual ~CefWebPluginInfoVisitorCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_INFO_VISITOR_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc new file mode 100644 index 000000000..47ad22052 --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.cc @@ -0,0 +1,53 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK web_plugin_unstable_callback_is_unstable( + struct _cef_web_plugin_unstable_callback_t* self, const cef_string_t* path, + int unstable) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefWebPluginUnstableCallbackCppToC::Get(self)->IsUnstable( + CefString(path), + unstable?true:false); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefWebPluginUnstableCallbackCppToC::CefWebPluginUnstableCallbackCppToC( + CefWebPluginUnstableCallback* cls) + : CefCppToC( + cls) { + struct_.struct_.is_unstable = web_plugin_unstable_callback_is_unstable; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h new file mode 100644 index 000000000..0dc0cb6e7 --- /dev/null +++ b/libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h @@ -0,0 +1,38 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefWebPluginUnstableCallbackCppToC + : public CefCppToC { + public: + explicit CefWebPluginUnstableCallbackCppToC( + CefWebPluginUnstableCallback* cls); + virtual ~CefWebPluginUnstableCallbackCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_WEB_PLUGIN_UNSTABLE_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/write_handler_cpptoc.cc b/libcef_dll/cpptoc/write_handler_cpptoc.cc new file mode 100644 index 000000000..4cbfb69e0 --- /dev/null +++ b/libcef_dll/cpptoc/write_handler_cpptoc.cc @@ -0,0 +1,116 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/write_handler_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +size_t CEF_CALLBACK write_handler_write(struct _cef_write_handler_t* self, + const void* ptr, size_t size, size_t n) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = CefWriteHandlerCppToC::Get(self)->Write( + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK write_handler_seek(struct _cef_write_handler_t* self, + int64 offset, int whence) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefWriteHandlerCppToC::Get(self)->Seek( + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK write_handler_tell(struct _cef_write_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefWriteHandlerCppToC::Get(self)->Tell(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK write_handler_flush(struct _cef_write_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefWriteHandlerCppToC::Get(self)->Flush(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK write_handler_may_block(struct _cef_write_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefWriteHandlerCppToC::Get(self)->MayBlock(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefWriteHandlerCppToC::CefWriteHandlerCppToC(CefWriteHandler* cls) + : CefCppToC( + cls) { + struct_.struct_.write = write_handler_write; + struct_.struct_.seek = write_handler_seek; + struct_.struct_.tell = write_handler_tell; + struct_.struct_.flush = write_handler_flush; + struct_.struct_.may_block = write_handler_may_block; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/write_handler_cpptoc.h b/libcef_dll/cpptoc/write_handler_cpptoc.h new file mode 100644 index 000000000..5852e4eba --- /dev/null +++ b/libcef_dll/cpptoc/write_handler_cpptoc.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_WRITE_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_WRITE_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefWriteHandlerCppToC + : public CefCppToC { + public: + explicit CefWriteHandlerCppToC(CefWriteHandler* cls); + virtual ~CefWriteHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_WRITE_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/xml_reader_cpptoc.cc b/libcef_dll/cpptoc/xml_reader_cpptoc.cc new file mode 100644 index 000000000..7f68aecc2 --- /dev/null +++ b/libcef_dll/cpptoc/xml_reader_cpptoc.cc @@ -0,0 +1,558 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/stream_reader_cpptoc.h" +#include "libcef_dll/cpptoc/xml_reader_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_xml_reader_t* cef_xml_reader_create(cef_stream_reader_t* stream, + cef_xml_encoding_type_t encodingType, const cef_string_t* URI) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: stream; type: refptr_same + DCHECK(stream); + if (!stream) + return NULL; + // Verify param: URI; type: string_byref_const + DCHECK(URI); + if (!URI) + return NULL; + + // Execute + CefRefPtr _retval = CefXmlReader::Create( + CefStreamReaderCppToC::Unwrap(stream), + encodingType, + CefString(URI)); + + // Return type: refptr_same + return CefXmlReaderCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK xml_reader_move_to_next_node(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToNextNode(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_close(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->Close(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_has_error(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->HasError(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_error( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetError(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_xml_node_type_t CEF_CALLBACK xml_reader_get_type( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return XML_NODE_UNSUPPORTED; + + // Execute + cef_xml_node_type_t _retval = CefXmlReaderCppToC::Get(self)->GetType(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK xml_reader_get_depth(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefXmlReaderCppToC::Get(self)->GetDepth(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_local_name( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetLocalName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_prefix( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetPrefix(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_qualified_name( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetQualifiedName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_namespace_uri( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetNamespaceURI(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_base_uri( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetBaseURI(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_xml_lang( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetXmlLang(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK xml_reader_is_empty_element(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->IsEmptyElement(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_has_value(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->HasValue(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_value( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetValue(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK xml_reader_has_attributes(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->HasAttributes(); + + // Return type: bool + return _retval; +} + +size_t CEF_CALLBACK xml_reader_get_attribute_count( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefXmlReaderCppToC::Get(self)->GetAttributeCount(); + + // Return type: simple + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_attribute_byindex( + struct _cef_xml_reader_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetAttribute( + index); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_attribute_byqname( + struct _cef_xml_reader_t* self, const cef_string_t* qualifiedName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: qualifiedName; type: string_byref_const + DCHECK(qualifiedName); + if (!qualifiedName) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetAttribute( + CefString(qualifiedName)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_attribute_bylname( + struct _cef_xml_reader_t* self, const cef_string_t* localName, + const cef_string_t* namespaceURI) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: localName; type: string_byref_const + DCHECK(localName); + if (!localName) + return NULL; + // Verify param: namespaceURI; type: string_byref_const + DCHECK(namespaceURI); + if (!namespaceURI) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetAttribute( + CefString(localName), + CefString(namespaceURI)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_inner_xml( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetInnerXml(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_string_userfree_t CEF_CALLBACK xml_reader_get_outer_xml( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefXmlReaderCppToC::Get(self)->GetOuterXml(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int CEF_CALLBACK xml_reader_get_line_number(struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int _retval = CefXmlReaderCppToC::Get(self)->GetLineNumber(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_attribute_byindex( + struct _cef_xml_reader_t* self, int index) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToAttribute( + index); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_attribute_byqname( + struct _cef_xml_reader_t* self, const cef_string_t* qualifiedName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: qualifiedName; type: string_byref_const + DCHECK(qualifiedName); + if (!qualifiedName) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToAttribute( + CefString(qualifiedName)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_attribute_bylname( + struct _cef_xml_reader_t* self, const cef_string_t* localName, + const cef_string_t* namespaceURI) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: localName; type: string_byref_const + DCHECK(localName); + if (!localName) + return 0; + // Verify param: namespaceURI; type: string_byref_const + DCHECK(namespaceURI); + if (!namespaceURI) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToAttribute( + CefString(localName), + CefString(namespaceURI)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_first_attribute( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToFirstAttribute(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_next_attribute( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToNextAttribute(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK xml_reader_move_to_carrying_element( + struct _cef_xml_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefXmlReaderCppToC::Get(self)->MoveToCarryingElement(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefXmlReaderCppToC::CefXmlReaderCppToC(CefXmlReader* cls) + : CefCppToC(cls) { + struct_.struct_.move_to_next_node = xml_reader_move_to_next_node; + struct_.struct_.close = xml_reader_close; + struct_.struct_.has_error = xml_reader_has_error; + struct_.struct_.get_error = xml_reader_get_error; + struct_.struct_.get_type = xml_reader_get_type; + struct_.struct_.get_depth = xml_reader_get_depth; + struct_.struct_.get_local_name = xml_reader_get_local_name; + struct_.struct_.get_prefix = xml_reader_get_prefix; + struct_.struct_.get_qualified_name = xml_reader_get_qualified_name; + struct_.struct_.get_namespace_uri = xml_reader_get_namespace_uri; + struct_.struct_.get_base_uri = xml_reader_get_base_uri; + struct_.struct_.get_xml_lang = xml_reader_get_xml_lang; + struct_.struct_.is_empty_element = xml_reader_is_empty_element; + struct_.struct_.has_value = xml_reader_has_value; + struct_.struct_.get_value = xml_reader_get_value; + struct_.struct_.has_attributes = xml_reader_has_attributes; + struct_.struct_.get_attribute_count = xml_reader_get_attribute_count; + struct_.struct_.get_attribute_byindex = xml_reader_get_attribute_byindex; + struct_.struct_.get_attribute_byqname = xml_reader_get_attribute_byqname; + struct_.struct_.get_attribute_bylname = xml_reader_get_attribute_bylname; + struct_.struct_.get_inner_xml = xml_reader_get_inner_xml; + struct_.struct_.get_outer_xml = xml_reader_get_outer_xml; + struct_.struct_.get_line_number = xml_reader_get_line_number; + struct_.struct_.move_to_attribute_byindex = + xml_reader_move_to_attribute_byindex; + struct_.struct_.move_to_attribute_byqname = + xml_reader_move_to_attribute_byqname; + struct_.struct_.move_to_attribute_bylname = + xml_reader_move_to_attribute_bylname; + struct_.struct_.move_to_first_attribute = xml_reader_move_to_first_attribute; + struct_.struct_.move_to_next_attribute = xml_reader_move_to_next_attribute; + struct_.struct_.move_to_carrying_element = + xml_reader_move_to_carrying_element; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/xml_reader_cpptoc.h b/libcef_dll/cpptoc/xml_reader_cpptoc.h new file mode 100644 index 000000000..42b61f7d5 --- /dev/null +++ b/libcef_dll/cpptoc/xml_reader_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_XML_READER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_XML_READER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_xml_reader.h" +#include "include/capi/cef_xml_reader_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefXmlReaderCppToC + : public CefCppToC { + public: + explicit CefXmlReaderCppToC(CefXmlReader* cls); + virtual ~CefXmlReaderCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_XML_READER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/zip_reader_cpptoc.cc b/libcef_dll/cpptoc/zip_reader_cpptoc.cc new file mode 100644 index 000000000..ee0be27cd --- /dev/null +++ b/libcef_dll/cpptoc/zip_reader_cpptoc.cc @@ -0,0 +1,249 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/stream_reader_cpptoc.h" +#include "libcef_dll/cpptoc/zip_reader_cpptoc.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_zip_reader_t* cef_zip_reader_create( + cef_stream_reader_t* stream) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: stream; type: refptr_same + DCHECK(stream); + if (!stream) + return NULL; + + // Execute + CefRefPtr _retval = CefZipReader::Create( + CefStreamReaderCppToC::Unwrap(stream)); + + // Return type: refptr_same + return CefZipReaderCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK zip_reader_move_to_first_file(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->MoveToFirstFile(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK zip_reader_move_to_next_file(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->MoveToNextFile(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK zip_reader_move_to_file(struct _cef_zip_reader_t* self, + const cef_string_t* fileName, int caseSensitive) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: fileName; type: string_byref_const + DCHECK(fileName); + if (!fileName) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->MoveToFile( + CefString(fileName), + caseSensitive?true:false); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK zip_reader_close(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->Close(); + + // Return type: bool + return _retval; +} + +cef_string_userfree_t CEF_CALLBACK zip_reader_get_file_name( + struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefZipReaderCppToC::Get(self)->GetFileName(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +int64 CEF_CALLBACK zip_reader_get_file_size(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefZipReaderCppToC::Get(self)->GetFileSize(); + + // Return type: simple + return _retval; +} + +time_t CEF_CALLBACK zip_reader_get_file_last_modified( + struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + time_t _retval = CefZipReaderCppToC::Get(self)->GetFileLastModified(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK zip_reader_open_file(struct _cef_zip_reader_t* self, + const cef_string_t* password) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: password + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->OpenFile( + CefString(password)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK zip_reader_close_file(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->CloseFile(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK zip_reader_read_file(struct _cef_zip_reader_t* self, + void* buffer, size_t bufferSize) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return 0; + + // Execute + int _retval = CefZipReaderCppToC::Get(self)->ReadFile( + buffer, + bufferSize); + + // Return type: simple + return _retval; +} + +int64 CEF_CALLBACK zip_reader_tell(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + int64 _retval = CefZipReaderCppToC::Get(self)->Tell(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK zip_reader_eof(struct _cef_zip_reader_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefZipReaderCppToC::Get(self)->Eof(); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefZipReaderCppToC::CefZipReaderCppToC(CefZipReader* cls) + : CefCppToC(cls) { + struct_.struct_.move_to_first_file = zip_reader_move_to_first_file; + struct_.struct_.move_to_next_file = zip_reader_move_to_next_file; + struct_.struct_.move_to_file = zip_reader_move_to_file; + struct_.struct_.close = zip_reader_close; + struct_.struct_.get_file_name = zip_reader_get_file_name; + struct_.struct_.get_file_size = zip_reader_get_file_size; + struct_.struct_.get_file_last_modified = zip_reader_get_file_last_modified; + struct_.struct_.open_file = zip_reader_open_file; + struct_.struct_.close_file = zip_reader_close_file; + struct_.struct_.read_file = zip_reader_read_file; + struct_.struct_.tell = zip_reader_tell; + struct_.struct_.eof = zip_reader_eof; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/zip_reader_cpptoc.h b/libcef_dll/cpptoc/zip_reader_cpptoc.h new file mode 100644 index 000000000..011bf2f7b --- /dev/null +++ b/libcef_dll/cpptoc/zip_reader_cpptoc.h @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_ZIP_READER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_ZIP_READER_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_zip_reader.h" +#include "include/capi/cef_zip_reader_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefZipReaderCppToC + : public CefCppToC { + public: + explicit CefZipReaderCppToC(CefZipReader* cls); + virtual ~CefZipReaderCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_ZIP_READER_CPPTOC_H_ + diff --git a/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc new file mode 100644 index 000000000..4cc64f58b --- /dev/null +++ b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.cc @@ -0,0 +1,35 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefAllowCertificateErrorCallbackCToCpp::Continue(bool allow) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cont(struct_, + allow); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h new file mode 100644 index 000000000..ae35463cf --- /dev/null +++ b/libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_ALLOW_CERTIFICATE_ERROR_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_ALLOW_CERTIFICATE_ERROR_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefAllowCertificateErrorCallbackCToCpp + : public CefCToCpp { + public: + explicit CefAllowCertificateErrorCallbackCToCpp( + cef_allow_certificate_error_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefAllowCertificateErrorCallbackCToCpp() {} + + // CefAllowCertificateErrorCallback methods + virtual void Continue(bool allow) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_ALLOW_CERTIFICATE_ERROR_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/app_ctocpp.cc b/libcef_dll/ctocpp/app_ctocpp.cc new file mode 100644 index 000000000..93689a4f8 --- /dev/null +++ b/libcef_dll/ctocpp/app_ctocpp.cc @@ -0,0 +1,106 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/command_line_cpptoc.h" +#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h" +#include "libcef_dll/ctocpp/app_ctocpp.h" +#include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h" +#include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" +#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefAppCToCpp::OnBeforeCommandLineProcessing(const CefString& process_type, + CefRefPtr command_line) { + if (CEF_MEMBER_MISSING(struct_, on_before_command_line_processing)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: command_line; type: refptr_diff + DCHECK(command_line.get()); + if (!command_line.get()) + return; + // Unverified params: process_type + + // Execute + struct_->on_before_command_line_processing(struct_, + process_type.GetStruct(), + CefCommandLineCppToC::Wrap(command_line)); +} + +void CefAppCToCpp::OnRegisterCustomSchemes( + CefRefPtr registrar) { + if (CEF_MEMBER_MISSING(struct_, on_register_custom_schemes)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: registrar; type: refptr_diff + DCHECK(registrar.get()); + if (!registrar.get()) + return; + + // Execute + struct_->on_register_custom_schemes(struct_, + CefSchemeRegistrarCppToC::Wrap(registrar)); +} + +CefRefPtr CefAppCToCpp::GetResourceBundleHandler() { + if (CEF_MEMBER_MISSING(struct_, get_resource_bundle_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_resource_bundle_handler_t* _retval = struct_->get_resource_bundle_handler( + struct_); + + // Return type: refptr_same + return CefResourceBundleHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefAppCToCpp::GetBrowserProcessHandler() { + if (CEF_MEMBER_MISSING(struct_, get_browser_process_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_browser_process_handler_t* _retval = struct_->get_browser_process_handler( + struct_); + + // Return type: refptr_same + return CefBrowserProcessHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefAppCToCpp::GetRenderProcessHandler() { + if (CEF_MEMBER_MISSING(struct_, get_render_process_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_render_process_handler_t* _retval = struct_->get_render_process_handler( + struct_); + + // Return type: refptr_same + return CefRenderProcessHandlerCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/app_ctocpp.h b/libcef_dll/ctocpp/app_ctocpp.h new file mode 100644 index 000000000..632eaf0c6 --- /dev/null +++ b/libcef_dll/ctocpp/app_ctocpp.h @@ -0,0 +1,48 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_APP_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_APP_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_app.h" +#include "include/capi/cef_app_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefAppCToCpp + : public CefCToCpp { + public: + explicit CefAppCToCpp(cef_app_t* str) + : CefCToCpp(str) {} + virtual ~CefAppCToCpp() {} + + // CefApp methods + virtual void OnBeforeCommandLineProcessing(const CefString& process_type, + CefRefPtr command_line) OVERRIDE; + virtual void OnRegisterCustomSchemes( + CefRefPtr registrar) OVERRIDE; + virtual CefRefPtr GetResourceBundleHandler( + ) OVERRIDE; + virtual CefRefPtr GetBrowserProcessHandler( + ) OVERRIDE; + virtual CefRefPtr GetRenderProcessHandler() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_APP_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/auth_callback_ctocpp.cc b/libcef_dll/ctocpp/auth_callback_ctocpp.cc new file mode 100644 index 000000000..1266e56ce --- /dev/null +++ b/libcef_dll/ctocpp/auth_callback_ctocpp.cc @@ -0,0 +1,55 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/auth_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefAuthCallbackCToCpp::Continue(const CefString& username, + const CefString& password) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: username; type: string_byref_const + DCHECK(!username.empty()); + if (username.empty()) + return; + // Verify param: password; type: string_byref_const + DCHECK(!password.empty()); + if (password.empty()) + return; + + // Execute + struct_->cont(struct_, + username.GetStruct(), + password.GetStruct()); +} + +void CefAuthCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/auth_callback_ctocpp.h b/libcef_dll/ctocpp/auth_callback_ctocpp.h new file mode 100644 index 000000000..2171f67e5 --- /dev/null +++ b/libcef_dll/ctocpp/auth_callback_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_AUTH_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_AUTH_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_auth_callback.h" +#include "include/capi/cef_auth_callback_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefAuthCallbackCToCpp + : public CefCToCpp { + public: + explicit CefAuthCallbackCToCpp(cef_auth_callback_t* str) + : CefCToCpp( + str) {} + virtual ~CefAuthCallbackCToCpp() {} + + // CefAuthCallback methods + virtual void Continue(const CefString& username, + const CefString& password) OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_AUTH_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/base_ctocpp.h b/libcef_dll/ctocpp/base_ctocpp.h new file mode 100644 index 000000000..f085183b1 --- /dev/null +++ b/libcef_dll/ctocpp/base_ctocpp.h @@ -0,0 +1,101 @@ +// 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_LIBCEF_DLL_CTOCPP_BASE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BASE_CTOCPP_H_ +#pragma once + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_base.h" +#include "include/capi/cef_base_capi.h" + + +// CefCToCpp implementation for CefBase. +class CefBaseCToCpp : public CefBase { + public: + // Use this method to create a wrapper class instance for a structure + // received from the other side. + static CefRefPtr Wrap(cef_base_t* s) { + if (!s) + return NULL; + + // Wrap their structure with the CefCToCpp object. + CefBaseCToCpp* wrapper = new CefBaseCToCpp(s); + // Put the wrapper object in a smart pointer. + CefRefPtr wrapperPtr(wrapper); + // Release the reference that was added to the CefCppToC wrapper object on + // the other side before their structure was passed to us. + wrapper->UnderlyingRelease(); + // Return the smart pointer. + return wrapperPtr; + } + + // Use this method to retrieve the underlying structure from a wrapper class + // instance for return back to the other side. + static cef_base_t* Unwrap(CefRefPtr c) { + if (!c.get()) + return NULL; + + // Cast the object to our wrapper class type. + CefBaseCToCpp* wrapper = static_cast(c.get()); + // Add a reference to the CefCppToC wrapper object on the other side that + // will be released once the structure is received. + wrapper->UnderlyingAddRef(); + // Return their original structure. + return wrapper->GetStruct(); + } + + explicit CefBaseCToCpp(cef_base_t* str) + : struct_(str) { + DCHECK(str); + } + virtual ~CefBaseCToCpp() {} + + // If returning the structure across the DLL boundary you should call + // UnderlyingAddRef() on this wrapping CefCToCpp object. On the other side of + // the DLL boundary, call Release() on the CefCppToC object. + cef_base_t* GetStruct() { return struct_; } + + // CefBase methods increment/decrement reference counts on both this object + // and the underlying wrapped structure. + void AddRef() const { + UnderlyingAddRef(); + ref_count_.AddRef(); + } + bool Release() const { + UnderlyingRelease(); + if (ref_count_.Release()) { + delete this; + return true; + } + return false; + } + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + // Increment/decrement reference counts on only the underlying class. + void UnderlyingAddRef() const { + if (struct_->add_ref) + struct_->add_ref(struct_); + } + bool UnderlyingRelease() const { + if (!struct_->release) + return false; + return struct_->release(struct_) ? true : false; + } + bool UnderlyingHasOneRef() const { + if (!struct_->has_one_ref) + return false; + return struct_->has_one_ref(struct_) ? true : false; + } + + private: + CefRefCount ref_count_; + cef_base_t* struct_; + + DISALLOW_COPY_AND_ASSIGN(CefBaseCToCpp); +}; + + +#endif // CEF_LIBCEF_DLL_CTOCPP_BASE_CTOCPP_H_ diff --git a/libcef_dll/ctocpp/before_download_callback_ctocpp.cc b/libcef_dll/ctocpp/before_download_callback_ctocpp.cc new file mode 100644 index 000000000..972325959 --- /dev/null +++ b/libcef_dll/ctocpp/before_download_callback_ctocpp.cc @@ -0,0 +1,39 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/before_download_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefBeforeDownloadCallbackCToCpp::Continue(const CefString& download_path, + bool show_dialog) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: download_path + + // Execute + struct_->cont(struct_, + download_path.GetStruct(), + show_dialog); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = + 0; +#endif + diff --git a/libcef_dll/ctocpp/before_download_callback_ctocpp.h b/libcef_dll/ctocpp/before_download_callback_ctocpp.h new file mode 100644 index 000000000..30e1c0c10 --- /dev/null +++ b/libcef_dll/ctocpp/before_download_callback_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_BEFORE_DOWNLOAD_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BEFORE_DOWNLOAD_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefBeforeDownloadCallbackCToCpp + : public CefCToCpp { + public: + explicit CefBeforeDownloadCallbackCToCpp(cef_before_download_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefBeforeDownloadCallbackCToCpp() {} + + // CefBeforeDownloadCallback methods + virtual void Continue(const CefString& download_path, + bool show_dialog) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_BEFORE_DOWNLOAD_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/binary_value_ctocpp.cc b/libcef_dll/ctocpp/binary_value_ctocpp.cc new file mode 100644 index 000000000..24bb115e5 --- /dev/null +++ b/libcef_dll/ctocpp/binary_value_ctocpp.cc @@ -0,0 +1,118 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/binary_value_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefBinaryValue::Create(const void* data, + size_t data_size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return NULL; + + // Execute + cef_binary_value_t* _retval = cef_binary_value_create( + data, + data_size); + + // Return type: refptr_same + return CefBinaryValueCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefBinaryValueCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefBinaryValueCToCpp::IsOwned() { + if (CEF_MEMBER_MISSING(struct_, is_owned)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_owned(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefBinaryValueCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_binary_value_t* _retval = struct_->copy(struct_); + + // Return type: refptr_same + return CefBinaryValueCToCpp::Wrap(_retval); +} + +size_t CefBinaryValueCToCpp::GetSize() { + if (CEF_MEMBER_MISSING(struct_, get_size)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_size(struct_); + + // Return type: simple + return _retval; +} + +size_t CefBinaryValueCToCpp::GetData(void* buffer, size_t buffer_size, + size_t data_offset) { + if (CEF_MEMBER_MISSING(struct_, get_data)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return 0; + + // Execute + size_t _retval = struct_->get_data(struct_, + buffer, + buffer_size, + data_offset); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/binary_value_ctocpp.h b/libcef_dll/ctocpp/binary_value_ctocpp.h new file mode 100644 index 000000000..bd0f359bb --- /dev/null +++ b/libcef_dll/ctocpp/binary_value_ctocpp.h @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefBinaryValueCToCpp + : public CefCToCpp { + public: + explicit CefBinaryValueCToCpp(cef_binary_value_t* str) + : CefCToCpp( + str) {} + virtual ~CefBinaryValueCToCpp() {} + + // CefBinaryValue methods + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual size_t GetData(void* buffer, size_t buffer_size, + size_t data_offset) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/browser_ctocpp.cc b/libcef_dll/ctocpp/browser_ctocpp.cc new file mode 100644 index 000000000..bfe707b44 --- /dev/null +++ b/libcef_dll/ctocpp/browser_ctocpp.cc @@ -0,0 +1,343 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/browser_host_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefBrowserCToCpp::GetHost() { + if (CEF_MEMBER_MISSING(struct_, get_host)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_browser_host_t* _retval = struct_->get_host(struct_); + + // Return type: refptr_same + return CefBrowserHostCToCpp::Wrap(_retval); +} + +bool CefBrowserCToCpp::CanGoBack() { + if (CEF_MEMBER_MISSING(struct_, can_go_back)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_go_back(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefBrowserCToCpp::GoBack() { + if (CEF_MEMBER_MISSING(struct_, go_back)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->go_back(struct_); +} + +bool CefBrowserCToCpp::CanGoForward() { + if (CEF_MEMBER_MISSING(struct_, can_go_forward)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_go_forward(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefBrowserCToCpp::GoForward() { + if (CEF_MEMBER_MISSING(struct_, go_forward)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->go_forward(struct_); +} + +bool CefBrowserCToCpp::IsLoading() { + if (CEF_MEMBER_MISSING(struct_, is_loading)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_loading(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefBrowserCToCpp::Reload() { + if (CEF_MEMBER_MISSING(struct_, reload)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->reload(struct_); +} + +void CefBrowserCToCpp::ReloadIgnoreCache() { + if (CEF_MEMBER_MISSING(struct_, reload_ignore_cache)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->reload_ignore_cache(struct_); +} + +void CefBrowserCToCpp::StopLoad() { + if (CEF_MEMBER_MISSING(struct_, stop_load)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->stop_load(struct_); +} + +int CefBrowserCToCpp::GetIdentifier() { + if (CEF_MEMBER_MISSING(struct_, get_identifier)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_identifier(struct_); + + // Return type: simple + return _retval; +} + +bool CefBrowserCToCpp::IsSame(CefRefPtr that) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: that; type: refptr_same + DCHECK(that.get()); + if (!that.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefBrowserCToCpp::Unwrap(that)); + + // Return type: bool + return _retval?true:false; +} + +bool CefBrowserCToCpp::IsPopup() { + if (CEF_MEMBER_MISSING(struct_, is_popup)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_popup(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefBrowserCToCpp::HasDocument() { + if (CEF_MEMBER_MISSING(struct_, has_document)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_document(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefBrowserCToCpp::GetMainFrame() { + if (CEF_MEMBER_MISSING(struct_, get_main_frame)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_frame_t* _retval = struct_->get_main_frame(struct_); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +CefRefPtr CefBrowserCToCpp::GetFocusedFrame() { + if (CEF_MEMBER_MISSING(struct_, get_focused_frame)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_frame_t* _retval = struct_->get_focused_frame(struct_); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +CefRefPtr CefBrowserCToCpp::GetFrame(int64 identifier) { + if (CEF_MEMBER_MISSING(struct_, get_frame_byident)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_frame_t* _retval = struct_->get_frame_byident(struct_, + identifier); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +CefRefPtr CefBrowserCToCpp::GetFrame(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, get_frame)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return NULL; + + // Execute + cef_frame_t* _retval = struct_->get_frame(struct_, + name.GetStruct()); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +size_t CefBrowserCToCpp::GetFrameCount() { + if (CEF_MEMBER_MISSING(struct_, get_frame_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_frame_count(struct_); + + // Return type: simple + return _retval; +} + +void CefBrowserCToCpp::GetFrameIdentifiers(std::vector& identifiers) { + if (CEF_MEMBER_MISSING(struct_, get_frame_identifiers)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: identifiers; type: simple_vec_byref + size_t identifiersSize = identifiers.size(); + size_t identifiersCount = std::max(GetFrameCount(), identifiersSize); + int64* identifiersList = NULL; + if (identifiersCount > 0) { + identifiersList = new int64[identifiersCount]; + DCHECK(identifiersList); + if (identifiersList) { + memset(identifiersList, 0, sizeof(int64)*identifiersCount); + } + if (identifiersList && identifiersSize > 0) { + for (size_t i = 0; i < identifiersSize; ++i) { + identifiersList[i] = identifiers[i]; + } + } + } + + // Execute + struct_->get_frame_identifiers(struct_, + &identifiersCount, + identifiersList); + + // Restore param:identifiers; type: simple_vec_byref + identifiers.clear(); + if (identifiersCount > 0 && identifiersList) { + for (size_t i = 0; i < identifiersCount; ++i) { + identifiers.push_back(identifiersList[i]); + } + delete [] identifiersList; + } +} + +void CefBrowserCToCpp::GetFrameNames(std::vector& names) { + if (CEF_MEMBER_MISSING(struct_, get_frame_names)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: names; type: string_vec_byref + cef_string_list_t namesList = cef_string_list_alloc(); + DCHECK(namesList); + if (namesList) + transfer_string_list_contents(names, namesList); + + // Execute + struct_->get_frame_names(struct_, + namesList); + + // Restore param:names; type: string_vec_byref + if (namesList) { + names.clear(); + transfer_string_list_contents(namesList, names); + cef_string_list_free(namesList); + } +} + +bool CefBrowserCToCpp::SendProcessMessage(CefProcessId target_process, + CefRefPtr message) { + if (CEF_MEMBER_MISSING(struct_, send_process_message)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: message; type: refptr_same + DCHECK(message.get()); + if (!message.get()) + return false; + + // Execute + int _retval = struct_->send_process_message(struct_, + target_process, + CefProcessMessageCToCpp::Unwrap(message)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/browser_ctocpp.h b/libcef_dll/ctocpp/browser_ctocpp.h new file mode 100644 index 000000000..8f73e4837 --- /dev/null +++ b/libcef_dll/ctocpp/browser_ctocpp.h @@ -0,0 +1,64 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefBrowserCToCpp + : public CefCToCpp { + public: + explicit CefBrowserCToCpp(cef_browser_t* str) + : CefCToCpp(str) {} + virtual ~CefBrowserCToCpp() {} + + // CefBrowser methods + virtual CefRefPtr GetHost() OVERRIDE; + virtual bool CanGoBack() OVERRIDE; + virtual void GoBack() OVERRIDE; + virtual bool CanGoForward() OVERRIDE; + virtual void GoForward() OVERRIDE; + virtual bool IsLoading() OVERRIDE; + virtual void Reload() OVERRIDE; + virtual void ReloadIgnoreCache() OVERRIDE; + virtual void StopLoad() OVERRIDE; + virtual int GetIdentifier() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool IsPopup() OVERRIDE; + virtual bool HasDocument() OVERRIDE; + virtual CefRefPtr GetMainFrame() OVERRIDE; + virtual CefRefPtr GetFocusedFrame() OVERRIDE; + virtual CefRefPtr GetFrame(int64 identifier) OVERRIDE; + virtual CefRefPtr GetFrame(const CefString& name) OVERRIDE; + virtual size_t GetFrameCount() OVERRIDE; + virtual void GetFrameIdentifiers(std::vector& identifiers) OVERRIDE; + virtual void GetFrameNames(std::vector& names) OVERRIDE; + virtual bool SendProcessMessage(CefProcessId target_process, + CefRefPtr message) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc new file mode 100644 index 000000000..55ddc87dc --- /dev/null +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -0,0 +1,582 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/client_cpptoc.h" +#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/browser_host_ctocpp.h" +#include "libcef_dll/ctocpp/drag_data_ctocpp.h" +#include "libcef_dll/ctocpp/request_context_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +bool CefBrowserHost::CreateBrowser(const CefWindowInfo& windowInfo, + CefRefPtr client, const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr request_context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: client, url, request_context + + // Execute + int _retval = cef_browser_host_create_browser( + &windowInfo, + CefClientCppToC::Wrap(client), + url.GetStruct(), + &settings, + CefRequestContextCToCpp::Unwrap(request_context)); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefBrowserHost::CreateBrowserSync( + const CefWindowInfo& windowInfo, CefRefPtr client, + const CefString& url, const CefBrowserSettings& settings, + CefRefPtr request_context) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: client, url, request_context + + // Execute + cef_browser_t* _retval = cef_browser_host_create_browser_sync( + &windowInfo, + CefClientCppToC::Wrap(client), + url.GetStruct(), + &settings, + CefRequestContextCToCpp::Unwrap(request_context)); + + // Return type: refptr_same + return CefBrowserCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefBrowserHostCToCpp::GetBrowser() { + if (CEF_MEMBER_MISSING(struct_, get_browser)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_browser_t* _retval = struct_->get_browser(struct_); + + // Return type: refptr_same + return CefBrowserCToCpp::Wrap(_retval); +} + +void CefBrowserHostCToCpp::CloseBrowser(bool force_close) { + if (CEF_MEMBER_MISSING(struct_, close_browser)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->close_browser(struct_, + force_close); +} + +void CefBrowserHostCToCpp::SetFocus(bool focus) { + if (CEF_MEMBER_MISSING(struct_, set_focus)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_focus(struct_, + focus); +} + +void CefBrowserHostCToCpp::SetWindowVisibility(bool visible) { + if (CEF_MEMBER_MISSING(struct_, set_window_visibility)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_window_visibility(struct_, + visible); +} + +CefWindowHandle CefBrowserHostCToCpp::GetWindowHandle() { + if (CEF_MEMBER_MISSING(struct_, get_window_handle)) + return kNullWindowHandle; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_window_handle_t _retval = struct_->get_window_handle(struct_); + + // Return type: simple + return _retval; +} + +CefWindowHandle CefBrowserHostCToCpp::GetOpenerWindowHandle() { + if (CEF_MEMBER_MISSING(struct_, get_opener_window_handle)) + return kNullWindowHandle; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_window_handle_t _retval = struct_->get_opener_window_handle(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefBrowserHostCToCpp::GetClient() { + if (CEF_MEMBER_MISSING(struct_, get_client)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_client_t* _retval = struct_->get_client(struct_); + + // Return type: refptr_diff + return CefClientCppToC::Unwrap(_retval); +} + +CefRefPtr CefBrowserHostCToCpp::GetRequestContext() { + if (CEF_MEMBER_MISSING(struct_, get_request_context)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_context_t* _retval = struct_->get_request_context(struct_); + + // Return type: refptr_same + return CefRequestContextCToCpp::Wrap(_retval); +} + +double CefBrowserHostCToCpp::GetZoomLevel() { + if (CEF_MEMBER_MISSING(struct_, get_zoom_level)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + double _retval = struct_->get_zoom_level(struct_); + + // Return type: simple + return _retval; +} + +void CefBrowserHostCToCpp::SetZoomLevel(double zoomLevel) { + if (CEF_MEMBER_MISSING(struct_, set_zoom_level)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_zoom_level(struct_, + zoomLevel); +} + +void CefBrowserHostCToCpp::RunFileDialog(FileDialogMode mode, + const CefString& title, const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, run_file_dialog)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return; + // Unverified params: title, default_file_name, accept_types + + // Translate param: accept_types; type: string_vec_byref_const + cef_string_list_t accept_typesList = cef_string_list_alloc(); + DCHECK(accept_typesList); + if (accept_typesList) + transfer_string_list_contents(accept_types, accept_typesList); + + // Execute + struct_->run_file_dialog(struct_, + mode, + title.GetStruct(), + default_file_name.GetStruct(), + accept_typesList, + CefRunFileDialogCallbackCppToC::Wrap(callback)); + + // Restore param:accept_types; type: string_vec_byref_const + if (accept_typesList) + cef_string_list_free(accept_typesList); +} + +void CefBrowserHostCToCpp::StartDownload(const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, start_download)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->start_download(struct_, + url.GetStruct()); +} + +void CefBrowserHostCToCpp::Print() { + if (CEF_MEMBER_MISSING(struct_, print)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->print(struct_); +} + +void CefBrowserHostCToCpp::Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) { + if (CEF_MEMBER_MISSING(struct_, find)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: searchText; type: string_byref_const + DCHECK(!searchText.empty()); + if (searchText.empty()) + return; + + // Execute + struct_->find(struct_, + identifier, + searchText.GetStruct(), + forward, + matchCase, + findNext); +} + +void CefBrowserHostCToCpp::StopFinding(bool clearSelection) { + if (CEF_MEMBER_MISSING(struct_, stop_finding)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->stop_finding(struct_, + clearSelection); +} + +void CefBrowserHostCToCpp::ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, const CefBrowserSettings& settings) { + if (CEF_MEMBER_MISSING(struct_, show_dev_tools)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: client; type: refptr_diff + DCHECK(client.get()); + if (!client.get()) + return; + + // Execute + struct_->show_dev_tools(struct_, + &windowInfo, + CefClientCppToC::Wrap(client), + &settings); +} + +void CefBrowserHostCToCpp::CloseDevTools() { + if (CEF_MEMBER_MISSING(struct_, close_dev_tools)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->close_dev_tools(struct_); +} + +void CefBrowserHostCToCpp::SetMouseCursorChangeDisabled(bool disabled) { + if (CEF_MEMBER_MISSING(struct_, set_mouse_cursor_change_disabled)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_mouse_cursor_change_disabled(struct_, + disabled); +} + +bool CefBrowserHostCToCpp::IsMouseCursorChangeDisabled() { + if (CEF_MEMBER_MISSING(struct_, is_mouse_cursor_change_disabled)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_mouse_cursor_change_disabled(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefBrowserHostCToCpp::IsWindowRenderingDisabled() { + if (CEF_MEMBER_MISSING(struct_, is_window_rendering_disabled)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_window_rendering_disabled(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefBrowserHostCToCpp::WasResized() { + if (CEF_MEMBER_MISSING(struct_, was_resized)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->was_resized(struct_); +} + +void CefBrowserHostCToCpp::WasHidden(bool hidden) { + if (CEF_MEMBER_MISSING(struct_, was_hidden)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->was_hidden(struct_, + hidden); +} + +void CefBrowserHostCToCpp::NotifyScreenInfoChanged() { + if (CEF_MEMBER_MISSING(struct_, notify_screen_info_changed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->notify_screen_info_changed(struct_); +} + +void CefBrowserHostCToCpp::Invalidate(PaintElementType type) { + if (CEF_MEMBER_MISSING(struct_, invalidate)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->invalidate(struct_, + type); +} + +void CefBrowserHostCToCpp::SendKeyEvent(const CefKeyEvent& event) { + if (CEF_MEMBER_MISSING(struct_, send_key_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_key_event(struct_, + &event); +} + +void CefBrowserHostCToCpp::SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) { + if (CEF_MEMBER_MISSING(struct_, send_mouse_click_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_mouse_click_event(struct_, + &event, + type, + mouseUp, + clickCount); +} + +void CefBrowserHostCToCpp::SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) { + if (CEF_MEMBER_MISSING(struct_, send_mouse_move_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_mouse_move_event(struct_, + &event, + mouseLeave); +} + +void CefBrowserHostCToCpp::SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) { + if (CEF_MEMBER_MISSING(struct_, send_mouse_wheel_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_mouse_wheel_event(struct_, + &event, + deltaX, + deltaY); +} + +void CefBrowserHostCToCpp::SendFocusEvent(bool setFocus) { + if (CEF_MEMBER_MISSING(struct_, send_focus_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_focus_event(struct_, + setFocus); +} + +void CefBrowserHostCToCpp::SendCaptureLostEvent() { + if (CEF_MEMBER_MISSING(struct_, send_capture_lost_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->send_capture_lost_event(struct_); +} + +CefTextInputContext CefBrowserHostCToCpp::GetNSTextInputContext() { + if (CEF_MEMBER_MISSING(struct_, get_nstext_input_context)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_text_input_context_t _retval = struct_->get_nstext_input_context(struct_); + + // Return type: simple + return _retval; +} + +void CefBrowserHostCToCpp::HandleKeyEventBeforeTextInputClient( + CefEventHandle keyEvent) { + if (CEF_MEMBER_MISSING(struct_, handle_key_event_before_text_input_client)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->handle_key_event_before_text_input_client(struct_, + keyEvent); +} + +void CefBrowserHostCToCpp::HandleKeyEventAfterTextInputClient( + CefEventHandle keyEvent) { + if (CEF_MEMBER_MISSING(struct_, handle_key_event_after_text_input_client)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->handle_key_event_after_text_input_client(struct_, + keyEvent); +} + +void CefBrowserHostCToCpp::DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, DragOperationsMask allowed_ops) { + if (CEF_MEMBER_MISSING(struct_, drag_target_drag_enter)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: drag_data; type: refptr_same + DCHECK(drag_data.get()); + if (!drag_data.get()) + return; + + // Execute + struct_->drag_target_drag_enter(struct_, + CefDragDataCToCpp::Unwrap(drag_data), + &event, + allowed_ops); +} + +void CefBrowserHostCToCpp::DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops) { + if (CEF_MEMBER_MISSING(struct_, drag_target_drag_over)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->drag_target_drag_over(struct_, + &event, + allowed_ops); +} + +void CefBrowserHostCToCpp::DragTargetDragLeave() { + if (CEF_MEMBER_MISSING(struct_, drag_target_drag_leave)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->drag_target_drag_leave(struct_); +} + +void CefBrowserHostCToCpp::DragTargetDrop(const CefMouseEvent& event) { + if (CEF_MEMBER_MISSING(struct_, drag_target_drop)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->drag_target_drop(struct_, + &event); +} + +void CefBrowserHostCToCpp::DragSourceEndedAt(int x, int y, + DragOperationsMask op) { + if (CEF_MEMBER_MISSING(struct_, drag_source_ended_at)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->drag_source_ended_at(struct_, + x, + y, + op); +} + +void CefBrowserHostCToCpp::DragSourceSystemDragEnded() { + if (CEF_MEMBER_MISSING(struct_, drag_source_system_drag_ended)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->drag_source_system_drag_ended(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.h b/libcef_dll/ctocpp/browser_host_ctocpp.h new file mode 100644 index 000000000..901296336 --- /dev/null +++ b/libcef_dll/ctocpp/browser_host_ctocpp.h @@ -0,0 +1,96 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefBrowserHostCToCpp + : public CefCToCpp { + public: + explicit CefBrowserHostCToCpp(cef_browser_host_t* str) + : CefCToCpp( + str) {} + virtual ~CefBrowserHostCToCpp() {} + + // CefBrowserHost methods + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual void CloseBrowser(bool force_close) OVERRIDE; + virtual void SetFocus(bool focus) OVERRIDE; + virtual void SetWindowVisibility(bool visible) OVERRIDE; + virtual CefWindowHandle GetWindowHandle() OVERRIDE; + virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; + virtual CefRefPtr GetClient() OVERRIDE; + virtual CefRefPtr GetRequestContext() OVERRIDE; + virtual double GetZoomLevel() OVERRIDE; + virtual void SetZoomLevel(double zoomLevel) OVERRIDE; + virtual void RunFileDialog(FileDialogMode mode, const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) OVERRIDE; + virtual void StartDownload(const CefString& url) OVERRIDE; + virtual void Print() OVERRIDE; + virtual void Find(int identifier, const CefString& searchText, bool forward, + bool matchCase, bool findNext) OVERRIDE; + virtual void StopFinding(bool clearSelection) OVERRIDE; + virtual void ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings) OVERRIDE; + virtual void CloseDevTools() OVERRIDE; + virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE; + virtual bool IsMouseCursorChangeDisabled() OVERRIDE; + virtual bool IsWindowRenderingDisabled() OVERRIDE; + virtual void WasResized() OVERRIDE; + virtual void WasHidden(bool hidden) OVERRIDE; + virtual void NotifyScreenInfoChanged() OVERRIDE; + virtual void Invalidate(PaintElementType type) OVERRIDE; + virtual void SendKeyEvent(const CefKeyEvent& event) OVERRIDE; + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) OVERRIDE; + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) OVERRIDE; + virtual void SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, + int deltaY) OVERRIDE; + virtual void SendFocusEvent(bool setFocus) OVERRIDE; + virtual void SendCaptureLostEvent() OVERRIDE; + virtual CefTextInputContext GetNSTextInputContext() OVERRIDE; + virtual void HandleKeyEventBeforeTextInputClient( + CefEventHandle keyEvent) OVERRIDE; + virtual void HandleKeyEventAfterTextInputClient( + CefEventHandle keyEvent) OVERRIDE; + virtual void DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, DragOperationsMask allowed_ops) OVERRIDE; + virtual void DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops) OVERRIDE; + virtual void DragTargetDragLeave() OVERRIDE; + virtual void DragTargetDrop(const CefMouseEvent& event) OVERRIDE; + virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op) OVERRIDE; + virtual void DragSourceSystemDragEnded() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc new file mode 100644 index 000000000..4e7616c72 --- /dev/null +++ b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc @@ -0,0 +1,83 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/command_line_cpptoc.h" +#include "libcef_dll/cpptoc/list_value_cpptoc.h" +#include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h" +#include "libcef_dll/ctocpp/print_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefBrowserProcessHandlerCToCpp::OnContextInitialized() { + if (CEF_MEMBER_MISSING(struct_, on_context_initialized)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_context_initialized(struct_); +} + +void CefBrowserProcessHandlerCToCpp::OnBeforeChildProcessLaunch( + CefRefPtr command_line) { + if (CEF_MEMBER_MISSING(struct_, on_before_child_process_launch)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: command_line; type: refptr_diff + DCHECK(command_line.get()); + if (!command_line.get()) + return; + + // Execute + struct_->on_before_child_process_launch(struct_, + CefCommandLineCppToC::Wrap(command_line)); +} + +void CefBrowserProcessHandlerCToCpp::OnRenderProcessThreadCreated( + CefRefPtr extra_info) { + if (CEF_MEMBER_MISSING(struct_, on_render_process_thread_created)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extra_info; type: refptr_diff + DCHECK(extra_info.get()); + if (!extra_info.get()) + return; + + // Execute + struct_->on_render_process_thread_created(struct_, + CefListValueCppToC::Wrap(extra_info)); +} + +CefRefPtr CefBrowserProcessHandlerCToCpp::GetPrintHandler() { + if (CEF_MEMBER_MISSING(struct_, get_print_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_print_handler_t* _retval = struct_->get_print_handler(struct_); + + // Return type: refptr_same + return CefPrintHandlerCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/browser_process_handler_ctocpp.h b/libcef_dll/ctocpp/browser_process_handler_ctocpp.h new file mode 100644 index 000000000..07495972c --- /dev/null +++ b/libcef_dll/ctocpp/browser_process_handler_ctocpp.h @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_browser_process_handler.h" +#include "include/capi/cef_browser_process_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefBrowserProcessHandlerCToCpp + : public CefCToCpp { + public: + explicit CefBrowserProcessHandlerCToCpp(cef_browser_process_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefBrowserProcessHandlerCToCpp() {} + + // CefBrowserProcessHandler methods + virtual void OnContextInitialized() OVERRIDE; + virtual void OnBeforeChildProcessLaunch( + CefRefPtr command_line) OVERRIDE; + virtual void OnRenderProcessThreadCreated( + CefRefPtr extra_info) OVERRIDE; + virtual CefRefPtr GetPrintHandler() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/callback_ctocpp.cc b/libcef_dll/ctocpp/callback_ctocpp.cc new file mode 100644 index 000000000..7fe0daab5 --- /dev/null +++ b/libcef_dll/ctocpp/callback_ctocpp.cc @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefCallbackCToCpp::Continue() { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cont(struct_); +} + +void CefCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/callback_ctocpp.h b/libcef_dll/ctocpp/callback_ctocpp.h new file mode 100644 index 000000000..ade67876c --- /dev/null +++ b/libcef_dll/ctocpp/callback_ctocpp.h @@ -0,0 +1,41 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_callback.h" +#include "include/capi/cef_callback_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefCallbackCToCpp + : public CefCToCpp { + public: + explicit CefCallbackCToCpp(cef_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefCallbackCToCpp() {} + + // CefCallback methods + virtual void Continue() OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/client_ctocpp.cc b/libcef_dll/ctocpp/client_ctocpp.cc new file mode 100644 index 000000000..ec786c8a7 --- /dev/null +++ b/libcef_dll/ctocpp/client_ctocpp.cc @@ -0,0 +1,235 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" +#include "libcef_dll/ctocpp/client_ctocpp.h" +#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h" +#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h" +#include "libcef_dll/ctocpp/display_handler_ctocpp.h" +#include "libcef_dll/ctocpp/download_handler_ctocpp.h" +#include "libcef_dll/ctocpp/drag_handler_ctocpp.h" +#include "libcef_dll/ctocpp/focus_handler_ctocpp.h" +#include "libcef_dll/ctocpp/geolocation_handler_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" +#include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h" +#include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" +#include "libcef_dll/ctocpp/load_handler_ctocpp.h" +#include "libcef_dll/ctocpp/render_handler_ctocpp.h" +#include "libcef_dll/ctocpp/request_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefClientCToCpp::GetContextMenuHandler() { + if (CEF_MEMBER_MISSING(struct_, get_context_menu_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_context_menu_handler_t* _retval = struct_->get_context_menu_handler( + struct_); + + // Return type: refptr_same + return CefContextMenuHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetDialogHandler() { + if (CEF_MEMBER_MISSING(struct_, get_dialog_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dialog_handler_t* _retval = struct_->get_dialog_handler(struct_); + + // Return type: refptr_same + return CefDialogHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetDisplayHandler() { + if (CEF_MEMBER_MISSING(struct_, get_display_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_display_handler_t* _retval = struct_->get_display_handler(struct_); + + // Return type: refptr_same + return CefDisplayHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetDownloadHandler() { + if (CEF_MEMBER_MISSING(struct_, get_download_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_download_handler_t* _retval = struct_->get_download_handler(struct_); + + // Return type: refptr_same + return CefDownloadHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetDragHandler() { + if (CEF_MEMBER_MISSING(struct_, get_drag_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_drag_handler_t* _retval = struct_->get_drag_handler(struct_); + + // Return type: refptr_same + return CefDragHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetFocusHandler() { + if (CEF_MEMBER_MISSING(struct_, get_focus_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_focus_handler_t* _retval = struct_->get_focus_handler(struct_); + + // Return type: refptr_same + return CefFocusHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetGeolocationHandler() { + if (CEF_MEMBER_MISSING(struct_, get_geolocation_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_geolocation_handler_t* _retval = struct_->get_geolocation_handler( + struct_); + + // Return type: refptr_same + return CefGeolocationHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetJSDialogHandler() { + if (CEF_MEMBER_MISSING(struct_, get_jsdialog_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_jsdialog_handler_t* _retval = struct_->get_jsdialog_handler(struct_); + + // Return type: refptr_same + return CefJSDialogHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetKeyboardHandler() { + if (CEF_MEMBER_MISSING(struct_, get_keyboard_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_keyboard_handler_t* _retval = struct_->get_keyboard_handler(struct_); + + // Return type: refptr_same + return CefKeyboardHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetLifeSpanHandler() { + if (CEF_MEMBER_MISSING(struct_, get_life_span_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_life_span_handler_t* _retval = struct_->get_life_span_handler(struct_); + + // Return type: refptr_same + return CefLifeSpanHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetLoadHandler() { + if (CEF_MEMBER_MISSING(struct_, get_load_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_load_handler_t* _retval = struct_->get_load_handler(struct_); + + // Return type: refptr_same + return CefLoadHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetRenderHandler() { + if (CEF_MEMBER_MISSING(struct_, get_render_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_render_handler_t* _retval = struct_->get_render_handler(struct_); + + // Return type: refptr_same + return CefRenderHandlerCToCpp::Wrap(_retval); +} + +CefRefPtr CefClientCToCpp::GetRequestHandler() { + if (CEF_MEMBER_MISSING(struct_, get_request_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_handler_t* _retval = struct_->get_request_handler(struct_); + + // Return type: refptr_same + return CefRequestHandlerCToCpp::Wrap(_retval); +} + +bool CefClientCToCpp::OnProcessMessageReceived(CefRefPtr browser, + CefProcessId source_process, CefRefPtr message) { + if (CEF_MEMBER_MISSING(struct_, on_process_message_received)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: message; type: refptr_diff + DCHECK(message.get()); + if (!message.get()) + return false; + + // Execute + int _retval = struct_->on_process_message_received(struct_, + CefBrowserCppToC::Wrap(browser), + source_process, + CefProcessMessageCppToC::Wrap(message)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/client_ctocpp.h b/libcef_dll/ctocpp/client_ctocpp.h new file mode 100644 index 000000000..e793c39f1 --- /dev/null +++ b/libcef_dll/ctocpp/client_ctocpp.h @@ -0,0 +1,55 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefClientCToCpp + : public CefCToCpp { + public: + explicit CefClientCToCpp(cef_client_t* str) + : CefCToCpp(str) {} + virtual ~CefClientCToCpp() {} + + // CefClient methods + virtual CefRefPtr GetContextMenuHandler() OVERRIDE; + virtual CefRefPtr GetDialogHandler() OVERRIDE; + virtual CefRefPtr GetDisplayHandler() OVERRIDE; + virtual CefRefPtr GetDownloadHandler() OVERRIDE; + virtual CefRefPtr GetDragHandler() OVERRIDE; + virtual CefRefPtr GetFocusHandler() OVERRIDE; + virtual CefRefPtr GetGeolocationHandler() OVERRIDE; + virtual CefRefPtr GetJSDialogHandler() OVERRIDE; + virtual CefRefPtr GetKeyboardHandler() OVERRIDE; + virtual CefRefPtr GetLifeSpanHandler() OVERRIDE; + virtual CefRefPtr GetLoadHandler() OVERRIDE; + virtual CefRefPtr GetRenderHandler() OVERRIDE; + virtual CefRefPtr GetRequestHandler() OVERRIDE; + virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/command_line_ctocpp.cc b/libcef_dll/ctocpp/command_line_ctocpp.cc new file mode 100644 index 000000000..f08030da3 --- /dev/null +++ b/libcef_dll/ctocpp/command_line_ctocpp.cc @@ -0,0 +1,398 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "include/cef_version.h" +#include "libcef_dll/ctocpp/command_line_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefCommandLine::CreateCommandLine() { + const char* api_hash = cef_api_hash(0); + if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) { + // The libcef API hash does not match the current header API hash. + NOTREACHED(); + return NULL; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_command_line_t* _retval = cef_command_line_create(); + + // Return type: refptr_same + return CefCommandLineCToCpp::Wrap(_retval); +} + +CefRefPtr CefCommandLine::GetGlobalCommandLine() { + const char* api_hash = cef_api_hash(0); + if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) { + // The libcef API hash does not match the current header API hash. + NOTREACHED(); + return NULL; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_command_line_t* _retval = cef_command_line_get_global(); + + // Return type: refptr_same + return CefCommandLineCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefCommandLineCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefCommandLineCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefCommandLineCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_command_line_t* _retval = struct_->copy(struct_); + + // Return type: refptr_same + return CefCommandLineCToCpp::Wrap(_retval); +} + +void CefCommandLineCToCpp::InitFromArgv(int argc, const char* const* argv) { + if (CEF_MEMBER_MISSING(struct_, init_from_argv)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: argv; type: simple_byaddr + DCHECK(argv); + if (!argv) + return; + + // Execute + struct_->init_from_argv(struct_, + argc, + argv); +} + +void CefCommandLineCToCpp::InitFromString(const CefString& command_line) { + if (CEF_MEMBER_MISSING(struct_, init_from_string)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: command_line; type: string_byref_const + DCHECK(!command_line.empty()); + if (command_line.empty()) + return; + + // Execute + struct_->init_from_string(struct_, + command_line.GetStruct()); +} + +void CefCommandLineCToCpp::Reset() { + if (CEF_MEMBER_MISSING(struct_, reset)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->reset(struct_); +} + +void CefCommandLineCToCpp::GetArgv(std::vector& argv) { + if (CEF_MEMBER_MISSING(struct_, get_argv)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: argv; type: string_vec_byref + cef_string_list_t argvList = cef_string_list_alloc(); + DCHECK(argvList); + if (argvList) + transfer_string_list_contents(argv, argvList); + + // Execute + struct_->get_argv(struct_, + argvList); + + // Restore param:argv; type: string_vec_byref + if (argvList) { + argv.clear(); + transfer_string_list_contents(argvList, argv); + cef_string_list_free(argvList); + } +} + +CefString CefCommandLineCToCpp::GetCommandLineString() { + if (CEF_MEMBER_MISSING(struct_, get_command_line_string)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_command_line_string(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefCommandLineCToCpp::GetProgram() { + if (CEF_MEMBER_MISSING(struct_, get_program)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_program(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefCommandLineCToCpp::SetProgram(const CefString& program) { + if (CEF_MEMBER_MISSING(struct_, set_program)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: program; type: string_byref_const + DCHECK(!program.empty()); + if (program.empty()) + return; + + // Execute + struct_->set_program(struct_, + program.GetStruct()); +} + +bool CefCommandLineCToCpp::HasSwitches() { + if (CEF_MEMBER_MISSING(struct_, has_switches)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_switches(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefCommandLineCToCpp::HasSwitch(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, has_switch)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return false; + + // Execute + int _retval = struct_->has_switch(struct_, + name.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefString CefCommandLineCToCpp::GetSwitchValue(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, get_switch_value)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_switch_value(struct_, + name.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefCommandLineCToCpp::GetSwitches(SwitchMap& switches) { + if (CEF_MEMBER_MISSING(struct_, get_switches)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: switches; type: string_map_single_byref + cef_string_map_t switchesMap = cef_string_map_alloc(); + DCHECK(switchesMap); + if (switchesMap) + transfer_string_map_contents(switches, switchesMap); + + // Execute + struct_->get_switches(struct_, + switchesMap); + + // Restore param:switches; type: string_map_single_byref + if (switchesMap) { + switches.clear(); + transfer_string_map_contents(switchesMap, switches); + cef_string_map_free(switchesMap); + } +} + +void CefCommandLineCToCpp::AppendSwitch(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, append_switch)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return; + + // Execute + struct_->append_switch(struct_, + name.GetStruct()); +} + +void CefCommandLineCToCpp::AppendSwitchWithValue(const CefString& name, + const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, append_switch_with_value)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return; + // Verify param: value; type: string_byref_const + DCHECK(!value.empty()); + if (value.empty()) + return; + + // Execute + struct_->append_switch_with_value(struct_, + name.GetStruct(), + value.GetStruct()); +} + +bool CefCommandLineCToCpp::HasArguments() { + if (CEF_MEMBER_MISSING(struct_, has_arguments)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_arguments(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefCommandLineCToCpp::GetArguments(ArgumentList& arguments) { + if (CEF_MEMBER_MISSING(struct_, get_arguments)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: arguments; type: string_vec_byref + cef_string_list_t argumentsList = cef_string_list_alloc(); + DCHECK(argumentsList); + if (argumentsList) + transfer_string_list_contents(arguments, argumentsList); + + // Execute + struct_->get_arguments(struct_, + argumentsList); + + // Restore param:arguments; type: string_vec_byref + if (argumentsList) { + arguments.clear(); + transfer_string_list_contents(argumentsList, arguments); + cef_string_list_free(argumentsList); + } +} + +void CefCommandLineCToCpp::AppendArgument(const CefString& argument) { + if (CEF_MEMBER_MISSING(struct_, append_argument)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: argument; type: string_byref_const + DCHECK(!argument.empty()); + if (argument.empty()) + return; + + // Execute + struct_->append_argument(struct_, + argument.GetStruct()); +} + +void CefCommandLineCToCpp::PrependWrapper(const CefString& wrapper) { + if (CEF_MEMBER_MISSING(struct_, prepend_wrapper)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: wrapper; type: string_byref_const + DCHECK(!wrapper.empty()); + if (wrapper.empty()) + return; + + // Execute + struct_->prepend_wrapper(struct_, + wrapper.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/command_line_ctocpp.h b/libcef_dll/ctocpp/command_line_ctocpp.h new file mode 100644 index 000000000..b73bff999 --- /dev/null +++ b/libcef_dll/ctocpp/command_line_ctocpp.h @@ -0,0 +1,63 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_COMMAND_LINE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_COMMAND_LINE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_command_line.h" +#include "include/capi/cef_command_line_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefCommandLineCToCpp + : public CefCToCpp { + public: + explicit CefCommandLineCToCpp(cef_command_line_t* str) + : CefCToCpp( + str) {} + virtual ~CefCommandLineCToCpp() {} + + // CefCommandLine methods + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual void InitFromArgv(int argc, const char* const* argv) OVERRIDE; + virtual void InitFromString(const CefString& command_line) OVERRIDE; + virtual void Reset() OVERRIDE; + virtual void GetArgv(std::vector& argv) OVERRIDE; + virtual CefString GetCommandLineString() OVERRIDE; + virtual CefString GetProgram() OVERRIDE; + virtual void SetProgram(const CefString& program) OVERRIDE; + virtual bool HasSwitches() OVERRIDE; + virtual bool HasSwitch(const CefString& name) OVERRIDE; + virtual CefString GetSwitchValue(const CefString& name) OVERRIDE; + virtual void GetSwitches(SwitchMap& switches) OVERRIDE; + virtual void AppendSwitch(const CefString& name) OVERRIDE; + virtual void AppendSwitchWithValue(const CefString& name, + const CefString& value) OVERRIDE; + virtual bool HasArguments() OVERRIDE; + virtual void GetArguments(ArgumentList& arguments) OVERRIDE; + virtual void AppendArgument(const CefString& argument) OVERRIDE; + virtual void PrependWrapper(const CefString& wrapper) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_COMMAND_LINE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/completion_callback_ctocpp.cc b/libcef_dll/ctocpp/completion_callback_ctocpp.cc new file mode 100644 index 000000000..7f6efbfd6 --- /dev/null +++ b/libcef_dll/ctocpp/completion_callback_ctocpp.cc @@ -0,0 +1,33 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/completion_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefCompletionCallbackCToCpp::OnComplete() { + if (CEF_MEMBER_MISSING(struct_, on_complete)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_complete(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/completion_callback_ctocpp.h b/libcef_dll/ctocpp/completion_callback_ctocpp.h new file mode 100644 index 000000000..7435c0088 --- /dev/null +++ b/libcef_dll/ctocpp/completion_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_COMPLETION_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_COMPLETION_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_callback.h" +#include "include/capi/cef_callback_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefCompletionCallbackCToCpp + : public CefCToCpp { + public: + explicit CefCompletionCallbackCToCpp(cef_completion_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefCompletionCallbackCToCpp() {} + + // CefCompletionCallback methods + virtual void OnComplete() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_COMPLETION_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc b/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc new file mode 100644 index 000000000..a94020cef --- /dev/null +++ b/libcef_dll/ctocpp/context_menu_handler_ctocpp.cc @@ -0,0 +1,116 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/context_menu_params_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/menu_model_cpptoc.h" +#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefContextMenuHandlerCToCpp::OnBeforeContextMenu( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr params, CefRefPtr model) { + if (CEF_MEMBER_MISSING(struct_, on_before_context_menu)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: params; type: refptr_diff + DCHECK(params.get()); + if (!params.get()) + return; + // Verify param: model; type: refptr_diff + DCHECK(model.get()); + if (!model.get()) + return; + + // Execute + struct_->on_before_context_menu(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefContextMenuParamsCppToC::Wrap(params), + CefMenuModelCppToC::Wrap(model)); +} + +bool CefContextMenuHandlerCToCpp::OnContextMenuCommand( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr params, int command_id, + EventFlags event_flags) { + if (CEF_MEMBER_MISSING(struct_, on_context_menu_command)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: params; type: refptr_diff + DCHECK(params.get()); + if (!params.get()) + return false; + + // Execute + int _retval = struct_->on_context_menu_command(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefContextMenuParamsCppToC::Wrap(params), + command_id, + event_flags); + + // Return type: bool + return _retval?true:false; +} + +void CefContextMenuHandlerCToCpp::OnContextMenuDismissed( + CefRefPtr browser, CefRefPtr frame) { + if (CEF_MEMBER_MISSING(struct_, on_context_menu_dismissed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + + // Execute + struct_->on_context_menu_dismissed(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/context_menu_handler_ctocpp.h b/libcef_dll/ctocpp/context_menu_handler_ctocpp.h new file mode 100644 index 000000000..2fc4afda8 --- /dev/null +++ b/libcef_dll/ctocpp/context_menu_handler_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_context_menu_handler.h" +#include "include/capi/cef_context_menu_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefContextMenuHandlerCToCpp + : public CefCToCpp { + public: + explicit CefContextMenuHandlerCToCpp(cef_context_menu_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefContextMenuHandlerCToCpp() {} + + // CefContextMenuHandler methods + virtual void OnBeforeContextMenu(CefRefPtr browser, + CefRefPtr frame, CefRefPtr params, + CefRefPtr model) OVERRIDE; + virtual bool OnContextMenuCommand(CefRefPtr browser, + CefRefPtr frame, CefRefPtr params, + int command_id, EventFlags event_flags) OVERRIDE; + virtual void OnContextMenuDismissed(CefRefPtr browser, + CefRefPtr frame) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/context_menu_params_ctocpp.cc b/libcef_dll/ctocpp/context_menu_params_ctocpp.cc new file mode 100644 index 000000000..8748c3641 --- /dev/null +++ b/libcef_dll/ctocpp/context_menu_params_ctocpp.cc @@ -0,0 +1,236 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/context_menu_params_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +int CefContextMenuParamsCToCpp::GetXCoord() { + if (CEF_MEMBER_MISSING(struct_, get_xcoord)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_xcoord(struct_); + + // Return type: simple + return _retval; +} + +int CefContextMenuParamsCToCpp::GetYCoord() { + if (CEF_MEMBER_MISSING(struct_, get_ycoord)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_ycoord(struct_); + + // Return type: simple + return _retval; +} + +CefContextMenuParams::TypeFlags CefContextMenuParamsCToCpp::GetTypeFlags() { + if (CEF_MEMBER_MISSING(struct_, get_type_flags)) + return CM_TYPEFLAG_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_context_menu_type_flags_t _retval = struct_->get_type_flags(struct_); + + // Return type: simple + return _retval; +} + +CefString CefContextMenuParamsCToCpp::GetLinkUrl() { + if (CEF_MEMBER_MISSING(struct_, get_link_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_link_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefContextMenuParamsCToCpp::GetUnfilteredLinkUrl() { + if (CEF_MEMBER_MISSING(struct_, get_unfiltered_link_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_unfiltered_link_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefContextMenuParamsCToCpp::GetSourceUrl() { + if (CEF_MEMBER_MISSING(struct_, get_source_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_source_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefContextMenuParamsCToCpp::HasImageContents() { + if (CEF_MEMBER_MISSING(struct_, has_image_contents)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_image_contents(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefContextMenuParamsCToCpp::GetPageUrl() { + if (CEF_MEMBER_MISSING(struct_, get_page_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_page_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefContextMenuParamsCToCpp::GetFrameUrl() { + if (CEF_MEMBER_MISSING(struct_, get_frame_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_frame_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefContextMenuParamsCToCpp::GetFrameCharset() { + if (CEF_MEMBER_MISSING(struct_, get_frame_charset)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_frame_charset(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefContextMenuParams::MediaType CefContextMenuParamsCToCpp::GetMediaType() { + if (CEF_MEMBER_MISSING(struct_, get_media_type)) + return CM_MEDIATYPE_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_context_menu_media_type_t _retval = struct_->get_media_type(struct_); + + // Return type: simple + return _retval; +} + +CefContextMenuParams::MediaStateFlags CefContextMenuParamsCToCpp::GetMediaStateFlags( + ) { + if (CEF_MEMBER_MISSING(struct_, get_media_state_flags)) + return CM_MEDIAFLAG_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_context_menu_media_state_flags_t _retval = struct_->get_media_state_flags( + struct_); + + // Return type: simple + return _retval; +} + +CefString CefContextMenuParamsCToCpp::GetSelectionText() { + if (CEF_MEMBER_MISSING(struct_, get_selection_text)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_selection_text(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefContextMenuParamsCToCpp::IsEditable() { + if (CEF_MEMBER_MISSING(struct_, is_editable)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_editable(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefContextMenuParams::EditStateFlags CefContextMenuParamsCToCpp::GetEditStateFlags( + ) { + if (CEF_MEMBER_MISSING(struct_, get_edit_state_flags)) + return CM_EDITFLAG_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_context_menu_edit_state_flags_t _retval = struct_->get_edit_state_flags( + struct_); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/context_menu_params_ctocpp.h b/libcef_dll/ctocpp/context_menu_params_ctocpp.h new file mode 100644 index 000000000..e23ff501b --- /dev/null +++ b/libcef_dll/ctocpp/context_menu_params_ctocpp.h @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_PARAMS_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_PARAMS_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_context_menu_handler.h" +#include "include/capi/cef_context_menu_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefContextMenuParamsCToCpp + : public CefCToCpp { + public: + explicit CefContextMenuParamsCToCpp(cef_context_menu_params_t* str) + : CefCToCpp(str) {} + virtual ~CefContextMenuParamsCToCpp() {} + + // CefContextMenuParams methods + virtual int GetXCoord() OVERRIDE; + virtual int GetYCoord() OVERRIDE; + virtual TypeFlags GetTypeFlags() OVERRIDE; + virtual CefString GetLinkUrl() OVERRIDE; + virtual CefString GetUnfilteredLinkUrl() OVERRIDE; + virtual CefString GetSourceUrl() OVERRIDE; + virtual bool HasImageContents() OVERRIDE; + virtual CefString GetPageUrl() OVERRIDE; + virtual CefString GetFrameUrl() OVERRIDE; + virtual CefString GetFrameCharset() OVERRIDE; + virtual MediaType GetMediaType() OVERRIDE; + virtual MediaStateFlags GetMediaStateFlags() OVERRIDE; + virtual CefString GetSelectionText() OVERRIDE; + virtual bool IsEditable() OVERRIDE; + virtual EditStateFlags GetEditStateFlags() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_PARAMS_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc new file mode 100644 index 000000000..c081f606f --- /dev/null +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc @@ -0,0 +1,199 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/completion_callback_cpptoc.h" +#include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefCookieManager::GetGlobalManager() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_cookie_manager_t* _retval = cef_cookie_manager_get_global_manager(); + + // Return type: refptr_same + return CefCookieManagerCToCpp::Wrap(_retval); +} + +CefRefPtr CefCookieManager::CreateManager( + const CefString& path, bool persist_session_cookies) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + cef_cookie_manager_t* _retval = cef_cookie_manager_create_manager( + path.GetStruct(), + persist_session_cookies); + + // Return type: refptr_same + return CefCookieManagerCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefCookieManagerCToCpp::SetSupportedSchemes( + const std::vector& schemes) { + if (CEF_MEMBER_MISSING(struct_, set_supported_schemes)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: schemes; type: string_vec_byref_const + cef_string_list_t schemesList = cef_string_list_alloc(); + DCHECK(schemesList); + if (schemesList) + transfer_string_list_contents(schemes, schemesList); + + // Execute + struct_->set_supported_schemes(struct_, + schemesList); + + // Restore param:schemes; type: string_vec_byref_const + if (schemesList) + cef_string_list_free(schemesList); +} + +bool CefCookieManagerCToCpp::VisitAllCookies( + CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, visit_all_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return false; + + // Execute + int _retval = struct_->visit_all_cookies(struct_, + CefCookieVisitorCppToC::Wrap(visitor)); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::VisitUrlCookies(const CefString& url, + bool includeHttpOnly, CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, visit_url_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return false; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return false; + + // Execute + int _retval = struct_->visit_url_cookies(struct_, + url.GetStruct(), + includeHttpOnly, + CefCookieVisitorCppToC::Wrap(visitor)); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::SetCookie(const CefString& url, + const CefCookie& cookie) { + if (CEF_MEMBER_MISSING(struct_, set_cookie)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return false; + + // Execute + int _retval = struct_->set_cookie(struct_, + url.GetStruct(), + &cookie); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::DeleteCookies(const CefString& url, + const CefString& cookie_name) { + if (CEF_MEMBER_MISSING(struct_, delete_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: url, cookie_name + + // Execute + int _retval = struct_->delete_cookies(struct_, + url.GetStruct(), + cookie_name.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::SetStoragePath(const CefString& path, + bool persist_session_cookies) { + if (CEF_MEMBER_MISSING(struct_, set_storage_path)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + int _retval = struct_->set_storage_path(struct_, + path.GetStruct(), + persist_session_cookies); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::FlushStore( + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, flush_store)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->flush_store(struct_, + CefCompletionCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.h b/libcef_dll/ctocpp/cookie_manager_ctocpp.h new file mode 100644 index 000000000..f6c2127c7 --- /dev/null +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.h @@ -0,0 +1,54 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefCookieManagerCToCpp + : public CefCToCpp { + public: + explicit CefCookieManagerCToCpp(cef_cookie_manager_t* str) + : CefCToCpp(str) {} + virtual ~CefCookieManagerCToCpp() {} + + // CefCookieManager methods + virtual void SetSupportedSchemes( + const std::vector& schemes) OVERRIDE; + virtual bool VisitAllCookies(CefRefPtr visitor) OVERRIDE; + virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, + CefRefPtr visitor) OVERRIDE; + virtual bool SetCookie(const CefString& url, + const CefCookie& cookie) OVERRIDE; + virtual bool DeleteCookies(const CefString& url, + const CefString& cookie_name) OVERRIDE; + virtual bool SetStoragePath(const CefString& path, + bool persist_session_cookies) OVERRIDE; + virtual bool FlushStore(CefRefPtr callback) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc b/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc new file mode 100644 index 000000000..bd2cb3180 --- /dev/null +++ b/libcef_dll/ctocpp/cookie_visitor_ctocpp.cc @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefCookieVisitorCToCpp::Visit(const CefCookie& cookie, int count, + int total, bool& deleteCookie) { + if (CEF_MEMBER_MISSING(struct_, visit)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: deleteCookie; type: bool_byref + int deleteCookieInt = deleteCookie; + + // Execute + int _retval = struct_->visit(struct_, + &cookie, + count, + total, + &deleteCookieInt); + + // Restore param:deleteCookie; type: bool_byref + deleteCookie = deleteCookieInt?true:false; + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/cookie_visitor_ctocpp.h b/libcef_dll/ctocpp/cookie_visitor_ctocpp.h new file mode 100644 index 000000000..02ce5ce73 --- /dev/null +++ b/libcef_dll/ctocpp/cookie_visitor_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_VISITOR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_COOKIE_VISITOR_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefCookieVisitorCToCpp + : public CefCToCpp { + public: + explicit CefCookieVisitorCToCpp(cef_cookie_visitor_t* str) + : CefCToCpp(str) {} + virtual ~CefCookieVisitorCToCpp() {} + + // CefCookieVisitor methods + virtual bool Visit(const CefCookie& cookie, int count, int total, + bool& deleteCookie) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_COOKIE_VISITOR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/ctocpp.h b/libcef_dll/ctocpp/ctocpp.h new file mode 100644 index 000000000..063fe1cfd --- /dev/null +++ b/libcef_dll/ctocpp/ctocpp.h @@ -0,0 +1,117 @@ +// 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_LIBCEF_DLL_CTOCPP_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_CTOCPP_H_ +#pragma once + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_base.h" +#include "include/capi/cef_base_capi.h" + +// Wrap a C structure with a C++ class. This is used when the implementation +// exists on the other side of the DLL boundary but will have methods called on +// this side of the DLL boundary. +template +class CefCToCpp : public BaseName { + public: + // Use this method to create a wrapper class instance for a structure + // received from the other side. + static CefRefPtr Wrap(StructName* s) { + if (!s) + return NULL; + + // Wrap their structure with the CefCToCpp object. + ClassName* wrapper = new ClassName(s); + // Put the wrapper object in a smart pointer. + CefRefPtr wrapperPtr(wrapper); + // Release the reference that was added to the CefCppToC wrapper object on + // the other side before their structure was passed to us. + wrapper->UnderlyingRelease(); + // Return the smart pointer. + return wrapperPtr; + } + + // Use this method to retrieve the underlying structure from a wrapper class + // instance for return back to the other side. + static StructName* Unwrap(CefRefPtr c) { + if (!c.get()) + return NULL; + + // Cast the object to our wrapper class type. + ClassName* wrapper = static_cast(c.get()); + // Add a reference to the CefCppToC wrapper object on the other side that + // will be released once the structure is received. + wrapper->UnderlyingAddRef(); + // Return their original structure. + return wrapper->GetStruct(); + } + + explicit CefCToCpp(StructName* str) + : struct_(str) { + DCHECK(str); + +#ifndef NDEBUG + base::AtomicRefCountInc(&DebugObjCt); +#endif + } + virtual ~CefCToCpp() { +#ifndef NDEBUG + base::AtomicRefCountDec(&DebugObjCt); +#endif + } + + // If returning the structure across the DLL boundary you should call + // UnderlyingAddRef() on this wrapping CefCToCpp object. On the other side of + // the DLL boundary, call Release() on the CefCppToC object. + StructName* GetStruct() { return struct_; } + + // CefBase methods increment/decrement reference counts on both this object + // and the underlying wrapped structure. + void AddRef() const { + UnderlyingAddRef(); + ref_count_.AddRef(); + } + bool Release() const { + UnderlyingRelease(); + if (ref_count_.Release()) { + delete this; + return true; + } + return false; + } + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + // Increment/decrement reference counts on only the underlying class. + void UnderlyingAddRef() const { + if (struct_->base.add_ref) + struct_->base.add_ref(&struct_->base); + } + bool UnderlyingRelease() const { + if (!struct_->base.release) + return false; + return struct_->base.release(&struct_->base) ? true : false; + } + bool UnderlyingHasOneRef() const { + if (!struct_->base.has_one_ref) + return false; + return struct_->base.has_one_ref(&struct_->base) ? true : false; + } + +#ifndef NDEBUG + // Simple tracking of allocated objects. + static base::AtomicRefCount DebugObjCt; // NOLINT(runtime/int) +#endif + + protected: + StructName* struct_; + + private: + CefRefCount ref_count_; + + DISALLOW_COPY_AND_ASSIGN(CefCToCpp); +}; + +#endif // CEF_LIBCEF_DLL_CTOCPP_CTOCPP_H_ diff --git a/libcef_dll/ctocpp/dialog_handler_ctocpp.cc b/libcef_dll/ctocpp/dialog_handler_ctocpp.cc new file mode 100644 index 000000000..27ac4468f --- /dev/null +++ b/libcef_dll/ctocpp/dialog_handler_ctocpp.cc @@ -0,0 +1,69 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h" +#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefDialogHandlerCToCpp::OnFileDialog(CefRefPtr browser, + FileDialogMode mode, const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_file_dialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: title, default_file_name, accept_types + + // Translate param: accept_types; type: string_vec_byref_const + cef_string_list_t accept_typesList = cef_string_list_alloc(); + DCHECK(accept_typesList); + if (accept_typesList) + transfer_string_list_contents(accept_types, accept_typesList); + + // Execute + int _retval = struct_->on_file_dialog(struct_, + CefBrowserCppToC::Wrap(browser), + mode, + title.GetStruct(), + default_file_name.GetStruct(), + accept_typesList, + CefFileDialogCallbackCppToC::Wrap(callback)); + + // Restore param:accept_types; type: string_vec_byref_const + if (accept_typesList) + cef_string_list_free(accept_typesList); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/dialog_handler_ctocpp.h b/libcef_dll/ctocpp/dialog_handler_ctocpp.h new file mode 100644 index 000000000..8ecc578cd --- /dev/null +++ b/libcef_dll/ctocpp/dialog_handler_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include +#include "include/cef_dialog_handler.h" +#include "include/capi/cef_dialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDialogHandlerCToCpp + : public CefCToCpp { + public: + explicit CefDialogHandlerCToCpp(cef_dialog_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefDialogHandlerCToCpp() {} + + // CefDialogHandler methods + virtual bool OnFileDialog(CefRefPtr browser, FileDialogMode mode, + const CefString& title, const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DIALOG_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/dictionary_value_ctocpp.cc b/libcef_dll/ctocpp/dictionary_value_ctocpp.cc new file mode 100644 index 000000000..25401a289 --- /dev/null +++ b/libcef_dll/ctocpp/dictionary_value_ctocpp.cc @@ -0,0 +1,517 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/binary_value_ctocpp.h" +#include "libcef_dll/ctocpp/dictionary_value_ctocpp.h" +#include "libcef_dll/ctocpp/list_value_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefDictionaryValue::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dictionary_value_t* _retval = cef_dictionary_value_create(); + + // Return type: refptr_same + return CefDictionaryValueCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefDictionaryValueCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::IsOwned() { + if (CEF_MEMBER_MISSING(struct_, is_owned)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_owned(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefDictionaryValueCToCpp::Copy( + bool exclude_empty_children) { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dictionary_value_t* _retval = struct_->copy(struct_, + exclude_empty_children); + + // Return type: refptr_same + return CefDictionaryValueCToCpp::Wrap(_retval); +} + +size_t CefDictionaryValueCToCpp::GetSize() { + if (CEF_MEMBER_MISSING(struct_, get_size)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_size(struct_); + + // Return type: simple + return _retval; +} + +bool CefDictionaryValueCToCpp::Clear() { + if (CEF_MEMBER_MISSING(struct_, clear)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->clear(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::HasKey(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, has_key)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->has_key(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::GetKeys(KeyList& keys) { + if (CEF_MEMBER_MISSING(struct_, get_keys)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: keys; type: string_vec_byref + cef_string_list_t keysList = cef_string_list_alloc(); + DCHECK(keysList); + if (keysList) + transfer_string_list_contents(keys, keysList); + + // Execute + int _retval = struct_->get_keys(struct_, + keysList); + + // Restore param:keys; type: string_vec_byref + if (keysList) { + keys.clear(); + transfer_string_list_contents(keysList, keys); + cef_string_list_free(keysList); + } + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::Remove(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, remove)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->remove(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefValueType CefDictionaryValueCToCpp::GetType(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return VTYPE_INVALID; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return VTYPE_INVALID; + + // Execute + cef_value_type_t _retval = struct_->get_type(struct_, + key.GetStruct()); + + // Return type: simple + return _retval; +} + +bool CefDictionaryValueCToCpp::GetBool(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_bool)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->get_bool(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +int CefDictionaryValueCToCpp::GetInt(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_int)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return 0; + + // Execute + int _retval = struct_->get_int(struct_, + key.GetStruct()); + + // Return type: simple + return _retval; +} + +double CefDictionaryValueCToCpp::GetDouble(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_double)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return 0; + + // Execute + double _retval = struct_->get_double(struct_, + key.GetStruct()); + + // Return type: simple + return _retval; +} + +CefString CefDictionaryValueCToCpp::GetString(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_string)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_string(struct_, + key.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefDictionaryValueCToCpp::GetBinary( + const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_binary)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return NULL; + + // Execute + cef_binary_value_t* _retval = struct_->get_binary(struct_, + key.GetStruct()); + + // Return type: refptr_same + return CefBinaryValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefDictionaryValueCToCpp::GetDictionary( + const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_dictionary)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return NULL; + + // Execute + cef_dictionary_value_t* _retval = struct_->get_dictionary(struct_, + key.GetStruct()); + + // Return type: refptr_same + return CefDictionaryValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefDictionaryValueCToCpp::GetList( + const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_list)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return NULL; + + // Execute + cef_list_value_t* _retval = struct_->get_list(struct_, + key.GetStruct()); + + // Return type: refptr_same + return CefListValueCToCpp::Wrap(_retval); +} + +bool CefDictionaryValueCToCpp::SetNull(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, set_null)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->set_null(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetBool(const CefString& key, bool value) { + if (CEF_MEMBER_MISSING(struct_, set_bool)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->set_bool(struct_, + key.GetStruct(), + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetInt(const CefString& key, int value) { + if (CEF_MEMBER_MISSING(struct_, set_int)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->set_int(struct_, + key.GetStruct(), + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetDouble(const CefString& key, double value) { + if (CEF_MEMBER_MISSING(struct_, set_double)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + + // Execute + int _retval = struct_->set_double(struct_, + key.GetStruct(), + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetString(const CefString& key, + const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, set_string)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + // Unverified params: value + + // Execute + int _retval = struct_->set_string(struct_, + key.GetStruct(), + value.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetBinary(const CefString& key, + CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_binary)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_binary(struct_, + key.GetStruct(), + CefBinaryValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetDictionary(const CefString& key, + CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_dictionary)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_dictionary(struct_, + key.GetStruct(), + CefDictionaryValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + +bool CefDictionaryValueCToCpp::SetList(const CefString& key, + CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_list)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: key; type: string_byref_const + DCHECK(!key.empty()); + if (key.empty()) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_list(struct_, + key.GetStruct(), + CefListValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/dictionary_value_ctocpp.h b/libcef_dll/ctocpp/dictionary_value_ctocpp.h new file mode 100644 index 000000000..6d7b7e486 --- /dev/null +++ b/libcef_dll/ctocpp/dictionary_value_ctocpp.h @@ -0,0 +1,71 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DICTIONARY_VALUE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DICTIONARY_VALUE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDictionaryValueCToCpp + : public CefCToCpp { + public: + explicit CefDictionaryValueCToCpp(cef_dictionary_value_t* str) + : CefCToCpp(str) {} + virtual ~CefDictionaryValueCToCpp() {} + + // CefDictionaryValue methods + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy( + bool exclude_empty_children) OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual bool Clear() OVERRIDE; + virtual bool HasKey(const CefString& key) OVERRIDE; + virtual bool GetKeys(KeyList& keys) OVERRIDE; + virtual bool Remove(const CefString& key) OVERRIDE; + virtual CefValueType GetType(const CefString& key) OVERRIDE; + virtual bool GetBool(const CefString& key) OVERRIDE; + virtual int GetInt(const CefString& key) OVERRIDE; + virtual double GetDouble(const CefString& key) OVERRIDE; + virtual CefString GetString(const CefString& key) OVERRIDE; + virtual CefRefPtr GetBinary(const CefString& key) OVERRIDE; + virtual CefRefPtr GetDictionary( + const CefString& key) OVERRIDE; + virtual CefRefPtr GetList(const CefString& key) OVERRIDE; + virtual bool SetNull(const CefString& key) OVERRIDE; + virtual bool SetBool(const CefString& key, bool value) OVERRIDE; + virtual bool SetInt(const CefString& key, int value) OVERRIDE; + virtual bool SetDouble(const CefString& key, double value) OVERRIDE; + virtual bool SetString(const CefString& key, const CefString& value) OVERRIDE; + virtual bool SetBinary(const CefString& key, + CefRefPtr value) OVERRIDE; + virtual bool SetDictionary(const CefString& key, + CefRefPtr value) OVERRIDE; + virtual bool SetList(const CefString& key, + CefRefPtr value) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DICTIONARY_VALUE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/display_handler_ctocpp.cc b/libcef_dll/ctocpp/display_handler_ctocpp.cc new file mode 100644 index 000000000..bdeb9f054 --- /dev/null +++ b/libcef_dll/ctocpp/display_handler_ctocpp.cc @@ -0,0 +1,136 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/ctocpp/display_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDisplayHandlerCToCpp::OnAddressChange(CefRefPtr browser, + CefRefPtr frame, const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, on_address_change)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->on_address_change(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + url.GetStruct()); +} + +void CefDisplayHandlerCToCpp::OnTitleChange(CefRefPtr browser, + const CefString& title) { + if (CEF_MEMBER_MISSING(struct_, on_title_change)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Unverified params: title + + // Execute + struct_->on_title_change(struct_, + CefBrowserCppToC::Wrap(browser), + title.GetStruct()); +} + +bool CefDisplayHandlerCToCpp::OnTooltip(CefRefPtr browser, + CefString& text) { + if (CEF_MEMBER_MISSING(struct_, on_tooltip)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Unverified params: text + + // Execute + int _retval = struct_->on_tooltip(struct_, + CefBrowserCppToC::Wrap(browser), + text.GetWritableStruct()); + + // Return type: bool + return _retval?true:false; +} + +void CefDisplayHandlerCToCpp::OnStatusMessage(CefRefPtr browser, + const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, on_status_message)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Unverified params: value + + // Execute + struct_->on_status_message(struct_, + CefBrowserCppToC::Wrap(browser), + value.GetStruct()); +} + +bool CefDisplayHandlerCToCpp::OnConsoleMessage(CefRefPtr browser, + const CefString& message, const CefString& source, int line) { + if (CEF_MEMBER_MISSING(struct_, on_console_message)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Unverified params: message, source + + // Execute + int _retval = struct_->on_console_message(struct_, + CefBrowserCppToC::Wrap(browser), + message.GetStruct(), + source.GetStruct(), + line); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/display_handler_ctocpp.h b/libcef_dll/ctocpp/display_handler_ctocpp.h new file mode 100644 index 000000000..f2fd5b3a7 --- /dev/null +++ b/libcef_dll/ctocpp/display_handler_ctocpp.h @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DISPLAY_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DISPLAY_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_display_handler.h" +#include "include/capi/cef_display_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDisplayHandlerCToCpp + : public CefCToCpp { + public: + explicit CefDisplayHandlerCToCpp(cef_display_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefDisplayHandlerCToCpp() {} + + // CefDisplayHandler methods + virtual void OnAddressChange(CefRefPtr browser, + CefRefPtr frame, const CefString& url) OVERRIDE; + virtual void OnTitleChange(CefRefPtr browser, + const CefString& title) OVERRIDE; + virtual bool OnTooltip(CefRefPtr browser, + CefString& text) OVERRIDE; + virtual void OnStatusMessage(CefRefPtr browser, + const CefString& value) OVERRIDE; + virtual bool OnConsoleMessage(CefRefPtr browser, + const CefString& message, const CefString& source, int line) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DISPLAY_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/domdocument_ctocpp.cc b/libcef_dll/ctocpp/domdocument_ctocpp.cc new file mode 100644 index 000000000..a8755c9c6 --- /dev/null +++ b/libcef_dll/ctocpp/domdocument_ctocpp.cc @@ -0,0 +1,255 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/domdocument_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefDOMDocument::Type CefDOMDocumentCToCpp::GetType() { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return DOM_DOCUMENT_TYPE_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dom_document_type_t _retval = struct_->get_type(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefDOMDocumentCToCpp::GetDocument() { + if (CEF_MEMBER_MISSING(struct_, get_document)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_document(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMDocumentCToCpp::GetBody() { + if (CEF_MEMBER_MISSING(struct_, get_body)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_body(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMDocumentCToCpp::GetHead() { + if (CEF_MEMBER_MISSING(struct_, get_head)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_head(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefString CefDOMDocumentCToCpp::GetTitle() { + if (CEF_MEMBER_MISSING(struct_, get_title)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_title(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefDOMDocumentCToCpp::GetElementById( + const CefString& id) { + if (CEF_MEMBER_MISSING(struct_, get_element_by_id)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: id; type: string_byref_const + DCHECK(!id.empty()); + if (id.empty()) + return NULL; + + // Execute + cef_domnode_t* _retval = struct_->get_element_by_id(struct_, + id.GetStruct()); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMDocumentCToCpp::GetFocusedNode() { + if (CEF_MEMBER_MISSING(struct_, get_focused_node)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_focused_node(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +bool CefDOMDocumentCToCpp::HasSelection() { + if (CEF_MEMBER_MISSING(struct_, has_selection)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_selection(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefDOMDocumentCToCpp::GetSelectionStartNode() { + if (CEF_MEMBER_MISSING(struct_, get_selection_start_node)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_selection_start_node(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +int CefDOMDocumentCToCpp::GetSelectionStartOffset() { + if (CEF_MEMBER_MISSING(struct_, get_selection_start_offset)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_selection_start_offset(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefDOMDocumentCToCpp::GetSelectionEndNode() { + if (CEF_MEMBER_MISSING(struct_, get_selection_end_node)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_selection_end_node(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +int CefDOMDocumentCToCpp::GetSelectionEndOffset() { + if (CEF_MEMBER_MISSING(struct_, get_selection_end_offset)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_selection_end_offset(struct_); + + // Return type: simple + return _retval; +} + +CefString CefDOMDocumentCToCpp::GetSelectionAsMarkup() { + if (CEF_MEMBER_MISSING(struct_, get_selection_as_markup)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_selection_as_markup(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDOMDocumentCToCpp::GetSelectionAsText() { + if (CEF_MEMBER_MISSING(struct_, get_selection_as_text)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_selection_as_text(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDOMDocumentCToCpp::GetBaseURL() { + if (CEF_MEMBER_MISSING(struct_, get_base_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_base_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDOMDocumentCToCpp::GetCompleteURL(const CefString& partialURL) { + if (CEF_MEMBER_MISSING(struct_, get_complete_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: partialURL; type: string_byref_const + DCHECK(!partialURL.empty()); + if (partialURL.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_complete_url(struct_, + partialURL.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/domdocument_ctocpp.h b/libcef_dll/ctocpp/domdocument_ctocpp.h new file mode 100644 index 000000000..b69afb549 --- /dev/null +++ b/libcef_dll/ctocpp/domdocument_ctocpp.h @@ -0,0 +1,57 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOMDOCUMENT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOMDOCUMENT_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDOMDocumentCToCpp + : public CefCToCpp { + public: + explicit CefDOMDocumentCToCpp(cef_domdocument_t* str) + : CefCToCpp( + str) {} + virtual ~CefDOMDocumentCToCpp() {} + + // CefDOMDocument methods + virtual Type GetType() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetBody() OVERRIDE; + virtual CefRefPtr GetHead() OVERRIDE; + virtual CefString GetTitle() OVERRIDE; + virtual CefRefPtr GetElementById(const CefString& id) OVERRIDE; + virtual CefRefPtr GetFocusedNode() OVERRIDE; + virtual bool HasSelection() OVERRIDE; + virtual CefRefPtr GetSelectionStartNode() OVERRIDE; + virtual int GetSelectionStartOffset() OVERRIDE; + virtual CefRefPtr GetSelectionEndNode() OVERRIDE; + virtual int GetSelectionEndOffset() OVERRIDE; + virtual CefString GetSelectionAsMarkup() OVERRIDE; + virtual CefString GetSelectionAsText() OVERRIDE; + virtual CefString GetBaseURL() OVERRIDE; + virtual CefString GetCompleteURL(const CefString& partialURL) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOMDOCUMENT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/domevent_ctocpp.cc b/libcef_dll/ctocpp/domevent_ctocpp.cc new file mode 100644 index 000000000..2119ec486 --- /dev/null +++ b/libcef_dll/ctocpp/domevent_ctocpp.cc @@ -0,0 +1,131 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/domdocument_ctocpp.h" +#include "libcef_dll/ctocpp/domevent_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefString CefDOMEventCToCpp::GetType() { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_type(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefDOMEvent::Category CefDOMEventCToCpp::GetCategory() { + if (CEF_MEMBER_MISSING(struct_, get_category)) + return DOM_EVENT_CATEGORY_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dom_event_category_t _retval = struct_->get_category(struct_); + + // Return type: simple + return _retval; +} + +CefDOMEvent::Phase CefDOMEventCToCpp::GetPhase() { + if (CEF_MEMBER_MISSING(struct_, get_phase)) + return DOM_EVENT_PHASE_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dom_event_phase_t _retval = struct_->get_phase(struct_); + + // Return type: simple + return _retval; +} + +bool CefDOMEventCToCpp::CanBubble() { + if (CEF_MEMBER_MISSING(struct_, can_bubble)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_bubble(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDOMEventCToCpp::CanCancel() { + if (CEF_MEMBER_MISSING(struct_, can_cancel)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_cancel(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefDOMEventCToCpp::GetDocument() { + if (CEF_MEMBER_MISSING(struct_, get_document)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domdocument_t* _retval = struct_->get_document(struct_); + + // Return type: refptr_same + return CefDOMDocumentCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMEventCToCpp::GetTarget() { + if (CEF_MEMBER_MISSING(struct_, get_target)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_target(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMEventCToCpp::GetCurrentTarget() { + if (CEF_MEMBER_MISSING(struct_, get_current_target)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_current_target(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/domevent_ctocpp.h b/libcef_dll/ctocpp/domevent_ctocpp.h new file mode 100644 index 000000000..6b03c9c29 --- /dev/null +++ b/libcef_dll/ctocpp/domevent_ctocpp.h @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDOMEventCToCpp + : public CefCToCpp { + public: + explicit CefDOMEventCToCpp(cef_domevent_t* str) + : CefCToCpp(str) {} + virtual ~CefDOMEventCToCpp() {} + + // CefDOMEvent methods + virtual CefString GetType() OVERRIDE; + virtual Category GetCategory() OVERRIDE; + virtual Phase GetPhase() OVERRIDE; + virtual bool CanBubble() OVERRIDE; + virtual bool CanCancel() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetTarget() OVERRIDE; + virtual CefRefPtr GetCurrentTarget() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/domevent_listener_ctocpp.cc b/libcef_dll/ctocpp/domevent_listener_ctocpp.cc new file mode 100644 index 000000000..cabb3dd62 --- /dev/null +++ b/libcef_dll/ctocpp/domevent_listener_ctocpp.cc @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domevent_cpptoc.h" +#include "libcef_dll/ctocpp/domevent_listener_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDOMEventListenerCToCpp::HandleEvent(CefRefPtr event) { + if (CEF_MEMBER_MISSING(struct_, handle_event)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: event; type: refptr_diff + DCHECK(event.get()); + if (!event.get()) + return; + + // Execute + struct_->handle_event(struct_, + CefDOMEventCppToC::Wrap(event)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/domevent_listener_ctocpp.h b/libcef_dll/ctocpp/domevent_listener_ctocpp.h new file mode 100644 index 000000000..3721e513f --- /dev/null +++ b/libcef_dll/ctocpp/domevent_listener_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_LISTENER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_LISTENER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDOMEventListenerCToCpp + : public CefCToCpp { + public: + explicit CefDOMEventListenerCToCpp(cef_domevent_listener_t* str) + : CefCToCpp(str) {} + virtual ~CefDOMEventListenerCToCpp() {} + + // CefDOMEventListener methods + virtual void HandleEvent(CefRefPtr event) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOMEVENT_LISTENER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/domnode_ctocpp.cc b/libcef_dll/ctocpp/domnode_ctocpp.cc new file mode 100644 index 000000000..1ef950804 --- /dev/null +++ b/libcef_dll/ctocpp/domnode_ctocpp.cc @@ -0,0 +1,436 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domevent_listener_cpptoc.h" +#include "libcef_dll/ctocpp/domdocument_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefDOMNode::Type CefDOMNodeCToCpp::GetType() { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return DOM_NODE_TYPE_UNSUPPORTED; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_dom_node_type_t _retval = struct_->get_type(struct_); + + // Return type: simple + return _retval; +} + +bool CefDOMNodeCToCpp::IsText() { + if (CEF_MEMBER_MISSING(struct_, is_text)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_text(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDOMNodeCToCpp::IsElement() { + if (CEF_MEMBER_MISSING(struct_, is_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_element(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDOMNodeCToCpp::IsEditable() { + if (CEF_MEMBER_MISSING(struct_, is_editable)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_editable(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDOMNodeCToCpp::IsFormControlElement() { + if (CEF_MEMBER_MISSING(struct_, is_form_control_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_form_control_element(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDOMNodeCToCpp::GetFormControlElementType() { + if (CEF_MEMBER_MISSING(struct_, get_form_control_element_type)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_form_control_element_type( + struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefDOMNodeCToCpp::IsSame(CefRefPtr that) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: that; type: refptr_same + DCHECK(that.get()); + if (!that.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefDOMNodeCToCpp::Unwrap(that)); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDOMNodeCToCpp::GetName() { + if (CEF_MEMBER_MISSING(struct_, get_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDOMNodeCToCpp::GetValue() { + if (CEF_MEMBER_MISSING(struct_, get_value)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_value(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefDOMNodeCToCpp::SetValue(const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, set_value)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: value; type: string_byref_const + DCHECK(!value.empty()); + if (value.empty()) + return false; + + // Execute + int _retval = struct_->set_value(struct_, + value.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDOMNodeCToCpp::GetAsMarkup() { + if (CEF_MEMBER_MISSING(struct_, get_as_markup)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_as_markup(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefDOMNodeCToCpp::GetDocument() { + if (CEF_MEMBER_MISSING(struct_, get_document)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domdocument_t* _retval = struct_->get_document(struct_); + + // Return type: refptr_same + return CefDOMDocumentCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMNodeCToCpp::GetParent() { + if (CEF_MEMBER_MISSING(struct_, get_parent)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_parent(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMNodeCToCpp::GetPreviousSibling() { + if (CEF_MEMBER_MISSING(struct_, get_previous_sibling)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_previous_sibling(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMNodeCToCpp::GetNextSibling() { + if (CEF_MEMBER_MISSING(struct_, get_next_sibling)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_next_sibling(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +bool CefDOMNodeCToCpp::HasChildren() { + if (CEF_MEMBER_MISSING(struct_, has_children)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_children(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefDOMNodeCToCpp::GetFirstChild() { + if (CEF_MEMBER_MISSING(struct_, get_first_child)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_first_child(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +CefRefPtr CefDOMNodeCToCpp::GetLastChild() { + if (CEF_MEMBER_MISSING(struct_, get_last_child)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_domnode_t* _retval = struct_->get_last_child(struct_); + + // Return type: refptr_same + return CefDOMNodeCToCpp::Wrap(_retval); +} + +void CefDOMNodeCToCpp::AddEventListener(const CefString& eventType, + CefRefPtr listener, bool useCapture) { + if (CEF_MEMBER_MISSING(struct_, add_event_listener)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: eventType; type: string_byref_const + DCHECK(!eventType.empty()); + if (eventType.empty()) + return; + // Verify param: listener; type: refptr_diff + DCHECK(listener.get()); + if (!listener.get()) + return; + + // Execute + struct_->add_event_listener(struct_, + eventType.GetStruct(), + CefDOMEventListenerCppToC::Wrap(listener), + useCapture); +} + +CefString CefDOMNodeCToCpp::GetElementTagName() { + if (CEF_MEMBER_MISSING(struct_, get_element_tag_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_element_tag_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefDOMNodeCToCpp::HasElementAttributes() { + if (CEF_MEMBER_MISSING(struct_, has_element_attributes)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_element_attributes(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDOMNodeCToCpp::HasElementAttribute(const CefString& attrName) { + if (CEF_MEMBER_MISSING(struct_, has_element_attribute)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: attrName; type: string_byref_const + DCHECK(!attrName.empty()); + if (attrName.empty()) + return false; + + // Execute + int _retval = struct_->has_element_attribute(struct_, + attrName.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDOMNodeCToCpp::GetElementAttribute(const CefString& attrName) { + if (CEF_MEMBER_MISSING(struct_, get_element_attribute)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: attrName; type: string_byref_const + DCHECK(!attrName.empty()); + if (attrName.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_element_attribute(struct_, + attrName.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefDOMNodeCToCpp::GetElementAttributes(AttributeMap& attrMap) { + if (CEF_MEMBER_MISSING(struct_, get_element_attributes)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: attrMap; type: string_map_single_byref + cef_string_map_t attrMapMap = cef_string_map_alloc(); + DCHECK(attrMapMap); + if (attrMapMap) + transfer_string_map_contents(attrMap, attrMapMap); + + // Execute + struct_->get_element_attributes(struct_, + attrMapMap); + + // Restore param:attrMap; type: string_map_single_byref + if (attrMapMap) { + attrMap.clear(); + transfer_string_map_contents(attrMapMap, attrMap); + cef_string_map_free(attrMapMap); + } +} + +bool CefDOMNodeCToCpp::SetElementAttribute(const CefString& attrName, + const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, set_element_attribute)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: attrName; type: string_byref_const + DCHECK(!attrName.empty()); + if (attrName.empty()) + return false; + // Verify param: value; type: string_byref_const + DCHECK(!value.empty()); + if (value.empty()) + return false; + + // Execute + int _retval = struct_->set_element_attribute(struct_, + attrName.GetStruct(), + value.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDOMNodeCToCpp::GetElementInnerText() { + if (CEF_MEMBER_MISSING(struct_, get_element_inner_text)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_element_inner_text(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/domnode_ctocpp.h b/libcef_dll/ctocpp/domnode_ctocpp.h new file mode 100644 index 000000000..6cb95319b --- /dev/null +++ b/libcef_dll/ctocpp/domnode_ctocpp.h @@ -0,0 +1,67 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOMNODE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOMNODE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDOMNodeCToCpp + : public CefCToCpp { + public: + explicit CefDOMNodeCToCpp(cef_domnode_t* str) + : CefCToCpp(str) {} + virtual ~CefDOMNodeCToCpp() {} + + // CefDOMNode methods + virtual Type GetType() OVERRIDE; + virtual bool IsText() OVERRIDE; + virtual bool IsElement() OVERRIDE; + virtual bool IsEditable() OVERRIDE; + virtual bool IsFormControlElement() OVERRIDE; + virtual CefString GetFormControlElementType() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual CefString GetValue() OVERRIDE; + virtual bool SetValue(const CefString& value) OVERRIDE; + virtual CefString GetAsMarkup() OVERRIDE; + virtual CefRefPtr GetDocument() OVERRIDE; + virtual CefRefPtr GetParent() OVERRIDE; + virtual CefRefPtr GetPreviousSibling() OVERRIDE; + virtual CefRefPtr GetNextSibling() OVERRIDE; + virtual bool HasChildren() OVERRIDE; + virtual CefRefPtr GetFirstChild() OVERRIDE; + virtual CefRefPtr GetLastChild() OVERRIDE; + virtual void AddEventListener(const CefString& eventType, + CefRefPtr listener, bool useCapture) OVERRIDE; + virtual CefString GetElementTagName() OVERRIDE; + virtual bool HasElementAttributes() OVERRIDE; + virtual bool HasElementAttribute(const CefString& attrName) OVERRIDE; + virtual CefString GetElementAttribute(const CefString& attrName) OVERRIDE; + virtual void GetElementAttributes(AttributeMap& attrMap) OVERRIDE; + virtual bool SetElementAttribute(const CefString& attrName, + const CefString& value) OVERRIDE; + virtual CefString GetElementInnerText() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOMNODE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/domvisitor_ctocpp.cc b/libcef_dll/ctocpp/domvisitor_ctocpp.cc new file mode 100644 index 000000000..5e4820f53 --- /dev/null +++ b/libcef_dll/ctocpp/domvisitor_ctocpp.cc @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domdocument_cpptoc.h" +#include "libcef_dll/ctocpp/domvisitor_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDOMVisitorCToCpp::Visit(CefRefPtr document) { + if (CEF_MEMBER_MISSING(struct_, visit)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: document; type: refptr_diff + DCHECK(document.get()); + if (!document.get()) + return; + + // Execute + struct_->visit(struct_, + CefDOMDocumentCppToC::Wrap(document)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/domvisitor_ctocpp.h b/libcef_dll/ctocpp/domvisitor_ctocpp.h new file mode 100644 index 000000000..e2f7fa371 --- /dev/null +++ b/libcef_dll/ctocpp/domvisitor_ctocpp.h @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOMVISITOR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOMVISITOR_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_dom.h" +#include "include/capi/cef_dom_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDOMVisitorCToCpp + : public CefCToCpp { + public: + explicit CefDOMVisitorCToCpp(cef_domvisitor_t* str) + : CefCToCpp(str) {} + virtual ~CefDOMVisitorCToCpp() {} + + // CefDOMVisitor methods + virtual void Visit(CefRefPtr document) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOMVISITOR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/download_handler_ctocpp.cc b/libcef_dll/ctocpp/download_handler_ctocpp.cc new file mode 100644 index 000000000..79204fc42 --- /dev/null +++ b/libcef_dll/ctocpp/download_handler_ctocpp.cc @@ -0,0 +1,88 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/before_download_callback_cpptoc.h" +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/download_item_cpptoc.h" +#include "libcef_dll/cpptoc/download_item_callback_cpptoc.h" +#include "libcef_dll/ctocpp/download_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDownloadHandlerCToCpp::OnBeforeDownload(CefRefPtr browser, + CefRefPtr download_item, const CefString& suggested_name, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_before_download)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: download_item; type: refptr_diff + DCHECK(download_item.get()); + if (!download_item.get()) + return; + // Verify param: suggested_name; type: string_byref_const + DCHECK(!suggested_name.empty()); + if (suggested_name.empty()) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return; + + // Execute + struct_->on_before_download(struct_, + CefBrowserCppToC::Wrap(browser), + CefDownloadItemCppToC::Wrap(download_item), + suggested_name.GetStruct(), + CefBeforeDownloadCallbackCppToC::Wrap(callback)); +} + +void CefDownloadHandlerCToCpp::OnDownloadUpdated(CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_download_updated)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: download_item; type: refptr_diff + DCHECK(download_item.get()); + if (!download_item.get()) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return; + + // Execute + struct_->on_download_updated(struct_, + CefBrowserCppToC::Wrap(browser), + CefDownloadItemCppToC::Wrap(download_item), + CefDownloadItemCallbackCppToC::Wrap(callback)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/download_handler_ctocpp.h b/libcef_dll/ctocpp/download_handler_ctocpp.h new file mode 100644 index 000000000..302251d06 --- /dev/null +++ b/libcef_dll/ctocpp/download_handler_ctocpp.h @@ -0,0 +1,48 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDownloadHandlerCToCpp + : public CefCToCpp { + public: + explicit CefDownloadHandlerCToCpp(cef_download_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefDownloadHandlerCToCpp() {} + + // CefDownloadHandler methods + virtual void OnBeforeDownload(CefRefPtr browser, + CefRefPtr download_item, + const CefString& suggested_name, + CefRefPtr callback) OVERRIDE; + virtual void OnDownloadUpdated(CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/download_item_callback_ctocpp.cc b/libcef_dll/ctocpp/download_item_callback_ctocpp.cc new file mode 100644 index 000000000..537b5740d --- /dev/null +++ b/libcef_dll/ctocpp/download_item_callback_ctocpp.cc @@ -0,0 +1,33 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/download_item_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDownloadItemCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/download_item_callback_ctocpp.h b/libcef_dll/ctocpp/download_item_callback_ctocpp.h new file mode 100644 index 000000000..706048dba --- /dev/null +++ b/libcef_dll/ctocpp/download_item_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_download_handler.h" +#include "include/capi/cef_download_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDownloadItemCallbackCToCpp + : public CefCToCpp { + public: + explicit CefDownloadItemCallbackCToCpp(cef_download_item_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefDownloadItemCallbackCToCpp() {} + + // CefDownloadItemCallback methods + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/download_item_ctocpp.cc b/libcef_dll/ctocpp/download_item_ctocpp.cc new file mode 100644 index 000000000..406a0ab43 --- /dev/null +++ b/libcef_dll/ctocpp/download_item_ctocpp.cc @@ -0,0 +1,241 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/download_item_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefDownloadItemCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDownloadItemCToCpp::IsInProgress() { + if (CEF_MEMBER_MISSING(struct_, is_in_progress)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_in_progress(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDownloadItemCToCpp::IsComplete() { + if (CEF_MEMBER_MISSING(struct_, is_complete)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_complete(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDownloadItemCToCpp::IsCanceled() { + if (CEF_MEMBER_MISSING(struct_, is_canceled)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_canceled(struct_); + + // Return type: bool + return _retval?true:false; +} + +int64 CefDownloadItemCToCpp::GetCurrentSpeed() { + if (CEF_MEMBER_MISSING(struct_, get_current_speed)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->get_current_speed(struct_); + + // Return type: simple + return _retval; +} + +int CefDownloadItemCToCpp::GetPercentComplete() { + if (CEF_MEMBER_MISSING(struct_, get_percent_complete)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_percent_complete(struct_); + + // Return type: simple + return _retval; +} + +int64 CefDownloadItemCToCpp::GetTotalBytes() { + if (CEF_MEMBER_MISSING(struct_, get_total_bytes)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->get_total_bytes(struct_); + + // Return type: simple + return _retval; +} + +int64 CefDownloadItemCToCpp::GetReceivedBytes() { + if (CEF_MEMBER_MISSING(struct_, get_received_bytes)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->get_received_bytes(struct_); + + // Return type: simple + return _retval; +} + +CefTime CefDownloadItemCToCpp::GetStartTime() { + if (CEF_MEMBER_MISSING(struct_, get_start_time)) + return CefTime(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_time_t _retval = struct_->get_start_time(struct_); + + // Return type: simple + return _retval; +} + +CefTime CefDownloadItemCToCpp::GetEndTime() { + if (CEF_MEMBER_MISSING(struct_, get_end_time)) + return CefTime(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_time_t _retval = struct_->get_end_time(struct_); + + // Return type: simple + return _retval; +} + +CefString CefDownloadItemCToCpp::GetFullPath() { + if (CEF_MEMBER_MISSING(struct_, get_full_path)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_full_path(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +uint32 CefDownloadItemCToCpp::GetId() { + if (CEF_MEMBER_MISSING(struct_, get_id)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + uint32 _retval = struct_->get_id(struct_); + + // Return type: simple + return _retval; +} + +CefString CefDownloadItemCToCpp::GetURL() { + if (CEF_MEMBER_MISSING(struct_, get_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDownloadItemCToCpp::GetSuggestedFileName() { + if (CEF_MEMBER_MISSING(struct_, get_suggested_file_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_suggested_file_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDownloadItemCToCpp::GetContentDisposition() { + if (CEF_MEMBER_MISSING(struct_, get_content_disposition)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_content_disposition(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDownloadItemCToCpp::GetMimeType() { + if (CEF_MEMBER_MISSING(struct_, get_mime_type)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_mime_type(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/download_item_ctocpp.h b/libcef_dll/ctocpp/download_item_ctocpp.h new file mode 100644 index 000000000..77125f197 --- /dev/null +++ b/libcef_dll/ctocpp/download_item_ctocpp.h @@ -0,0 +1,57 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_download_item.h" +#include "include/capi/cef_download_item_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDownloadItemCToCpp + : public CefCToCpp { + public: + explicit CefDownloadItemCToCpp(cef_download_item_t* str) + : CefCToCpp( + str) {} + virtual ~CefDownloadItemCToCpp() {} + + // CefDownloadItem methods + virtual bool IsValid() OVERRIDE; + virtual bool IsInProgress() OVERRIDE; + virtual bool IsComplete() OVERRIDE; + virtual bool IsCanceled() OVERRIDE; + virtual int64 GetCurrentSpeed() OVERRIDE; + virtual int GetPercentComplete() OVERRIDE; + virtual int64 GetTotalBytes() OVERRIDE; + virtual int64 GetReceivedBytes() OVERRIDE; + virtual CefTime GetStartTime() OVERRIDE; + virtual CefTime GetEndTime() OVERRIDE; + virtual CefString GetFullPath() OVERRIDE; + virtual uint32 GetId() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual CefString GetSuggestedFileName() OVERRIDE; + virtual CefString GetContentDisposition() OVERRIDE; + virtual CefString GetMimeType() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DOWNLOAD_ITEM_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/drag_data_ctocpp.cc b/libcef_dll/ctocpp/drag_data_ctocpp.cc new file mode 100644 index 000000000..a5f56d06a --- /dev/null +++ b/libcef_dll/ctocpp/drag_data_ctocpp.cc @@ -0,0 +1,358 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/drag_data_ctocpp.h" +#include "libcef_dll/ctocpp/stream_writer_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefDragData::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_drag_data_t* _retval = cef_drag_data_create(); + + // Return type: refptr_same + return CefDragDataCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefDragDataCToCpp::Clone() { + if (CEF_MEMBER_MISSING(struct_, clone)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_drag_data_t* _retval = struct_->clone(struct_); + + // Return type: refptr_same + return CefDragDataCToCpp::Wrap(_retval); +} + +bool CefDragDataCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDragDataCToCpp::IsLink() { + if (CEF_MEMBER_MISSING(struct_, is_link)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_link(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDragDataCToCpp::IsFragment() { + if (CEF_MEMBER_MISSING(struct_, is_fragment)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_fragment(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefDragDataCToCpp::IsFile() { + if (CEF_MEMBER_MISSING(struct_, is_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_file(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefDragDataCToCpp::GetLinkURL() { + if (CEF_MEMBER_MISSING(struct_, get_link_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_link_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetLinkTitle() { + if (CEF_MEMBER_MISSING(struct_, get_link_title)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_link_title(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetLinkMetadata() { + if (CEF_MEMBER_MISSING(struct_, get_link_metadata)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_link_metadata(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetFragmentText() { + if (CEF_MEMBER_MISSING(struct_, get_fragment_text)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_fragment_text(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetFragmentHtml() { + if (CEF_MEMBER_MISSING(struct_, get_fragment_html)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_fragment_html(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetFragmentBaseURL() { + if (CEF_MEMBER_MISSING(struct_, get_fragment_base_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_fragment_base_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefDragDataCToCpp::GetFileName() { + if (CEF_MEMBER_MISSING(struct_, get_file_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_file_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +size_t CefDragDataCToCpp::GetFileContents(CefRefPtr writer) { + if (CEF_MEMBER_MISSING(struct_, get_file_contents)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: writer + + // Execute + size_t _retval = struct_->get_file_contents(struct_, + CefStreamWriterCToCpp::Unwrap(writer)); + + // Return type: simple + return _retval; +} + +bool CefDragDataCToCpp::GetFileNames(std::vector& names) { + if (CEF_MEMBER_MISSING(struct_, get_file_names)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: names; type: string_vec_byref + cef_string_list_t namesList = cef_string_list_alloc(); + DCHECK(namesList); + if (namesList) + transfer_string_list_contents(names, namesList); + + // Execute + int _retval = struct_->get_file_names(struct_, + namesList); + + // Restore param:names; type: string_vec_byref + if (namesList) { + names.clear(); + transfer_string_list_contents(namesList, names); + cef_string_list_free(namesList); + } + + // Return type: bool + return _retval?true:false; +} + +void CefDragDataCToCpp::SetLinkURL(const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, set_link_url)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: url + + // Execute + struct_->set_link_url(struct_, + url.GetStruct()); +} + +void CefDragDataCToCpp::SetLinkTitle(const CefString& title) { + if (CEF_MEMBER_MISSING(struct_, set_link_title)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: title + + // Execute + struct_->set_link_title(struct_, + title.GetStruct()); +} + +void CefDragDataCToCpp::SetLinkMetadata(const CefString& data) { + if (CEF_MEMBER_MISSING(struct_, set_link_metadata)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: data + + // Execute + struct_->set_link_metadata(struct_, + data.GetStruct()); +} + +void CefDragDataCToCpp::SetFragmentText(const CefString& text) { + if (CEF_MEMBER_MISSING(struct_, set_fragment_text)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: text + + // Execute + struct_->set_fragment_text(struct_, + text.GetStruct()); +} + +void CefDragDataCToCpp::SetFragmentHtml(const CefString& html) { + if (CEF_MEMBER_MISSING(struct_, set_fragment_html)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: html + + // Execute + struct_->set_fragment_html(struct_, + html.GetStruct()); +} + +void CefDragDataCToCpp::SetFragmentBaseURL(const CefString& base_url) { + if (CEF_MEMBER_MISSING(struct_, set_fragment_base_url)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: base_url + + // Execute + struct_->set_fragment_base_url(struct_, + base_url.GetStruct()); +} + +void CefDragDataCToCpp::ResetFileContents() { + if (CEF_MEMBER_MISSING(struct_, reset_file_contents)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->reset_file_contents(struct_); +} + +void CefDragDataCToCpp::AddFile(const CefString& path, + const CefString& display_name) { + if (CEF_MEMBER_MISSING(struct_, add_file)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + // Unverified params: display_name + + // Execute + struct_->add_file(struct_, + path.GetStruct(), + display_name.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/drag_data_ctocpp.h b/libcef_dll/ctocpp/drag_data_ctocpp.h new file mode 100644 index 000000000..01be310ca --- /dev/null +++ b/libcef_dll/ctocpp/drag_data_ctocpp.h @@ -0,0 +1,63 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DRAG_DATA_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DRAG_DATA_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_drag_data.h" +#include "include/capi/cef_drag_data_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefDragDataCToCpp + : public CefCToCpp { + public: + explicit CefDragDataCToCpp(cef_drag_data_t* str) + : CefCToCpp(str) {} + virtual ~CefDragDataCToCpp() {} + + // CefDragData methods + virtual CefRefPtr Clone() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual bool IsLink() OVERRIDE; + virtual bool IsFragment() OVERRIDE; + virtual bool IsFile() OVERRIDE; + virtual CefString GetLinkURL() OVERRIDE; + virtual CefString GetLinkTitle() OVERRIDE; + virtual CefString GetLinkMetadata() OVERRIDE; + virtual CefString GetFragmentText() OVERRIDE; + virtual CefString GetFragmentHtml() OVERRIDE; + virtual CefString GetFragmentBaseURL() OVERRIDE; + virtual CefString GetFileName() OVERRIDE; + virtual size_t GetFileContents(CefRefPtr writer) OVERRIDE; + virtual bool GetFileNames(std::vector& names) OVERRIDE; + virtual void SetLinkURL(const CefString& url) OVERRIDE; + virtual void SetLinkTitle(const CefString& title) OVERRIDE; + virtual void SetLinkMetadata(const CefString& data) OVERRIDE; + virtual void SetFragmentText(const CefString& text) OVERRIDE; + virtual void SetFragmentHtml(const CefString& html) OVERRIDE; + virtual void SetFragmentBaseURL(const CefString& base_url) OVERRIDE; + virtual void ResetFileContents() OVERRIDE; + virtual void AddFile(const CefString& path, + const CefString& display_name) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DRAG_DATA_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/drag_handler_ctocpp.cc b/libcef_dll/ctocpp/drag_handler_ctocpp.cc new file mode 100644 index 000000000..4a1a9c1c3 --- /dev/null +++ b/libcef_dll/ctocpp/drag_handler_ctocpp.cc @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/ctocpp/drag_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefDragHandlerCToCpp::OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, DragOperationsMask mask) { + if (CEF_MEMBER_MISSING(struct_, on_drag_enter)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: dragData; type: refptr_diff + DCHECK(dragData.get()); + if (!dragData.get()) + return false; + + // Execute + int _retval = struct_->on_drag_enter(struct_, + CefBrowserCppToC::Wrap(browser), + CefDragDataCppToC::Wrap(dragData), + mask); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/drag_handler_ctocpp.h b/libcef_dll/ctocpp/drag_handler_ctocpp.h new file mode 100644 index 000000000..b942b6d8e --- /dev/null +++ b/libcef_dll/ctocpp/drag_handler_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DRAG_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DRAG_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_drag_handler.h" +#include "include/capi/cef_drag_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDragHandlerCToCpp + : public CefCToCpp { + public: + explicit CefDragHandlerCToCpp(cef_drag_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefDragHandlerCToCpp() {} + + // CefDragHandler methods + virtual bool OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, DragOperationsMask mask) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DRAG_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc new file mode 100644 index 000000000..866e1c790 --- /dev/null +++ b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.cc @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/end_tracing_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefEndTracingCallbackCToCpp::OnEndTracingComplete( + const CefString& tracing_file) { + if (CEF_MEMBER_MISSING(struct_, on_end_tracing_complete)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: tracing_file; type: string_byref_const + DCHECK(!tracing_file.empty()); + if (tracing_file.empty()) + return; + + // Execute + struct_->on_end_tracing_complete(struct_, + tracing_file.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h new file mode 100644 index 000000000..4d5ad69fc --- /dev/null +++ b/libcef_dll/ctocpp/end_tracing_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_END_TRACING_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_END_TRACING_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_trace.h" +#include "include/capi/cef_trace_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefEndTracingCallbackCToCpp + : public CefCToCpp { + public: + explicit CefEndTracingCallbackCToCpp(cef_end_tracing_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefEndTracingCallbackCToCpp() {} + + // CefEndTracingCallback methods + virtual void OnEndTracingComplete(const CefString& tracing_file) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_END_TRACING_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc new file mode 100644 index 000000000..2b44f8110 --- /dev/null +++ b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefFileDialogCallbackCToCpp::Continue( + const std::vector& file_paths) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: file_paths; type: string_vec_byref_const + cef_string_list_t file_pathsList = cef_string_list_alloc(); + DCHECK(file_pathsList); + if (file_pathsList) + transfer_string_list_contents(file_paths, file_pathsList); + + // Execute + struct_->cont(struct_, + file_pathsList); + + // Restore param:file_paths; type: string_vec_byref_const + if (file_pathsList) + cef_string_list_free(file_pathsList); +} + +void CefFileDialogCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h new file mode 100644 index 000000000..b7c8695b6 --- /dev/null +++ b/libcef_dll/ctocpp/file_dialog_callback_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_dialog_handler.h" +#include "include/capi/cef_dialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefFileDialogCallbackCToCpp + : public CefCToCpp { + public: + explicit CefFileDialogCallbackCToCpp(cef_file_dialog_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefFileDialogCallbackCToCpp() {} + + // CefFileDialogCallback methods + virtual void Continue(const std::vector& file_paths) OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_FILE_DIALOG_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/focus_handler_ctocpp.cc b/libcef_dll/ctocpp/focus_handler_ctocpp.cc new file mode 100644 index 000000000..b3b4759cb --- /dev/null +++ b/libcef_dll/ctocpp/focus_handler_ctocpp.cc @@ -0,0 +1,79 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/ctocpp/focus_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefFocusHandlerCToCpp::OnTakeFocus(CefRefPtr browser, + bool next) { + if (CEF_MEMBER_MISSING(struct_, on_take_focus)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_take_focus(struct_, + CefBrowserCppToC::Wrap(browser), + next); +} + +bool CefFocusHandlerCToCpp::OnSetFocus(CefRefPtr browser, + FocusSource source) { + if (CEF_MEMBER_MISSING(struct_, on_set_focus)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->on_set_focus(struct_, + CefBrowserCppToC::Wrap(browser), + source); + + // Return type: bool + return _retval?true:false; +} + +void CefFocusHandlerCToCpp::OnGotFocus(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_got_focus)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_got_focus(struct_, + CefBrowserCppToC::Wrap(browser)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/focus_handler_ctocpp.h b/libcef_dll/ctocpp/focus_handler_ctocpp.h new file mode 100644 index 000000000..701a40e99 --- /dev/null +++ b/libcef_dll/ctocpp/focus_handler_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_FOCUS_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_FOCUS_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_focus_handler.h" +#include "include/capi/cef_focus_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefFocusHandlerCToCpp + : public CefCToCpp { + public: + explicit CefFocusHandlerCToCpp(cef_focus_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefFocusHandlerCToCpp() {} + + // CefFocusHandler methods + virtual void OnTakeFocus(CefRefPtr browser, bool next) OVERRIDE; + virtual bool OnSetFocus(CefRefPtr browser, + FocusSource source) OVERRIDE; + virtual void OnGotFocus(CefRefPtr browser) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_FOCUS_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/frame_ctocpp.cc b/libcef_dll/ctocpp/frame_ctocpp.cc new file mode 100644 index 000000000..5996c119a --- /dev/null +++ b/libcef_dll/ctocpp/frame_ctocpp.cc @@ -0,0 +1,351 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/domvisitor_cpptoc.h" +#include "libcef_dll/cpptoc/string_visitor_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/v8context_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefFrameCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefFrameCToCpp::Undo() { + if (CEF_MEMBER_MISSING(struct_, undo)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->undo(struct_); +} + +void CefFrameCToCpp::Redo() { + if (CEF_MEMBER_MISSING(struct_, redo)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->redo(struct_); +} + +void CefFrameCToCpp::Cut() { + if (CEF_MEMBER_MISSING(struct_, cut)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cut(struct_); +} + +void CefFrameCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->copy(struct_); +} + +void CefFrameCToCpp::Paste() { + if (CEF_MEMBER_MISSING(struct_, paste)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->paste(struct_); +} + +void CefFrameCToCpp::Delete() { + if (CEF_MEMBER_MISSING(struct_, del)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->del(struct_); +} + +void CefFrameCToCpp::SelectAll() { + if (CEF_MEMBER_MISSING(struct_, select_all)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->select_all(struct_); +} + +void CefFrameCToCpp::ViewSource() { + if (CEF_MEMBER_MISSING(struct_, view_source)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->view_source(struct_); +} + +void CefFrameCToCpp::GetSource(CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, get_source)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return; + + // Execute + struct_->get_source(struct_, + CefStringVisitorCppToC::Wrap(visitor)); +} + +void CefFrameCToCpp::GetText(CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, get_text)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return; + + // Execute + struct_->get_text(struct_, + CefStringVisitorCppToC::Wrap(visitor)); +} + +void CefFrameCToCpp::LoadRequest(CefRefPtr request) { + if (CEF_MEMBER_MISSING(struct_, load_request)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_same + DCHECK(request.get()); + if (!request.get()) + return; + + // Execute + struct_->load_request(struct_, + CefRequestCToCpp::Unwrap(request)); +} + +void CefFrameCToCpp::LoadURL(const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, load_url)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->load_url(struct_, + url.GetStruct()); +} + +void CefFrameCToCpp::LoadString(const CefString& string_val, + const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, load_string)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: string_val; type: string_byref_const + DCHECK(!string_val.empty()); + if (string_val.empty()) + return; + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->load_string(struct_, + string_val.GetStruct(), + url.GetStruct()); +} + +void CefFrameCToCpp::ExecuteJavaScript(const CefString& code, + const CefString& script_url, int start_line) { + if (CEF_MEMBER_MISSING(struct_, execute_java_script)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: code; type: string_byref_const + DCHECK(!code.empty()); + if (code.empty()) + return; + // Unverified params: script_url + + // Execute + struct_->execute_java_script(struct_, + code.GetStruct(), + script_url.GetStruct(), + start_line); +} + +bool CefFrameCToCpp::IsMain() { + if (CEF_MEMBER_MISSING(struct_, is_main)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_main(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefFrameCToCpp::IsFocused() { + if (CEF_MEMBER_MISSING(struct_, is_focused)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_focused(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefFrameCToCpp::GetName() { + if (CEF_MEMBER_MISSING(struct_, get_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +int64 CefFrameCToCpp::GetIdentifier() { + if (CEF_MEMBER_MISSING(struct_, get_identifier)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->get_identifier(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefFrameCToCpp::GetParent() { + if (CEF_MEMBER_MISSING(struct_, get_parent)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_frame_t* _retval = struct_->get_parent(struct_); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +CefString CefFrameCToCpp::GetURL() { + if (CEF_MEMBER_MISSING(struct_, get_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefFrameCToCpp::GetBrowser() { + if (CEF_MEMBER_MISSING(struct_, get_browser)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_browser_t* _retval = struct_->get_browser(struct_); + + // Return type: refptr_same + return CefBrowserCToCpp::Wrap(_retval); +} + +CefRefPtr CefFrameCToCpp::GetV8Context() { + if (CEF_MEMBER_MISSING(struct_, get_v8context)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8context_t* _retval = struct_->get_v8context(struct_); + + // Return type: refptr_same + return CefV8ContextCToCpp::Wrap(_retval); +} + +void CefFrameCToCpp::VisitDOM(CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, visit_dom)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return; + + // Execute + struct_->visit_dom(struct_, + CefDOMVisitorCppToC::Wrap(visitor)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/frame_ctocpp.h b/libcef_dll/ctocpp/frame_ctocpp.h new file mode 100644 index 000000000..5285ad347 --- /dev/null +++ b/libcef_dll/ctocpp/frame_ctocpp.h @@ -0,0 +1,69 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_frame.h" +#include "include/capi/cef_frame_capi.h" +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefFrameCToCpp + : public CefCToCpp { + public: + explicit CefFrameCToCpp(cef_frame_t* str) + : CefCToCpp(str) {} + virtual ~CefFrameCToCpp() {} + + // CefFrame methods + virtual bool IsValid() OVERRIDE; + virtual void Undo() OVERRIDE; + virtual void Redo() OVERRIDE; + virtual void Cut() OVERRIDE; + virtual void Copy() OVERRIDE; + virtual void Paste() OVERRIDE; + virtual void Delete() OVERRIDE; + virtual void SelectAll() OVERRIDE; + virtual void ViewSource() OVERRIDE; + virtual void GetSource(CefRefPtr visitor) OVERRIDE; + virtual void GetText(CefRefPtr visitor) OVERRIDE; + virtual void LoadRequest(CefRefPtr request) OVERRIDE; + virtual void LoadURL(const CefString& url) OVERRIDE; + virtual void LoadString(const CefString& string_val, + const CefString& url) OVERRIDE; + virtual void ExecuteJavaScript(const CefString& code, + const CefString& script_url, int start_line) OVERRIDE; + virtual bool IsMain() OVERRIDE; + virtual bool IsFocused() OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual int64 GetIdentifier() OVERRIDE; + virtual CefRefPtr GetParent() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual CefRefPtr GetV8Context() OVERRIDE; + virtual void VisitDOM(CefRefPtr visitor) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc b/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc new file mode 100644 index 000000000..94218aecf --- /dev/null +++ b/libcef_dll/ctocpp/geolocation_callback_ctocpp.cc @@ -0,0 +1,34 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/geolocation_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefGeolocationCallbackCToCpp::Continue(bool allow) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cont(struct_, + allow); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/geolocation_callback_ctocpp.h b/libcef_dll/ctocpp/geolocation_callback_ctocpp.h new file mode 100644 index 000000000..42b25d089 --- /dev/null +++ b/libcef_dll/ctocpp/geolocation_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_geolocation_handler.h" +#include "include/capi/cef_geolocation_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefGeolocationCallbackCToCpp + : public CefCToCpp { + public: + explicit CefGeolocationCallbackCToCpp(cef_geolocation_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefGeolocationCallbackCToCpp() {} + + // CefGeolocationCallback methods + virtual void Continue(bool allow) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc b/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc new file mode 100644 index 000000000..396b44463 --- /dev/null +++ b/libcef_dll/ctocpp/geolocation_handler_ctocpp.cc @@ -0,0 +1,81 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/geolocation_callback_cpptoc.h" +#include "libcef_dll/ctocpp/geolocation_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefGeolocationHandlerCToCpp::OnRequestGeolocationPermission( + CefRefPtr browser, const CefString& requesting_url, + int request_id, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_request_geolocation_permission)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: requesting_url; type: string_byref_const + DCHECK(!requesting_url.empty()); + if (requesting_url.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->on_request_geolocation_permission(struct_, + CefBrowserCppToC::Wrap(browser), + requesting_url.GetStruct(), + request_id, + CefGeolocationCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefGeolocationHandlerCToCpp::OnCancelGeolocationPermission( + CefRefPtr browser, const CefString& requesting_url, + int request_id) { + if (CEF_MEMBER_MISSING(struct_, on_cancel_geolocation_permission)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: requesting_url; type: string_byref_const + DCHECK(!requesting_url.empty()); + if (requesting_url.empty()) + return; + + // Execute + struct_->on_cancel_geolocation_permission(struct_, + CefBrowserCppToC::Wrap(browser), + requesting_url.GetStruct(), + request_id); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/geolocation_handler_ctocpp.h b/libcef_dll/ctocpp/geolocation_handler_ctocpp.h new file mode 100644 index 000000000..e4d88ee70 --- /dev/null +++ b/libcef_dll/ctocpp/geolocation_handler_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_geolocation_handler.h" +#include "include/capi/cef_geolocation_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefGeolocationHandlerCToCpp + : public CefCToCpp { + public: + explicit CefGeolocationHandlerCToCpp(cef_geolocation_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefGeolocationHandlerCToCpp() {} + + // CefGeolocationHandler methods + virtual bool OnRequestGeolocationPermission(CefRefPtr browser, + const CefString& requesting_url, int request_id, + CefRefPtr callback) OVERRIDE; + virtual void OnCancelGeolocationPermission(CefRefPtr browser, + const CefString& requesting_url, int request_id) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_GEOLOCATION_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc new file mode 100644 index 000000000..4b38beb86 --- /dev/null +++ b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.cc @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefGetGeolocationCallbackCToCpp::OnLocationUpdate( + const CefGeoposition& position) { + if (CEF_MEMBER_MISSING(struct_, on_location_update)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_location_update(struct_, + &position); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = + 0; +#endif + diff --git a/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h new file mode 100644 index 000000000..d9b1276cc --- /dev/null +++ b/libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_GET_GEOLOCATION_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_GET_GEOLOCATION_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_geolocation.h" +#include "include/capi/cef_geolocation_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefGetGeolocationCallbackCToCpp + : public CefCToCpp { + public: + explicit CefGetGeolocationCallbackCToCpp(cef_get_geolocation_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefGetGeolocationCallbackCToCpp() {} + + // CefGetGeolocationCallback methods + virtual void OnLocationUpdate(const CefGeoposition& position) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_GET_GEOLOCATION_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc new file mode 100644 index 000000000..c0a6357cf --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc @@ -0,0 +1,38 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefJSDialogCallbackCToCpp::Continue(bool success, + const CefString& user_input) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: user_input + + // Execute + struct_->cont(struct_, + success, + user_input.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h new file mode 100644 index 000000000..fda751ad5 --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefJSDialogCallbackCToCpp + : public CefCToCpp { + public: + explicit CefJSDialogCallbackCToCpp(cef_jsdialog_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefJSDialogCallbackCToCpp() {} + + // CefJSDialogCallback methods + virtual void Continue(bool success, const CefString& user_input) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc new file mode 100644 index 000000000..f8f0d5415 --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc @@ -0,0 +1,129 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefJSDialogHandlerCToCpp::OnJSDialog(CefRefPtr browser, + const CefString& origin_url, const CefString& accept_lang, + JSDialogType dialog_type, const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, bool& suppress_message) { + if (CEF_MEMBER_MISSING(struct_, on_jsdialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: origin_url, accept_lang, message_text, + // default_prompt_text + + // Translate param: suppress_message; type: bool_byref + int suppress_messageInt = suppress_message; + + // Execute + int _retval = struct_->on_jsdialog(struct_, + CefBrowserCppToC::Wrap(browser), + origin_url.GetStruct(), + accept_lang.GetStruct(), + dialog_type, + message_text.GetStruct(), + default_prompt_text.GetStruct(), + CefJSDialogCallbackCppToC::Wrap(callback), + &suppress_messageInt); + + // Restore param:suppress_message; type: bool_byref + suppress_message = suppress_messageInt?true:false; + + // Return type: bool + return _retval?true:false; +} + +bool CefJSDialogHandlerCToCpp::OnBeforeUnloadDialog( + CefRefPtr browser, const CefString& message_text, + bool is_reload, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_before_unload_dialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: message_text + + // Execute + int _retval = struct_->on_before_unload_dialog(struct_, + CefBrowserCppToC::Wrap(browser), + message_text.GetStruct(), + is_reload, + CefJSDialogCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefJSDialogHandlerCToCpp::OnResetDialogState( + CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_reset_dialog_state)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_reset_dialog_state(struct_, + CefBrowserCppToC::Wrap(browser)); +} + +void CefJSDialogHandlerCToCpp::OnDialogClosed(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_dialog_closed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_dialog_closed(struct_, + CefBrowserCppToC::Wrap(browser)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h new file mode 100644 index 000000000..0acbb6a6b --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h @@ -0,0 +1,52 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefJSDialogHandlerCToCpp + : public CefCToCpp { + public: + explicit CefJSDialogHandlerCToCpp(cef_jsdialog_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefJSDialogHandlerCToCpp() {} + + // CefJSDialogHandler methods + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, const CefString& accept_lang, + JSDialogType dialog_type, const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) OVERRIDE; + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, bool is_reload, + CefRefPtr callback) OVERRIDE; + virtual void OnResetDialogState(CefRefPtr browser) OVERRIDE; + virtual void OnDialogClosed(CefRefPtr browser) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc b/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc new file mode 100644 index 000000000..ba6aabb4d --- /dev/null +++ b/libcef_dll/ctocpp/keyboard_handler_ctocpp.cc @@ -0,0 +1,81 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefKeyboardHandlerCToCpp::OnPreKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, CefEventHandle os_event, + bool* is_keyboard_shortcut) { + if (CEF_MEMBER_MISSING(struct_, on_pre_key_event)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: is_keyboard_shortcut; type: bool_byaddr + DCHECK(is_keyboard_shortcut); + if (!is_keyboard_shortcut) + return false; + + // Translate param: is_keyboard_shortcut; type: bool_byaddr + int is_keyboard_shortcutInt = is_keyboard_shortcut?*is_keyboard_shortcut:0; + + // Execute + int _retval = struct_->on_pre_key_event(struct_, + CefBrowserCppToC::Wrap(browser), + &event, + os_event, + &is_keyboard_shortcutInt); + + // Restore param:is_keyboard_shortcut; type: bool_byaddr + if (is_keyboard_shortcut) + *is_keyboard_shortcut = is_keyboard_shortcutInt?true:false; + + // Return type: bool + return _retval?true:false; +} + +bool CefKeyboardHandlerCToCpp::OnKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, CefEventHandle os_event) { + if (CEF_MEMBER_MISSING(struct_, on_key_event)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->on_key_event(struct_, + CefBrowserCppToC::Wrap(browser), + &event, + os_event); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/keyboard_handler_ctocpp.h b/libcef_dll/ctocpp/keyboard_handler_ctocpp.h new file mode 100644 index 000000000..3d661cbd5 --- /dev/null +++ b/libcef_dll/ctocpp/keyboard_handler_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_KEYBOARD_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_KEYBOARD_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_keyboard_handler.h" +#include "include/capi/cef_keyboard_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefKeyboardHandlerCToCpp + : public CefCToCpp { + public: + explicit CefKeyboardHandlerCToCpp(cef_keyboard_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefKeyboardHandlerCToCpp() {} + + // CefKeyboardHandler methods + virtual bool OnPreKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, CefEventHandle os_event, + bool* is_keyboard_shortcut) OVERRIDE; + virtual bool OnKeyEvent(CefRefPtr browser, + const CefKeyEvent& event, CefEventHandle os_event) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_KEYBOARD_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/life_span_handler_ctocpp.cc b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc new file mode 100644 index 000000000..4b876ee98 --- /dev/null +++ b/libcef_dll/ctocpp/life_span_handler_ctocpp.cc @@ -0,0 +1,156 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/ctocpp/client_ctocpp.h" +#include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefLifeSpanHandlerCToCpp::OnBeforePopup(CefRefPtr browser, + CefRefPtr frame, const CefString& target_url, + const CefString& target_frame_name, const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, CefRefPtr& client, + CefBrowserSettings& settings, bool* no_javascript_access) { + if (CEF_MEMBER_MISSING(struct_, on_before_popup)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: no_javascript_access; type: bool_byaddr + DCHECK(no_javascript_access); + if (!no_javascript_access) + return false; + // Unverified params: target_url, target_frame_name + + // Translate param: client; type: refptr_same_byref + cef_client_t* clientStruct = NULL; + if (client.get()) + clientStruct = CefClientCToCpp::Unwrap(client); + cef_client_t* clientOrig = clientStruct; + // Translate param: no_javascript_access; type: bool_byaddr + int no_javascript_accessInt = no_javascript_access?*no_javascript_access:0; + + // Execute + int _retval = struct_->on_before_popup(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + target_url.GetStruct(), + target_frame_name.GetStruct(), + &popupFeatures, + &windowInfo, + &clientStruct, + &settings, + &no_javascript_accessInt); + + // Restore param:client; type: refptr_same_byref + if (clientStruct) { + if (clientStruct != clientOrig) { + client = CefClientCToCpp::Wrap(clientStruct); + } + } else { + client = NULL; + } + // Restore param:no_javascript_access; type: bool_byaddr + if (no_javascript_access) + *no_javascript_access = no_javascript_accessInt?true:false; + + // Return type: bool + return _retval?true:false; +} + +void CefLifeSpanHandlerCToCpp::OnAfterCreated(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_after_created)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_after_created(struct_, + CefBrowserCppToC::Wrap(browser)); +} + +bool CefLifeSpanHandlerCToCpp::RunModal(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, run_modal)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->run_modal(struct_, + CefBrowserCppToC::Wrap(browser)); + + // Return type: bool + return _retval?true:false; +} + +bool CefLifeSpanHandlerCToCpp::DoClose(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, do_close)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->do_close(struct_, + CefBrowserCppToC::Wrap(browser)); + + // Return type: bool + return _retval?true:false; +} + +void CefLifeSpanHandlerCToCpp::OnBeforeClose(CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_before_close)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_before_close(struct_, + CefBrowserCppToC::Wrap(browser)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/life_span_handler_ctocpp.h b/libcef_dll/ctocpp/life_span_handler_ctocpp.h new file mode 100644 index 000000000..85fd68c5a --- /dev/null +++ b/libcef_dll/ctocpp/life_span_handler_ctocpp.h @@ -0,0 +1,53 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_LIFE_SPAN_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_LIFE_SPAN_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_life_span_handler.h" +#include "include/capi/cef_life_span_handler_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefLifeSpanHandlerCToCpp + : public CefCToCpp { + public: + explicit CefLifeSpanHandlerCToCpp(cef_life_span_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefLifeSpanHandlerCToCpp() {} + + // CefLifeSpanHandler methods + virtual bool OnBeforePopup(CefRefPtr browser, + CefRefPtr frame, const CefString& target_url, + const CefString& target_frame_name, + const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, + CefRefPtr& client, CefBrowserSettings& settings, + bool* no_javascript_access) OVERRIDE; + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; + virtual bool RunModal(CefRefPtr browser) OVERRIDE; + virtual bool DoClose(CefRefPtr browser) OVERRIDE; + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_LIFE_SPAN_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/list_value_ctocpp.cc b/libcef_dll/ctocpp/list_value_ctocpp.cc new file mode 100644 index 000000000..7fe3e6529 --- /dev/null +++ b/libcef_dll/ctocpp/list_value_ctocpp.cc @@ -0,0 +1,476 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/binary_value_ctocpp.h" +#include "libcef_dll/ctocpp/dictionary_value_ctocpp.h" +#include "libcef_dll/ctocpp/list_value_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefListValue::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_list_value_t* _retval = cef_list_value_create(); + + // Return type: refptr_same + return CefListValueCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefListValueCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::IsOwned() { + if (CEF_MEMBER_MISSING(struct_, is_owned)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_owned(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefListValueCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_list_value_t* _retval = struct_->copy(struct_); + + // Return type: refptr_same + return CefListValueCToCpp::Wrap(_retval); +} + +bool CefListValueCToCpp::SetSize(size_t size) { + if (CEF_MEMBER_MISSING(struct_, set_size)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_size(struct_, + size); + + // Return type: bool + return _retval?true:false; +} + +size_t CefListValueCToCpp::GetSize() { + if (CEF_MEMBER_MISSING(struct_, get_size)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_size(struct_); + + // Return type: simple + return _retval; +} + +bool CefListValueCToCpp::Clear() { + if (CEF_MEMBER_MISSING(struct_, clear)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->clear(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::Remove(int index) { + if (CEF_MEMBER_MISSING(struct_, remove)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->remove(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +CefValueType CefListValueCToCpp::GetType(int index) { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return VTYPE_INVALID; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return VTYPE_INVALID; + + // Execute + cef_value_type_t _retval = struct_->get_type(struct_, + index); + + // Return type: simple + return _retval; +} + +bool CefListValueCToCpp::GetBool(int index) { + if (CEF_MEMBER_MISSING(struct_, get_bool)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->get_bool(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +int CefListValueCToCpp::GetInt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_int)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + int _retval = struct_->get_int(struct_, + index); + + // Return type: simple + return _retval; +} + +double CefListValueCToCpp::GetDouble(int index) { + if (CEF_MEMBER_MISSING(struct_, get_double)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return 0; + + // Execute + double _retval = struct_->get_double(struct_, + index); + + // Return type: simple + return _retval; +} + +CefString CefListValueCToCpp::GetString(int index) { + if (CEF_MEMBER_MISSING(struct_, get_string)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_string(struct_, + index); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefListValueCToCpp::GetBinary(int index) { + if (CEF_MEMBER_MISSING(struct_, get_binary)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + cef_binary_value_t* _retval = struct_->get_binary(struct_, + index); + + // Return type: refptr_same + return CefBinaryValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefListValueCToCpp::GetDictionary(int index) { + if (CEF_MEMBER_MISSING(struct_, get_dictionary)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + cef_dictionary_value_t* _retval = struct_->get_dictionary(struct_, + index); + + // Return type: refptr_same + return CefDictionaryValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefListValueCToCpp::GetList(int index) { + if (CEF_MEMBER_MISSING(struct_, get_list)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + cef_list_value_t* _retval = struct_->get_list(struct_, + index); + + // Return type: refptr_same + return CefListValueCToCpp::Wrap(_retval); +} + +bool CefListValueCToCpp::SetNull(int index) { + if (CEF_MEMBER_MISSING(struct_, set_null)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->set_null(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetBool(int index, bool value) { + if (CEF_MEMBER_MISSING(struct_, set_bool)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->set_bool(struct_, + index, + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetInt(int index, int value) { + if (CEF_MEMBER_MISSING(struct_, set_int)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->set_int(struct_, + index, + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetDouble(int index, double value) { + if (CEF_MEMBER_MISSING(struct_, set_double)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->set_double(struct_, + index, + value); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetString(int index, const CefString& value) { + if (CEF_MEMBER_MISSING(struct_, set_string)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + // Unverified params: value + + // Execute + int _retval = struct_->set_string(struct_, + index, + value.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetBinary(int index, CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_binary)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_binary(struct_, + index, + CefBinaryValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetDictionary(int index, + CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_dictionary)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_dictionary(struct_, + index, + CefDictionaryValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + +bool CefListValueCToCpp::SetList(int index, CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_list)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_list(struct_, + index, + CefListValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/list_value_ctocpp.h b/libcef_dll/ctocpp/list_value_ctocpp.h new file mode 100644 index 000000000..8967344bb --- /dev/null +++ b/libcef_dll/ctocpp/list_value_ctocpp.h @@ -0,0 +1,64 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_LIST_VALUE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_LIST_VALUE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_values.h" +#include "include/capi/cef_values_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefListValueCToCpp + : public CefCToCpp { + public: + explicit CefListValueCToCpp(cef_list_value_t* str) + : CefCToCpp(str) {} + virtual ~CefListValueCToCpp() {} + + // CefListValue methods + virtual bool IsValid() OVERRIDE; + virtual bool IsOwned() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual bool SetSize(size_t size) OVERRIDE; + virtual size_t GetSize() OVERRIDE; + virtual bool Clear() OVERRIDE; + virtual bool Remove(int index) OVERRIDE; + virtual CefValueType GetType(int index) OVERRIDE; + virtual bool GetBool(int index) OVERRIDE; + virtual int GetInt(int index) OVERRIDE; + virtual double GetDouble(int index) OVERRIDE; + virtual CefString GetString(int index) OVERRIDE; + virtual CefRefPtr GetBinary(int index) OVERRIDE; + virtual CefRefPtr GetDictionary(int index) OVERRIDE; + virtual CefRefPtr GetList(int index) OVERRIDE; + virtual bool SetNull(int index) OVERRIDE; + virtual bool SetBool(int index, bool value) OVERRIDE; + virtual bool SetInt(int index, int value) OVERRIDE; + virtual bool SetDouble(int index, double value) OVERRIDE; + virtual bool SetString(int index, const CefString& value) OVERRIDE; + virtual bool SetBinary(int index, CefRefPtr value) OVERRIDE; + virtual bool SetDictionary(int index, + CefRefPtr value) OVERRIDE; + virtual bool SetList(int index, CefRefPtr value) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_LIST_VALUE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/load_handler_ctocpp.cc b/libcef_dll/ctocpp/load_handler_ctocpp.cc new file mode 100644 index 000000000..47953b5d9 --- /dev/null +++ b/libcef_dll/ctocpp/load_handler_ctocpp.cc @@ -0,0 +1,121 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/ctocpp/load_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefLoadHandlerCToCpp::OnLoadingStateChange(CefRefPtr browser, + bool isLoading, bool canGoBack, bool canGoForward) { + if (CEF_MEMBER_MISSING(struct_, on_loading_state_change)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_loading_state_change(struct_, + CefBrowserCppToC::Wrap(browser), + isLoading, + canGoBack, + canGoForward); +} + +void CefLoadHandlerCToCpp::OnLoadStart(CefRefPtr browser, + CefRefPtr frame) { + if (CEF_MEMBER_MISSING(struct_, on_load_start)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + + // Execute + struct_->on_load_start(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame)); +} + +void CefLoadHandlerCToCpp::OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, int httpStatusCode) { + if (CEF_MEMBER_MISSING(struct_, on_load_end)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + + // Execute + struct_->on_load_end(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + httpStatusCode); +} + +void CefLoadHandlerCToCpp::OnLoadError(CefRefPtr browser, + CefRefPtr frame, ErrorCode errorCode, const CefString& errorText, + const CefString& failedUrl) { + if (CEF_MEMBER_MISSING(struct_, on_load_error)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: failedUrl; type: string_byref_const + DCHECK(!failedUrl.empty()); + if (failedUrl.empty()) + return; + // Unverified params: errorText + + // Execute + struct_->on_load_error(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + errorCode, + errorText.GetStruct(), + failedUrl.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/load_handler_ctocpp.h b/libcef_dll/ctocpp/load_handler_ctocpp.h new file mode 100644 index 000000000..578059640 --- /dev/null +++ b/libcef_dll/ctocpp/load_handler_ctocpp.h @@ -0,0 +1,50 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_LOAD_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_LOAD_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_load_handler.h" +#include "include/capi/cef_load_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefLoadHandlerCToCpp + : public CefCToCpp { + public: + explicit CefLoadHandlerCToCpp(cef_load_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefLoadHandlerCToCpp() {} + + // CefLoadHandler methods + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, bool canGoBack, bool canGoForward) OVERRIDE; + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) OVERRIDE; + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, int httpStatusCode) OVERRIDE; + virtual void OnLoadError(CefRefPtr browser, + CefRefPtr frame, ErrorCode errorCode, + const CefString& errorText, const CefString& failedUrl) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_LOAD_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/menu_model_ctocpp.cc b/libcef_dll/ctocpp/menu_model_ctocpp.cc new file mode 100644 index 000000000..3b7b0d042 --- /dev/null +++ b/libcef_dll/ctocpp/menu_model_ctocpp.cc @@ -0,0 +1,839 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/menu_model_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefMenuModelCToCpp::Clear() { + if (CEF_MEMBER_MISSING(struct_, clear)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->clear(struct_); + + // Return type: bool + return _retval?true:false; +} + +int CefMenuModelCToCpp::GetCount() { + if (CEF_MEMBER_MISSING(struct_, get_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_count(struct_); + + // Return type: simple + return _retval; +} + +bool CefMenuModelCToCpp::AddSeparator() { + if (CEF_MEMBER_MISSING(struct_, add_separator)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->add_separator(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::AddItem(int command_id, const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, add_item)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->add_item(struct_, + command_id, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::AddCheckItem(int command_id, const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, add_check_item)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->add_check_item(struct_, + command_id, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::AddRadioItem(int command_id, const CefString& label, + int group_id) { + if (CEF_MEMBER_MISSING(struct_, add_radio_item)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->add_radio_item(struct_, + command_id, + label.GetStruct(), + group_id); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefMenuModelCToCpp::AddSubMenu(int command_id, + const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, add_sub_menu)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return NULL; + + // Execute + cef_menu_model_t* _retval = struct_->add_sub_menu(struct_, + command_id, + label.GetStruct()); + + // Return type: refptr_same + return CefMenuModelCToCpp::Wrap(_retval); +} + +bool CefMenuModelCToCpp::InsertSeparatorAt(int index) { + if (CEF_MEMBER_MISSING(struct_, insert_separator_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->insert_separator_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::InsertItemAt(int index, int command_id, + const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, insert_item_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->insert_item_at(struct_, + index, + command_id, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::InsertCheckItemAt(int index, int command_id, + const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, insert_check_item_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->insert_check_item_at(struct_, + index, + command_id, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::InsertRadioItemAt(int index, int command_id, + const CefString& label, int group_id) { + if (CEF_MEMBER_MISSING(struct_, insert_radio_item_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->insert_radio_item_at(struct_, + index, + command_id, + label.GetStruct(), + group_id); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefMenuModelCToCpp::InsertSubMenuAt(int index, + int command_id, const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, insert_sub_menu_at)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return NULL; + + // Execute + cef_menu_model_t* _retval = struct_->insert_sub_menu_at(struct_, + index, + command_id, + label.GetStruct()); + + // Return type: refptr_same + return CefMenuModelCToCpp::Wrap(_retval); +} + +bool CefMenuModelCToCpp::Remove(int command_id) { + if (CEF_MEMBER_MISSING(struct_, remove)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->remove(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::RemoveAt(int index) { + if (CEF_MEMBER_MISSING(struct_, remove_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->remove_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +int CefMenuModelCToCpp::GetIndexOf(int command_id) { + if (CEF_MEMBER_MISSING(struct_, get_index_of)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_index_of(struct_, + command_id); + + // Return type: simple + return _retval; +} + +int CefMenuModelCToCpp::GetCommandIdAt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_command_id_at)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_command_id_at(struct_, + index); + + // Return type: simple + return _retval; +} + +bool CefMenuModelCToCpp::SetCommandIdAt(int index, int command_id) { + if (CEF_MEMBER_MISSING(struct_, set_command_id_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_command_id_at(struct_, + index, + command_id); + + // Return type: bool + return _retval?true:false; +} + +CefString CefMenuModelCToCpp::GetLabel(int command_id) { + if (CEF_MEMBER_MISSING(struct_, get_label)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_label(struct_, + command_id); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefMenuModelCToCpp::GetLabelAt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_label_at)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_label_at(struct_, + index); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefMenuModelCToCpp::SetLabel(int command_id, const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, set_label)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->set_label(struct_, + command_id, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetLabelAt(int index, const CefString& label) { + if (CEF_MEMBER_MISSING(struct_, set_label_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: label; type: string_byref_const + DCHECK(!label.empty()); + if (label.empty()) + return false; + + // Execute + int _retval = struct_->set_label_at(struct_, + index, + label.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +CefMenuModel::MenuItemType CefMenuModelCToCpp::GetType(int command_id) { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return MENUITEMTYPE_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_menu_item_type_t _retval = struct_->get_type(struct_, + command_id); + + // Return type: simple + return _retval; +} + +CefMenuModel::MenuItemType CefMenuModelCToCpp::GetTypeAt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_type_at)) + return MENUITEMTYPE_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_menu_item_type_t _retval = struct_->get_type_at(struct_, + index); + + // Return type: simple + return _retval; +} + +int CefMenuModelCToCpp::GetGroupId(int command_id) { + if (CEF_MEMBER_MISSING(struct_, get_group_id)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_group_id(struct_, + command_id); + + // Return type: simple + return _retval; +} + +int CefMenuModelCToCpp::GetGroupIdAt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_group_id_at)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_group_id_at(struct_, + index); + + // Return type: simple + return _retval; +} + +bool CefMenuModelCToCpp::SetGroupId(int command_id, int group_id) { + if (CEF_MEMBER_MISSING(struct_, set_group_id)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_group_id(struct_, + command_id, + group_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetGroupIdAt(int index, int group_id) { + if (CEF_MEMBER_MISSING(struct_, set_group_id_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_group_id_at(struct_, + index, + group_id); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefMenuModelCToCpp::GetSubMenu(int command_id) { + if (CEF_MEMBER_MISSING(struct_, get_sub_menu)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_menu_model_t* _retval = struct_->get_sub_menu(struct_, + command_id); + + // Return type: refptr_same + return CefMenuModelCToCpp::Wrap(_retval); +} + +CefRefPtr CefMenuModelCToCpp::GetSubMenuAt(int index) { + if (CEF_MEMBER_MISSING(struct_, get_sub_menu_at)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_menu_model_t* _retval = struct_->get_sub_menu_at(struct_, + index); + + // Return type: refptr_same + return CefMenuModelCToCpp::Wrap(_retval); +} + +bool CefMenuModelCToCpp::IsVisible(int command_id) { + if (CEF_MEMBER_MISSING(struct_, is_visible)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_visible(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::IsVisibleAt(int index) { + if (CEF_MEMBER_MISSING(struct_, is_visible_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_visible_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetVisible(int command_id, bool visible) { + if (CEF_MEMBER_MISSING(struct_, set_visible)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_visible(struct_, + command_id, + visible); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetVisibleAt(int index, bool visible) { + if (CEF_MEMBER_MISSING(struct_, set_visible_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_visible_at(struct_, + index, + visible); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::IsEnabled(int command_id) { + if (CEF_MEMBER_MISSING(struct_, is_enabled)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_enabled(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::IsEnabledAt(int index) { + if (CEF_MEMBER_MISSING(struct_, is_enabled_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_enabled_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetEnabled(int command_id, bool enabled) { + if (CEF_MEMBER_MISSING(struct_, set_enabled)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_enabled(struct_, + command_id, + enabled); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetEnabledAt(int index, bool enabled) { + if (CEF_MEMBER_MISSING(struct_, set_enabled_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_enabled_at(struct_, + index, + enabled); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::IsChecked(int command_id) { + if (CEF_MEMBER_MISSING(struct_, is_checked)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_checked(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::IsCheckedAt(int index) { + if (CEF_MEMBER_MISSING(struct_, is_checked_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_checked_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetChecked(int command_id, bool checked) { + if (CEF_MEMBER_MISSING(struct_, set_checked)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_checked(struct_, + command_id, + checked); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetCheckedAt(int index, bool checked) { + if (CEF_MEMBER_MISSING(struct_, set_checked_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_checked_at(struct_, + index, + checked); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::HasAccelerator(int command_id) { + if (CEF_MEMBER_MISSING(struct_, has_accelerator)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_accelerator(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::HasAcceleratorAt(int index) { + if (CEF_MEMBER_MISSING(struct_, has_accelerator_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_accelerator_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetAccelerator(int command_id, int key_code, + bool shift_pressed, bool ctrl_pressed, bool alt_pressed) { + if (CEF_MEMBER_MISSING(struct_, set_accelerator)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_accelerator(struct_, + command_id, + key_code, + shift_pressed, + ctrl_pressed, + alt_pressed); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetAcceleratorAt(int index, int key_code, + bool shift_pressed, bool ctrl_pressed, bool alt_pressed) { + if (CEF_MEMBER_MISSING(struct_, set_accelerator_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_accelerator_at(struct_, + index, + key_code, + shift_pressed, + ctrl_pressed, + alt_pressed); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::RemoveAccelerator(int command_id) { + if (CEF_MEMBER_MISSING(struct_, remove_accelerator)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->remove_accelerator(struct_, + command_id); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::RemoveAcceleratorAt(int index) { + if (CEF_MEMBER_MISSING(struct_, remove_accelerator_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->remove_accelerator_at(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::GetAccelerator(int command_id, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) { + if (CEF_MEMBER_MISSING(struct_, get_accelerator)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: shift_pressed; type: bool_byref + int shift_pressedInt = shift_pressed; + // Translate param: ctrl_pressed; type: bool_byref + int ctrl_pressedInt = ctrl_pressed; + // Translate param: alt_pressed; type: bool_byref + int alt_pressedInt = alt_pressed; + + // Execute + int _retval = struct_->get_accelerator(struct_, + command_id, + &key_code, + &shift_pressedInt, + &ctrl_pressedInt, + &alt_pressedInt); + + // Restore param:shift_pressed; type: bool_byref + shift_pressed = shift_pressedInt?true:false; + // Restore param:ctrl_pressed; type: bool_byref + ctrl_pressed = ctrl_pressedInt?true:false; + // Restore param:alt_pressed; type: bool_byref + alt_pressed = alt_pressedInt?true:false; + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::GetAcceleratorAt(int index, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) { + if (CEF_MEMBER_MISSING(struct_, get_accelerator_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: shift_pressed; type: bool_byref + int shift_pressedInt = shift_pressed; + // Translate param: ctrl_pressed; type: bool_byref + int ctrl_pressedInt = ctrl_pressed; + // Translate param: alt_pressed; type: bool_byref + int alt_pressedInt = alt_pressed; + + // Execute + int _retval = struct_->get_accelerator_at(struct_, + index, + &key_code, + &shift_pressedInt, + &ctrl_pressedInt, + &alt_pressedInt); + + // Restore param:shift_pressed; type: bool_byref + shift_pressed = shift_pressedInt?true:false; + // Restore param:ctrl_pressed; type: bool_byref + ctrl_pressed = ctrl_pressedInt?true:false; + // Restore param:alt_pressed; type: bool_byref + alt_pressed = alt_pressedInt?true:false; + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/menu_model_ctocpp.h b/libcef_dll/ctocpp/menu_model_ctocpp.h new file mode 100644 index 000000000..ba8c369a2 --- /dev/null +++ b/libcef_dll/ctocpp/menu_model_ctocpp.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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_menu_model.h" +#include "include/capi/cef_menu_model_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefMenuModelCToCpp + : public CefCToCpp { + public: + explicit CefMenuModelCToCpp(cef_menu_model_t* str) + : CefCToCpp(str) {} + virtual ~CefMenuModelCToCpp() {} + + // CefMenuModel methods + virtual bool Clear() OVERRIDE; + virtual int GetCount() OVERRIDE; + virtual bool AddSeparator() OVERRIDE; + virtual bool AddItem(int command_id, const CefString& label) OVERRIDE; + virtual bool AddCheckItem(int command_id, const CefString& label) OVERRIDE; + virtual bool AddRadioItem(int command_id, const CefString& label, + int group_id) OVERRIDE; + virtual CefRefPtr AddSubMenu(int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertSeparatorAt(int index) OVERRIDE; + virtual bool InsertItemAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertCheckItemAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool InsertRadioItemAt(int index, int command_id, + const CefString& label, int group_id) OVERRIDE; + virtual CefRefPtr InsertSubMenuAt(int index, int command_id, + const CefString& label) OVERRIDE; + virtual bool Remove(int command_id) OVERRIDE; + virtual bool RemoveAt(int index) OVERRIDE; + virtual int GetIndexOf(int command_id) OVERRIDE; + virtual int GetCommandIdAt(int index) OVERRIDE; + virtual bool SetCommandIdAt(int index, int command_id) OVERRIDE; + virtual CefString GetLabel(int command_id) OVERRIDE; + virtual CefString GetLabelAt(int index) OVERRIDE; + virtual bool SetLabel(int command_id, const CefString& label) OVERRIDE; + virtual bool SetLabelAt(int index, const CefString& label) OVERRIDE; + virtual MenuItemType GetType(int command_id) OVERRIDE; + virtual MenuItemType GetTypeAt(int index) OVERRIDE; + virtual int GetGroupId(int command_id) OVERRIDE; + virtual int GetGroupIdAt(int index) OVERRIDE; + virtual bool SetGroupId(int command_id, int group_id) OVERRIDE; + virtual bool SetGroupIdAt(int index, int group_id) OVERRIDE; + virtual CefRefPtr GetSubMenu(int command_id) OVERRIDE; + virtual CefRefPtr GetSubMenuAt(int index) OVERRIDE; + virtual bool IsVisible(int command_id) OVERRIDE; + virtual bool IsVisibleAt(int index) OVERRIDE; + virtual bool SetVisible(int command_id, bool visible) OVERRIDE; + virtual bool SetVisibleAt(int index, bool visible) OVERRIDE; + virtual bool IsEnabled(int command_id) OVERRIDE; + virtual bool IsEnabledAt(int index) OVERRIDE; + virtual bool SetEnabled(int command_id, bool enabled) OVERRIDE; + virtual bool SetEnabledAt(int index, bool enabled) OVERRIDE; + virtual bool IsChecked(int command_id) OVERRIDE; + virtual bool IsCheckedAt(int index) OVERRIDE; + virtual bool SetChecked(int command_id, bool checked) OVERRIDE; + virtual bool SetCheckedAt(int index, bool checked) OVERRIDE; + virtual bool HasAccelerator(int command_id) OVERRIDE; + virtual bool HasAcceleratorAt(int index) OVERRIDE; + virtual bool SetAccelerator(int command_id, int key_code, bool shift_pressed, + bool ctrl_pressed, bool alt_pressed) OVERRIDE; + virtual bool SetAcceleratorAt(int index, int key_code, bool shift_pressed, + bool ctrl_pressed, bool alt_pressed) OVERRIDE; + virtual bool RemoveAccelerator(int command_id) OVERRIDE; + virtual bool RemoveAcceleratorAt(int index) OVERRIDE; + virtual bool GetAccelerator(int command_id, int& key_code, + bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; + virtual bool GetAcceleratorAt(int index, int& key_code, bool& shift_pressed, + bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/permission_handler_ctocpp.cc b/libcef_dll/ctocpp/permission_handler_ctocpp.cc new file mode 100644 index 000000000..700e91b39 --- /dev/null +++ b/libcef_dll/ctocpp/permission_handler_ctocpp.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/ctocpp/permission_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefPermissionHandlerCToCpp::OnBeforeScriptExtensionLoad( + CefRefPtr browser, CefRefPtr frame, + const CefString& extensionName) { + if (CEF_MEMBER_MISSING(struct_, on_before_script_extension_load)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: extensionName; type: string_byref_const + DCHECK(!extensionName.empty()); + if (extensionName.empty()) + return false; + + // Execute + int _retval = struct_->on_before_script_extension_load(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + extensionName.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> long CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/permission_handler_ctocpp.h b/libcef_dll/ctocpp/permission_handler_ctocpp.h new file mode 100644 index 000000000..0bffa2a81 --- /dev/null +++ b/libcef_dll/ctocpp/permission_handler_ctocpp.h @@ -0,0 +1,47 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_permission_handler.h" +#include "include/capi/cef_permission_handler_capi.h" +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_frame.h" +#include "include/capi/cef_frame_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefPermissionHandlerCToCpp + : public CefCToCpp { + public: + explicit CefPermissionHandlerCToCpp(cef_permission_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefPermissionHandlerCToCpp() {} + + // CefPermissionHandler methods + virtual bool OnBeforeScriptExtensionLoad(CefRefPtr browser, + CefRefPtr frame, const CefString& extensionName) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/post_data_ctocpp.cc b/libcef_dll/ctocpp/post_data_ctocpp.cc new file mode 100644 index 000000000..2c74a91fa --- /dev/null +++ b/libcef_dll/ctocpp/post_data_ctocpp.cc @@ -0,0 +1,150 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/ctocpp/post_data_ctocpp.h" +#include "libcef_dll/ctocpp/post_data_element_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefPostData::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_post_data_t* _retval = cef_post_data_create(); + + // Return type: refptr_same + return CefPostDataCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefPostDataCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +size_t CefPostDataCToCpp::GetElementCount() { + if (CEF_MEMBER_MISSING(struct_, get_element_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_element_count(struct_); + + // Return type: simple + return _retval; +} + +void CefPostDataCToCpp::GetElements(ElementVector& elements) { + if (CEF_MEMBER_MISSING(struct_, get_elements)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: elements; type: refptr_vec_same_byref + size_t elementsSize = elements.size(); + size_t elementsCount = std::max(GetElementCount(), elementsSize); + cef_post_data_element_t** elementsList = NULL; + if (elementsCount > 0) { + elementsList = new cef_post_data_element_t*[elementsCount]; + DCHECK(elementsList); + if (elementsList) { + memset(elementsList, 0, sizeof(cef_post_data_element_t*)*elementsCount); + } + if (elementsList && elementsSize > 0) { + for (size_t i = 0; i < elementsSize; ++i) { + elementsList[i] = CefPostDataElementCToCpp::Unwrap(elements[i]); + } + } + } + + // Execute + struct_->get_elements(struct_, + &elementsCount, + elementsList); + + // Restore param:elements; type: refptr_vec_same_byref + elements.clear(); + if (elementsCount > 0 && elementsList) { + for (size_t i = 0; i < elementsCount; ++i) { + elements.push_back(CefPostDataElementCToCpp::Wrap(elementsList[i])); + } + delete [] elementsList; + } +} + +bool CefPostDataCToCpp::RemoveElement(CefRefPtr element) { + if (CEF_MEMBER_MISSING(struct_, remove_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: element; type: refptr_same + DCHECK(element.get()); + if (!element.get()) + return false; + + // Execute + int _retval = struct_->remove_element(struct_, + CefPostDataElementCToCpp::Unwrap(element)); + + // Return type: bool + return _retval?true:false; +} + +bool CefPostDataCToCpp::AddElement(CefRefPtr element) { + if (CEF_MEMBER_MISSING(struct_, add_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: element; type: refptr_same + DCHECK(element.get()); + if (!element.get()) + return false; + + // Execute + int _retval = struct_->add_element(struct_, + CefPostDataElementCToCpp::Unwrap(element)); + + // Return type: bool + return _retval?true:false; +} + +void CefPostDataCToCpp::RemoveElements() { + if (CEF_MEMBER_MISSING(struct_, remove_elements)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->remove_elements(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/post_data_ctocpp.h b/libcef_dll/ctocpp/post_data_ctocpp.h new file mode 100644 index 000000000..7622a382d --- /dev/null +++ b/libcef_dll/ctocpp/post_data_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_POST_DATA_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_POST_DATA_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefPostDataCToCpp + : public CefCToCpp { + public: + explicit CefPostDataCToCpp(cef_post_data_t* str) + : CefCToCpp(str) {} + virtual ~CefPostDataCToCpp() {} + + // CefPostData methods + virtual bool IsReadOnly() OVERRIDE; + virtual size_t GetElementCount() OVERRIDE; + virtual void GetElements(ElementVector& elements) OVERRIDE; + virtual bool RemoveElement(CefRefPtr element) OVERRIDE; + virtual bool AddElement(CefRefPtr element) OVERRIDE; + virtual void RemoveElements() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_POST_DATA_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/post_data_element_ctocpp.cc b/libcef_dll/ctocpp/post_data_element_ctocpp.cc new file mode 100644 index 000000000..f84ab4995 --- /dev/null +++ b/libcef_dll/ctocpp/post_data_element_ctocpp.cc @@ -0,0 +1,153 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/post_data_element_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefPostDataElement::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_post_data_element_t* _retval = cef_post_data_element_create(); + + // Return type: refptr_same + return CefPostDataElementCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefPostDataElementCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefPostDataElementCToCpp::SetToEmpty() { + if (CEF_MEMBER_MISSING(struct_, set_to_empty)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_to_empty(struct_); +} + +void CefPostDataElementCToCpp::SetToFile(const CefString& fileName) { + if (CEF_MEMBER_MISSING(struct_, set_to_file)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(!fileName.empty()); + if (fileName.empty()) + return; + + // Execute + struct_->set_to_file(struct_, + fileName.GetStruct()); +} + +void CefPostDataElementCToCpp::SetToBytes(size_t size, const void* bytes) { + if (CEF_MEMBER_MISSING(struct_, set_to_bytes)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: bytes; type: simple_byaddr + DCHECK(bytes); + if (!bytes) + return; + + // Execute + struct_->set_to_bytes(struct_, + size, + bytes); +} + +CefPostDataElement::Type CefPostDataElementCToCpp::GetType() { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return PDE_TYPE_EMPTY; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_postdataelement_type_t _retval = struct_->get_type(struct_); + + // Return type: simple + return _retval; +} + +CefString CefPostDataElementCToCpp::GetFile() { + if (CEF_MEMBER_MISSING(struct_, get_file)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_file(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +size_t CefPostDataElementCToCpp::GetBytesCount() { + if (CEF_MEMBER_MISSING(struct_, get_bytes_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_bytes_count(struct_); + + // Return type: simple + return _retval; +} + +size_t CefPostDataElementCToCpp::GetBytes(size_t size, void* bytes) { + if (CEF_MEMBER_MISSING(struct_, get_bytes)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: bytes; type: simple_byaddr + DCHECK(bytes); + if (!bytes) + return 0; + + // Execute + size_t _retval = struct_->get_bytes(struct_, + size, + bytes); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/post_data_element_ctocpp.h b/libcef_dll/ctocpp/post_data_element_ctocpp.h new file mode 100644 index 000000000..ccc6e2b1b --- /dev/null +++ b/libcef_dll/ctocpp/post_data_element_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_POST_DATA_ELEMENT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_POST_DATA_ELEMENT_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefPostDataElementCToCpp + : public CefCToCpp { + public: + explicit CefPostDataElementCToCpp(cef_post_data_element_t* str) + : CefCToCpp(str) {} + virtual ~CefPostDataElementCToCpp() {} + + // CefPostDataElement methods + virtual bool IsReadOnly() OVERRIDE; + virtual void SetToEmpty() OVERRIDE; + virtual void SetToFile(const CefString& fileName) OVERRIDE; + virtual void SetToBytes(size_t size, const void* bytes) OVERRIDE; + virtual Type GetType() OVERRIDE; + virtual CefString GetFile() OVERRIDE; + virtual size_t GetBytesCount() OVERRIDE; + virtual size_t GetBytes(size_t size, void* bytes) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_POST_DATA_ELEMENT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc new file mode 100644 index 000000000..409e5450b --- /dev/null +++ b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.cc @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/print_dialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/print_settings_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefPrintDialogCallbackCToCpp::Continue( + CefRefPtr settings) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: settings; type: refptr_same + DCHECK(settings.get()); + if (!settings.get()) + return; + + // Execute + struct_->cont(struct_, + CefPrintSettingsCToCpp::Unwrap(settings)); +} + +void CefPrintDialogCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h new file mode 100644 index 000000000..11797393b --- /dev/null +++ b/libcef_dll/ctocpp/print_dialog_callback_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_DIALOG_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PRINT_DIALOG_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefPrintDialogCallbackCToCpp + : public CefCToCpp { + public: + explicit CefPrintDialogCallbackCToCpp(cef_print_dialog_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefPrintDialogCallbackCToCpp() {} + + // CefPrintDialogCallback methods + virtual void Continue(CefRefPtr settings) OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PRINT_DIALOG_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/print_handler_ctocpp.cc b/libcef_dll/ctocpp/print_handler_ctocpp.cc new file mode 100644 index 000000000..664e88c1f --- /dev/null +++ b/libcef_dll/ctocpp/print_handler_ctocpp.cc @@ -0,0 +1,105 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/print_dialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/print_job_callback_cpptoc.h" +#include "libcef_dll/cpptoc/print_settings_cpptoc.h" +#include "libcef_dll/ctocpp/print_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefPrintHandlerCToCpp::OnPrintSettings( + CefRefPtr settings, bool get_defaults) { + if (CEF_MEMBER_MISSING(struct_, on_print_settings)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: settings; type: refptr_diff + DCHECK(settings.get()); + if (!settings.get()) + return; + + // Execute + struct_->on_print_settings(struct_, + CefPrintSettingsCppToC::Wrap(settings), + get_defaults); +} + +bool CefPrintHandlerCToCpp::OnPrintDialog(bool has_selection, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_print_dialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->on_print_dialog(struct_, + has_selection, + CefPrintDialogCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +bool CefPrintHandlerCToCpp::OnPrintJob(const CefString& document_name, + const CefString& pdf_file_path, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_print_job)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: document_name; type: string_byref_const + DCHECK(!document_name.empty()); + if (document_name.empty()) + return false; + // Verify param: pdf_file_path; type: string_byref_const + DCHECK(!pdf_file_path.empty()); + if (pdf_file_path.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->on_print_job(struct_, + document_name.GetStruct(), + pdf_file_path.GetStruct(), + CefPrintJobCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefPrintHandlerCToCpp::OnPrintReset() { + if (CEF_MEMBER_MISSING(struct_, on_print_reset)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_print_reset(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/print_handler_ctocpp.h b/libcef_dll/ctocpp/print_handler_ctocpp.h new file mode 100644 index 000000000..f826c173a --- /dev/null +++ b/libcef_dll/ctocpp/print_handler_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefPrintHandlerCToCpp + : public CefCToCpp { + public: + explicit CefPrintHandlerCToCpp(cef_print_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefPrintHandlerCToCpp() {} + + // CefPrintHandler methods + virtual void OnPrintSettings(CefRefPtr settings, + bool get_defaults) OVERRIDE; + virtual bool OnPrintDialog(bool has_selection, + CefRefPtr callback) OVERRIDE; + virtual bool OnPrintJob(const CefString& document_name, + const CefString& pdf_file_path, + CefRefPtr callback) OVERRIDE; + virtual void OnPrintReset() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/print_job_callback_ctocpp.cc b/libcef_dll/ctocpp/print_job_callback_ctocpp.cc new file mode 100644 index 000000000..78470b5cb --- /dev/null +++ b/libcef_dll/ctocpp/print_job_callback_ctocpp.cc @@ -0,0 +1,33 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/print_job_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefPrintJobCallbackCToCpp::Continue() { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cont(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/print_job_callback_ctocpp.h b/libcef_dll/ctocpp/print_job_callback_ctocpp.h new file mode 100644 index 000000000..4cb4f68ce --- /dev/null +++ b/libcef_dll/ctocpp/print_job_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_JOB_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PRINT_JOB_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_print_handler.h" +#include "include/capi/cef_print_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefPrintJobCallbackCToCpp + : public CefCToCpp { + public: + explicit CefPrintJobCallbackCToCpp(cef_print_job_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefPrintJobCallbackCToCpp() {} + + // CefPrintJobCallback methods + virtual void Continue() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PRINT_JOB_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/print_settings_ctocpp.cc b/libcef_dll/ctocpp/print_settings_ctocpp.cc new file mode 100644 index 000000000..5b9baba24 --- /dev/null +++ b/libcef_dll/ctocpp/print_settings_ctocpp.cc @@ -0,0 +1,367 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include +#include "libcef_dll/ctocpp/print_settings_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefPrintSettings::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_print_settings_t* _retval = cef_print_settings_create(); + + // Return type: refptr_same + return CefPrintSettingsCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefPrintSettingsCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefPrintSettingsCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefPrintSettingsCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_print_settings_t* _retval = struct_->copy(struct_); + + // Return type: refptr_same + return CefPrintSettingsCToCpp::Wrap(_retval); +} + +void CefPrintSettingsCToCpp::SetOrientation(bool landscape) { + if (CEF_MEMBER_MISSING(struct_, set_orientation)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_orientation(struct_, + landscape); +} + +bool CefPrintSettingsCToCpp::IsLandscape() { + if (CEF_MEMBER_MISSING(struct_, is_landscape)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_landscape(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefPrintSettingsCToCpp::SetPrinterPrintableArea( + const CefSize& physical_size_device_units, + const CefRect& printable_area_device_units, bool landscape_needs_flip) { + if (CEF_MEMBER_MISSING(struct_, set_printer_printable_area)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_printer_printable_area(struct_, + &physical_size_device_units, + &printable_area_device_units, + landscape_needs_flip); +} + +void CefPrintSettingsCToCpp::SetDeviceName(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, set_device_name)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: name + + // Execute + struct_->set_device_name(struct_, + name.GetStruct()); +} + +CefString CefPrintSettingsCToCpp::GetDeviceName() { + if (CEF_MEMBER_MISSING(struct_, get_device_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_device_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefPrintSettingsCToCpp::SetDPI(int dpi) { + if (CEF_MEMBER_MISSING(struct_, set_dpi)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_dpi(struct_, + dpi); +} + +int CefPrintSettingsCToCpp::GetDPI() { + if (CEF_MEMBER_MISSING(struct_, get_dpi)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_dpi(struct_); + + // Return type: simple + return _retval; +} + +void CefPrintSettingsCToCpp::SetPageRanges(const PageRangeList& ranges) { + if (CEF_MEMBER_MISSING(struct_, set_page_ranges)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: ranges; type: simple_vec_byref_const + const size_t rangesCount = ranges.size(); + cef_page_range_t* rangesList = NULL; + if (rangesCount > 0) { + rangesList = new cef_page_range_t[rangesCount]; + DCHECK(rangesList); + if (rangesList) { + for (size_t i = 0; i < rangesCount; ++i) { + rangesList[i] = ranges[i]; + } + } + } + + // Execute + struct_->set_page_ranges(struct_, + rangesCount, + rangesList); + + // Restore param:ranges; type: simple_vec_byref_const + if (rangesList) + delete [] rangesList; +} + +size_t CefPrintSettingsCToCpp::GetPageRangesCount() { + if (CEF_MEMBER_MISSING(struct_, get_page_ranges_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_page_ranges_count(struct_); + + // Return type: simple + return _retval; +} + +void CefPrintSettingsCToCpp::GetPageRanges(PageRangeList& ranges) { + if (CEF_MEMBER_MISSING(struct_, get_page_ranges)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: ranges; type: simple_vec_byref + size_t rangesSize = ranges.size(); + size_t rangesCount = std::max(GetPageRangesCount(), rangesSize); + cef_page_range_t* rangesList = NULL; + if (rangesCount > 0) { + rangesList = new cef_page_range_t[rangesCount]; + DCHECK(rangesList); + if (rangesList) { + memset(rangesList, 0, sizeof(cef_page_range_t)*rangesCount); + } + if (rangesList && rangesSize > 0) { + for (size_t i = 0; i < rangesSize; ++i) { + rangesList[i] = ranges[i]; + } + } + } + + // Execute + struct_->get_page_ranges(struct_, + &rangesCount, + rangesList); + + // Restore param:ranges; type: simple_vec_byref + ranges.clear(); + if (rangesCount > 0 && rangesList) { + for (size_t i = 0; i < rangesCount; ++i) { + ranges.push_back(rangesList[i]); + } + delete [] rangesList; + } +} + +void CefPrintSettingsCToCpp::SetSelectionOnly(bool selection_only) { + if (CEF_MEMBER_MISSING(struct_, set_selection_only)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_selection_only(struct_, + selection_only); +} + +bool CefPrintSettingsCToCpp::IsSelectionOnly() { + if (CEF_MEMBER_MISSING(struct_, is_selection_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_selection_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefPrintSettingsCToCpp::SetCollate(bool collate) { + if (CEF_MEMBER_MISSING(struct_, set_collate)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_collate(struct_, + collate); +} + +bool CefPrintSettingsCToCpp::WillCollate() { + if (CEF_MEMBER_MISSING(struct_, will_collate)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->will_collate(struct_); + + // Return type: bool + return _retval?true:false; +} + +void CefPrintSettingsCToCpp::SetColorModel(ColorModel model) { + if (CEF_MEMBER_MISSING(struct_, set_color_model)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_color_model(struct_, + model); +} + +CefPrintSettings::ColorModel CefPrintSettingsCToCpp::GetColorModel() { + if (CEF_MEMBER_MISSING(struct_, get_color_model)) + return COLOR_MODEL_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_color_model_t _retval = struct_->get_color_model(struct_); + + // Return type: simple + return _retval; +} + +void CefPrintSettingsCToCpp::SetCopies(int copies) { + if (CEF_MEMBER_MISSING(struct_, set_copies)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_copies(struct_, + copies); +} + +int CefPrintSettingsCToCpp::GetCopies() { + if (CEF_MEMBER_MISSING(struct_, get_copies)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_copies(struct_); + + // Return type: simple + return _retval; +} + +void CefPrintSettingsCToCpp::SetDuplexMode(DuplexMode mode) { + if (CEF_MEMBER_MISSING(struct_, set_duplex_mode)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_duplex_mode(struct_, + mode); +} + +CefPrintSettings::DuplexMode CefPrintSettingsCToCpp::GetDuplexMode() { + if (CEF_MEMBER_MISSING(struct_, get_duplex_mode)) + return DUPLEX_MODE_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_duplex_mode_t _retval = struct_->get_duplex_mode(struct_); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/print_settings_ctocpp.h b/libcef_dll/ctocpp/print_settings_ctocpp.h new file mode 100644 index 000000000..8299b7ffd --- /dev/null +++ b/libcef_dll/ctocpp/print_settings_ctocpp.h @@ -0,0 +1,67 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_SETTINGS_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PRINT_SETTINGS_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_print_settings.h" +#include "include/capi/cef_print_settings_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefPrintSettingsCToCpp + : public CefCToCpp { + public: + explicit CefPrintSettingsCToCpp(cef_print_settings_t* str) + : CefCToCpp(str) {} + virtual ~CefPrintSettingsCToCpp() {} + + // CefPrintSettings methods + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual void SetOrientation(bool landscape) OVERRIDE; + virtual bool IsLandscape() OVERRIDE; + virtual void SetPrinterPrintableArea( + const CefSize& physical_size_device_units, + const CefRect& printable_area_device_units, + bool landscape_needs_flip) OVERRIDE; + virtual void SetDeviceName(const CefString& name) OVERRIDE; + virtual CefString GetDeviceName() OVERRIDE; + virtual void SetDPI(int dpi) OVERRIDE; + virtual int GetDPI() OVERRIDE; + virtual void SetPageRanges(const PageRangeList& ranges) OVERRIDE; + virtual size_t GetPageRangesCount() OVERRIDE; + virtual void GetPageRanges(PageRangeList& ranges) OVERRIDE; + virtual void SetSelectionOnly(bool selection_only) OVERRIDE; + virtual bool IsSelectionOnly() OVERRIDE; + virtual void SetCollate(bool collate) OVERRIDE; + virtual bool WillCollate() OVERRIDE; + virtual void SetColorModel(ColorModel model) OVERRIDE; + virtual ColorModel GetColorModel() OVERRIDE; + virtual void SetCopies(int copies) OVERRIDE; + virtual int GetCopies() OVERRIDE; + virtual void SetDuplexMode(DuplexMode mode) OVERRIDE; + virtual DuplexMode GetDuplexMode() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PRINT_SETTINGS_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/process_message_ctocpp.cc b/libcef_dll/ctocpp/process_message_ctocpp.cc new file mode 100644 index 000000000..77983aba0 --- /dev/null +++ b/libcef_dll/ctocpp/process_message_ctocpp.cc @@ -0,0 +1,110 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/list_value_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefProcessMessage::Create(const CefString& name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return NULL; + + // Execute + cef_process_message_t* _retval = cef_process_message_create( + name.GetStruct()); + + // Return type: refptr_same + return CefProcessMessageCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefProcessMessageCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefProcessMessageCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefProcessMessageCToCpp::Copy() { + if (CEF_MEMBER_MISSING(struct_, copy)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_process_message_t* _retval = struct_->copy(struct_); + + // Return type: refptr_same + return CefProcessMessageCToCpp::Wrap(_retval); +} + +CefString CefProcessMessageCToCpp::GetName() { + if (CEF_MEMBER_MISSING(struct_, get_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefProcessMessageCToCpp::GetArgumentList() { + if (CEF_MEMBER_MISSING(struct_, get_argument_list)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_list_value_t* _retval = struct_->get_argument_list(struct_); + + // Return type: refptr_same + return CefListValueCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/process_message_ctocpp.h b/libcef_dll/ctocpp/process_message_ctocpp.h new file mode 100644 index 000000000..242681a13 --- /dev/null +++ b/libcef_dll/ctocpp/process_message_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_process_message.h" +#include "include/capi/cef_process_message_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefProcessMessageCToCpp + : public CefCToCpp { + public: + explicit CefProcessMessageCToCpp(cef_process_message_t* str) + : CefCToCpp(str) {} + virtual ~CefProcessMessageCToCpp() {} + + // CefProcessMessage methods + virtual bool IsValid() OVERRIDE; + virtual bool IsReadOnly() OVERRIDE; + virtual CefRefPtr Copy() OVERRIDE; + virtual CefString GetName() OVERRIDE; + virtual CefRefPtr GetArgumentList() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/quota_callback_ctocpp.cc b/libcef_dll/ctocpp/quota_callback_ctocpp.cc new file mode 100644 index 000000000..c782ffb51 --- /dev/null +++ b/libcef_dll/ctocpp/quota_callback_ctocpp.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/quota_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefQuotaCallbackCToCpp::Continue(bool allow) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cont(struct_, + allow); +} + +void CefQuotaCallbackCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/quota_callback_ctocpp.h b/libcef_dll/ctocpp/quota_callback_ctocpp.h new file mode 100644 index 000000000..76ca72f24 --- /dev/null +++ b/libcef_dll/ctocpp/quota_callback_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_QUOTA_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_QUOTA_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefQuotaCallbackCToCpp + : public CefCToCpp { + public: + explicit CefQuotaCallbackCToCpp(cef_quota_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefQuotaCallbackCToCpp() {} + + // CefQuotaCallback methods + virtual void Continue(bool allow) OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_QUOTA_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/read_handler_ctocpp.cc b/libcef_dll/ctocpp/read_handler_ctocpp.cc new file mode 100644 index 000000000..2230cfeef --- /dev/null +++ b/libcef_dll/ctocpp/read_handler_ctocpp.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/read_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +size_t CefReadHandlerCToCpp::Read(void* ptr, size_t size, size_t n) { + if (CEF_MEMBER_MISSING(struct_, read)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = struct_->read(struct_, + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CefReadHandlerCToCpp::Seek(int64 offset, int whence) { + if (CEF_MEMBER_MISSING(struct_, seek)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->seek(struct_, + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CefReadHandlerCToCpp::Tell() { + if (CEF_MEMBER_MISSING(struct_, tell)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->tell(struct_); + + // Return type: simple + return _retval; +} + +int CefReadHandlerCToCpp::Eof() { + if (CEF_MEMBER_MISSING(struct_, eof)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->eof(struct_); + + // Return type: simple + return _retval; +} + +bool CefReadHandlerCToCpp::MayBlock() { + if (CEF_MEMBER_MISSING(struct_, may_block)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->may_block(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/read_handler_ctocpp.h b/libcef_dll/ctocpp/read_handler_ctocpp.h new file mode 100644 index 000000000..85ebf2de6 --- /dev/null +++ b/libcef_dll/ctocpp/read_handler_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_READ_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_READ_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefReadHandlerCToCpp + : public CefCToCpp { + public: + explicit CefReadHandlerCToCpp(cef_read_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefReadHandlerCToCpp() {} + + // CefReadHandler methods + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Eof() OVERRIDE; + virtual bool MayBlock() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_READ_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc new file mode 100644 index 000000000..3b46f9d14 --- /dev/null +++ b/libcef_dll/ctocpp/render_handler_ctocpp.cc @@ -0,0 +1,275 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/ctocpp/render_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefRenderHandlerCToCpp::GetRootScreenRect(CefRefPtr browser, + CefRect& rect) { + if (CEF_MEMBER_MISSING(struct_, get_root_screen_rect)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->get_root_screen_rect(struct_, + CefBrowserCppToC::Wrap(browser), + &rect); + + // Return type: bool + return _retval?true:false; +} + +bool CefRenderHandlerCToCpp::GetViewRect(CefRefPtr browser, + CefRect& rect) { + if (CEF_MEMBER_MISSING(struct_, get_view_rect)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->get_view_rect(struct_, + CefBrowserCppToC::Wrap(browser), + &rect); + + // Return type: bool + return _retval?true:false; +} + +bool CefRenderHandlerCToCpp::GetScreenPoint(CefRefPtr browser, + int viewX, int viewY, int& screenX, int& screenY) { + if (CEF_MEMBER_MISSING(struct_, get_screen_point)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->get_screen_point(struct_, + CefBrowserCppToC::Wrap(browser), + viewX, + viewY, + &screenX, + &screenY); + + // Return type: bool + return _retval?true:false; +} + +bool CefRenderHandlerCToCpp::GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) { + if (CEF_MEMBER_MISSING(struct_, get_screen_info)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + + // Execute + int _retval = struct_->get_screen_info(struct_, + CefBrowserCppToC::Wrap(browser), + &screen_info); + + // Return type: bool + return _retval?true:false; +} + +void CefRenderHandlerCToCpp::OnPopupShow(CefRefPtr browser, + bool show) { + if (CEF_MEMBER_MISSING(struct_, on_popup_show)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_popup_show(struct_, + CefBrowserCppToC::Wrap(browser), + show); +} + +void CefRenderHandlerCToCpp::OnPopupSize(CefRefPtr browser, + const CefRect& rect) { + if (CEF_MEMBER_MISSING(struct_, on_popup_size)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_popup_size(struct_, + CefBrowserCppToC::Wrap(browser), + &rect); +} + +void CefRenderHandlerCToCpp::OnPaint(CefRefPtr browser, + PaintElementType type, const RectList& dirtyRects, const void* buffer, + int width, int height) { + if (CEF_MEMBER_MISSING(struct_, on_paint)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return; + + // Translate param: dirtyRects; type: simple_vec_byref_const + const size_t dirtyRectsCount = dirtyRects.size(); + cef_rect_t* dirtyRectsList = NULL; + if (dirtyRectsCount > 0) { + dirtyRectsList = new cef_rect_t[dirtyRectsCount]; + DCHECK(dirtyRectsList); + if (dirtyRectsList) { + for (size_t i = 0; i < dirtyRectsCount; ++i) { + dirtyRectsList[i] = dirtyRects[i]; + } + } + } + + // Execute + struct_->on_paint(struct_, + CefBrowserCppToC::Wrap(browser), + type, + dirtyRectsCount, + dirtyRectsList, + buffer, + width, + height); + + // Restore param:dirtyRects; type: simple_vec_byref_const + if (dirtyRectsList) + delete [] dirtyRectsList; +} + +void CefRenderHandlerCToCpp::OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor) { + if (CEF_MEMBER_MISSING(struct_, on_cursor_change)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_cursor_change(struct_, + CefBrowserCppToC::Wrap(browser), + cursor); +} + +bool CefRenderHandlerCToCpp::StartDragging(CefRefPtr browser, + CefRefPtr drag_data, DragOperationsMask allowed_ops, int x, + int y) { + if (CEF_MEMBER_MISSING(struct_, start_dragging)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: drag_data; type: refptr_diff + DCHECK(drag_data.get()); + if (!drag_data.get()) + return false; + + // Execute + int _retval = struct_->start_dragging(struct_, + CefBrowserCppToC::Wrap(browser), + CefDragDataCppToC::Wrap(drag_data), + allowed_ops, + x, + y); + + // Return type: bool + return _retval?true:false; +} + +void CefRenderHandlerCToCpp::UpdateDragCursor(CefRefPtr browser, + DragOperation operation) { + if (CEF_MEMBER_MISSING(struct_, update_drag_cursor)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->update_drag_cursor(struct_, + CefBrowserCppToC::Wrap(browser), + operation); +} + +void CefRenderHandlerCToCpp::OnScrollOffsetChanged( + CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_scroll_offset_changed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_scroll_offset_changed(struct_, + CefBrowserCppToC::Wrap(browser)); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.h b/libcef_dll/ctocpp/render_handler_ctocpp.h new file mode 100644 index 000000000..9d8b790e6 --- /dev/null +++ b/libcef_dll/ctocpp/render_handler_ctocpp.h @@ -0,0 +1,63 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_render_handler.h" +#include "include/capi/cef_render_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefRenderHandlerCToCpp + : public CefCToCpp { + public: + explicit CefRenderHandlerCToCpp(cef_render_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefRenderHandlerCToCpp() {} + + // CefRenderHandler methods + virtual bool GetRootScreenRect(CefRefPtr browser, + CefRect& rect) OVERRIDE; + virtual bool GetViewRect(CefRefPtr browser, + CefRect& rect) OVERRIDE; + virtual bool GetScreenPoint(CefRefPtr browser, int viewX, + int viewY, int& screenX, int& screenY) OVERRIDE; + virtual bool GetScreenInfo(CefRefPtr browser, + CefScreenInfo& screen_info) OVERRIDE; + virtual void OnPopupShow(CefRefPtr browser, bool show) OVERRIDE; + virtual void OnPopupSize(CefRefPtr browser, + const CefRect& rect) OVERRIDE; + virtual void OnPaint(CefRefPtr browser, PaintElementType type, + const RectList& dirtyRects, const void* buffer, int width, + int height) OVERRIDE; + virtual void OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor) OVERRIDE; + virtual bool StartDragging(CefRefPtr browser, + CefRefPtr drag_data, DragOperationsMask allowed_ops, int x, + int y) OVERRIDE; + virtual void UpdateDragCursor(CefRefPtr browser, + DragOperation operation) OVERRIDE; + virtual void OnScrollOffsetChanged(CefRefPtr browser) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc new file mode 100644 index 000000000..c76f3a8dd --- /dev/null +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc @@ -0,0 +1,284 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/list_value_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/v8context_cpptoc.h" +#include "libcef_dll/cpptoc/v8exception_cpptoc.h" +#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h" +#include "libcef_dll/ctocpp/load_handler_ctocpp.h" +#include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefRenderProcessHandlerCToCpp::OnRenderThreadCreated( + CefRefPtr extra_info) { + if (CEF_MEMBER_MISSING(struct_, on_render_thread_created)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extra_info; type: refptr_diff + DCHECK(extra_info.get()); + if (!extra_info.get()) + return; + + // Execute + struct_->on_render_thread_created(struct_, + CefListValueCppToC::Wrap(extra_info)); +} + +void CefRenderProcessHandlerCToCpp::OnWebKitInitialized() { + if (CEF_MEMBER_MISSING(struct_, on_web_kit_initialized)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_web_kit_initialized(struct_); +} + +void CefRenderProcessHandlerCToCpp::OnBrowserCreated( + CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_browser_created)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_browser_created(struct_, + CefBrowserCppToC::Wrap(browser)); +} + +void CefRenderProcessHandlerCToCpp::OnBrowserDestroyed( + CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_browser_destroyed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_browser_destroyed(struct_, + CefBrowserCppToC::Wrap(browser)); +} + +CefRefPtr CefRenderProcessHandlerCToCpp::GetLoadHandler() { + if (CEF_MEMBER_MISSING(struct_, get_load_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_load_handler_t* _retval = struct_->get_load_handler(struct_); + + // Return type: refptr_same + return CefLoadHandlerCToCpp::Wrap(_retval); +} + +bool CefRenderProcessHandlerCToCpp::OnBeforeNavigation( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr request, NavigationType navigation_type, + bool is_redirect) { + if (CEF_MEMBER_MISSING(struct_, on_before_navigation)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return false; + + // Execute + int _retval = struct_->on_before_navigation(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefRequestCppToC::Wrap(request), + navigation_type, + is_redirect); + + // Return type: bool + return _retval?true:false; +} + +void CefRenderProcessHandlerCToCpp::OnContextCreated( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr context) { + if (CEF_MEMBER_MISSING(struct_, on_context_created)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: context; type: refptr_diff + DCHECK(context.get()); + if (!context.get()) + return; + + // Execute + struct_->on_context_created(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefV8ContextCppToC::Wrap(context)); +} + +void CefRenderProcessHandlerCToCpp::OnContextReleased( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr context) { + if (CEF_MEMBER_MISSING(struct_, on_context_released)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: context; type: refptr_diff + DCHECK(context.get()); + if (!context.get()) + return; + + // Execute + struct_->on_context_released(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefV8ContextCppToC::Wrap(context)); +} + +void CefRenderProcessHandlerCToCpp::OnUncaughtException( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr context, CefRefPtr exception, + CefRefPtr stackTrace) { + if (CEF_MEMBER_MISSING(struct_, on_uncaught_exception)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: context; type: refptr_diff + DCHECK(context.get()); + if (!context.get()) + return; + // Verify param: exception; type: refptr_diff + DCHECK(exception.get()); + if (!exception.get()) + return; + // Verify param: stackTrace; type: refptr_diff + DCHECK(stackTrace.get()); + if (!stackTrace.get()) + return; + + // Execute + struct_->on_uncaught_exception(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefV8ContextCppToC::Wrap(context), + CefV8ExceptionCppToC::Wrap(exception), + CefV8StackTraceCppToC::Wrap(stackTrace)); +} + +void CefRenderProcessHandlerCToCpp::OnFocusedNodeChanged( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr node) { + if (CEF_MEMBER_MISSING(struct_, on_focused_node_changed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Unverified params: frame, node + + // Execute + struct_->on_focused_node_changed(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefDOMNodeCppToC::Wrap(node)); +} + +bool CefRenderProcessHandlerCToCpp::OnProcessMessageReceived( + CefRefPtr browser, CefProcessId source_process, + CefRefPtr message) { + if (CEF_MEMBER_MISSING(struct_, on_process_message_received)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: message; type: refptr_diff + DCHECK(message.get()); + if (!message.get()) + return false; + + // Execute + int _retval = struct_->on_process_message_received(struct_, + CefBrowserCppToC::Wrap(browser), + source_process, + CefProcessMessageCppToC::Wrap(message)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.h b/libcef_dll/ctocpp/render_process_handler_ctocpp.h new file mode 100644 index 000000000..d6c4d32eb --- /dev/null +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.h @@ -0,0 +1,63 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_PROCESS_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RENDER_PROCESS_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_render_process_handler.h" +#include "include/capi/cef_render_process_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefRenderProcessHandlerCToCpp + : public CefCToCpp { + public: + explicit CefRenderProcessHandlerCToCpp(cef_render_process_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefRenderProcessHandlerCToCpp() {} + + // CefRenderProcessHandler methods + virtual void OnRenderThreadCreated( + CefRefPtr extra_info) OVERRIDE; + virtual void OnWebKitInitialized() OVERRIDE; + virtual void OnBrowserCreated(CefRefPtr browser) OVERRIDE; + virtual void OnBrowserDestroyed(CefRefPtr browser) OVERRIDE; + virtual CefRefPtr GetLoadHandler() OVERRIDE; + virtual bool OnBeforeNavigation(CefRefPtr browser, + CefRefPtr frame, CefRefPtr request, + NavigationType navigation_type, bool is_redirect) OVERRIDE; + virtual void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, CefRefPtr context) OVERRIDE; + virtual void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, CefRefPtr context) OVERRIDE; + virtual void OnUncaughtException(CefRefPtr browser, + CefRefPtr frame, CefRefPtr context, + CefRefPtr exception, + CefRefPtr stackTrace) OVERRIDE; + virtual void OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, CefRefPtr node) OVERRIDE; + virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RENDER_PROCESS_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_context_ctocpp.cc b/libcef_dll/ctocpp/request_context_ctocpp.cc new file mode 100644 index 000000000..a7bd7de01 --- /dev/null +++ b/libcef_dll/ctocpp/request_context_ctocpp.cc @@ -0,0 +1,96 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/request_context_handler_cpptoc.h" +#include "libcef_dll/ctocpp/request_context_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefRequestContext::GetGlobalContext() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_context_t* _retval = cef_request_context_get_global_context(); + + // Return type: refptr_same + return CefRequestContextCToCpp::Wrap(_retval); +} + +CefRefPtr CefRequestContext::CreateContext( + CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: handler + + // Execute + cef_request_context_t* _retval = cef_request_context_create_context( + CefRequestContextHandlerCppToC::Wrap(handler)); + + // Return type: refptr_same + return CefRequestContextCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefRequestContextCToCpp::IsSame(CefRefPtr other) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: other; type: refptr_same + DCHECK(other.get()); + if (!other.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefRequestContextCToCpp::Unwrap(other)); + + // Return type: bool + return _retval?true:false; +} + +bool CefRequestContextCToCpp::IsGlobal() { + if (CEF_MEMBER_MISSING(struct_, is_global)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_global(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefRequestContextCToCpp::GetHandler() { + if (CEF_MEMBER_MISSING(struct_, get_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_context_handler_t* _retval = struct_->get_handler(struct_); + + // Return type: refptr_diff + return CefRequestContextHandlerCppToC::Unwrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/request_context_ctocpp.h b/libcef_dll/ctocpp/request_context_ctocpp.h new file mode 100644 index 000000000..961150aa3 --- /dev/null +++ b/libcef_dll/ctocpp/request_context_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request_context.h" +#include "include/capi/cef_request_context_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefRequestContextCToCpp + : public CefCToCpp { + public: + explicit CefRequestContextCToCpp(cef_request_context_t* str) + : CefCToCpp(str) {} + virtual ~CefRequestContextCToCpp() {} + + // CefRequestContext methods + virtual bool IsSame(CefRefPtr other) OVERRIDE; + virtual bool IsGlobal() OVERRIDE; + virtual CefRefPtr GetHandler() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_context_handler_ctocpp.cc b/libcef_dll/ctocpp/request_context_handler_ctocpp.cc new file mode 100644 index 000000000..437366412 --- /dev/null +++ b/libcef_dll/ctocpp/request_context_handler_ctocpp.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" +#include "libcef_dll/ctocpp/request_context_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefRequestContextHandlerCToCpp::GetCookieManager() { + if (CEF_MEMBER_MISSING(struct_, get_cookie_manager)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_cookie_manager_t* _retval = struct_->get_cookie_manager(struct_); + + // Return type: refptr_diff + return CefCookieManagerCppToC::Unwrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/request_context_handler_ctocpp.h b/libcef_dll/ctocpp/request_context_handler_ctocpp.h new file mode 100644 index 000000000..099fdb1bd --- /dev/null +++ b/libcef_dll/ctocpp/request_context_handler_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request_context_handler.h" +#include "include/capi/cef_request_context_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefRequestContextHandlerCToCpp + : public CefCToCpp { + public: + explicit CefRequestContextHandlerCToCpp(cef_request_context_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefRequestContextHandlerCToCpp() {} + + // CefRequestContextHandler methods + virtual CefRefPtr GetCookieManager() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_ctocpp.cc b/libcef_dll/ctocpp/request_ctocpp.cc new file mode 100644 index 000000000..9e280c57a --- /dev/null +++ b/libcef_dll/ctocpp/request_ctocpp.cc @@ -0,0 +1,303 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/post_data_ctocpp.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefRequest::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_t* _retval = cef_request_create(); + + // Return type: refptr_same + return CefRequestCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefRequestCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefRequestCToCpp::GetURL() { + if (CEF_MEMBER_MISSING(struct_, get_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_url(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefRequestCToCpp::SetURL(const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, set_url)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->set_url(struct_, + url.GetStruct()); +} + +CefString CefRequestCToCpp::GetMethod() { + if (CEF_MEMBER_MISSING(struct_, get_method)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_method(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefRequestCToCpp::SetMethod(const CefString& method) { + if (CEF_MEMBER_MISSING(struct_, set_method)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: method; type: string_byref_const + DCHECK(!method.empty()); + if (method.empty()) + return; + + // Execute + struct_->set_method(struct_, + method.GetStruct()); +} + +CefRefPtr CefRequestCToCpp::GetPostData() { + if (CEF_MEMBER_MISSING(struct_, get_post_data)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_post_data_t* _retval = struct_->get_post_data(struct_); + + // Return type: refptr_same + return CefPostDataCToCpp::Wrap(_retval); +} + +void CefRequestCToCpp::SetPostData(CefRefPtr postData) { + if (CEF_MEMBER_MISSING(struct_, set_post_data)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: postData; type: refptr_same + DCHECK(postData.get()); + if (!postData.get()) + return; + + // Execute + struct_->set_post_data(struct_, + CefPostDataCToCpp::Unwrap(postData)); +} + +void CefRequestCToCpp::GetHeaderMap(HeaderMap& headerMap) { + if (CEF_MEMBER_MISSING(struct_, get_header_map)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: headerMap; type: string_map_multi_byref + cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc(); + DCHECK(headerMapMultimap); + if (headerMapMultimap) + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + struct_->get_header_map(struct_, + headerMapMultimap); + + // Restore param:headerMap; type: string_map_multi_byref + if (headerMapMultimap) { + headerMap.clear(); + transfer_string_multimap_contents(headerMapMultimap, headerMap); + cef_string_multimap_free(headerMapMultimap); + } +} + +void CefRequestCToCpp::SetHeaderMap(const HeaderMap& headerMap) { + if (CEF_MEMBER_MISSING(struct_, set_header_map)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: headerMap; type: string_map_multi_byref_const + cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc(); + DCHECK(headerMapMultimap); + if (headerMapMultimap) + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + struct_->set_header_map(struct_, + headerMapMultimap); + + // Restore param:headerMap; type: string_map_multi_byref_const + if (headerMapMultimap) + cef_string_multimap_free(headerMapMultimap); +} + +void CefRequestCToCpp::Set(const CefString& url, const CefString& method, + CefRefPtr postData, const HeaderMap& headerMap) { + if (CEF_MEMBER_MISSING(struct_, set)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + // Verify param: method; type: string_byref_const + DCHECK(!method.empty()); + if (method.empty()) + return; + // Unverified params: postData + + // Translate param: headerMap; type: string_map_multi_byref_const + cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc(); + DCHECK(headerMapMultimap); + if (headerMapMultimap) + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + struct_->set(struct_, + url.GetStruct(), + method.GetStruct(), + CefPostDataCToCpp::Unwrap(postData), + headerMapMultimap); + + // Restore param:headerMap; type: string_map_multi_byref_const + if (headerMapMultimap) + cef_string_multimap_free(headerMapMultimap); +} + +int CefRequestCToCpp::GetFlags() { + if (CEF_MEMBER_MISSING(struct_, get_flags)) + return UR_FLAG_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_flags(struct_); + + // Return type: simple + return _retval; +} + +void CefRequestCToCpp::SetFlags(int flags) { + if (CEF_MEMBER_MISSING(struct_, set_flags)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_flags(struct_, + flags); +} + +CefString CefRequestCToCpp::GetFirstPartyForCookies() { + if (CEF_MEMBER_MISSING(struct_, get_first_party_for_cookies)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_first_party_for_cookies(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefRequestCToCpp::SetFirstPartyForCookies(const CefString& url) { + if (CEF_MEMBER_MISSING(struct_, set_first_party_for_cookies)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Execute + struct_->set_first_party_for_cookies(struct_, + url.GetStruct()); +} + +CefRequest::ResourceType CefRequestCToCpp::GetResourceType() { + if (CEF_MEMBER_MISSING(struct_, get_resource_type)) + return RT_SUB_RESOURCE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_resource_type_t _retval = struct_->get_resource_type(struct_); + + // Return type: simple + return _retval; +} + +CefRequest::TransitionType CefRequestCToCpp::GetTransitionType() { + if (CEF_MEMBER_MISSING(struct_, get_transition_type)) + return TT_EXPLICIT; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_transition_type_t _retval = struct_->get_transition_type(struct_); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/request_ctocpp.h b/libcef_dll/ctocpp/request_ctocpp.h new file mode 100644 index 000000000..574ac7f4c --- /dev/null +++ b/libcef_dll/ctocpp/request_ctocpp.h @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_REQUEST_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_request.h" +#include "include/capi/cef_request_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefRequestCToCpp + : public CefCToCpp { + public: + explicit CefRequestCToCpp(cef_request_t* str) + : CefCToCpp(str) {} + virtual ~CefRequestCToCpp() {} + + // CefRequest methods + virtual bool IsReadOnly() OVERRIDE; + virtual CefString GetURL() OVERRIDE; + virtual void SetURL(const CefString& url) OVERRIDE; + virtual CefString GetMethod() OVERRIDE; + virtual void SetMethod(const CefString& method) OVERRIDE; + virtual CefRefPtr GetPostData() OVERRIDE; + virtual void SetPostData(CefRefPtr postData) OVERRIDE; + virtual void GetHeaderMap(HeaderMap& headerMap) OVERRIDE; + virtual void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE; + virtual void Set(const CefString& url, const CefString& method, + CefRefPtr postData, const HeaderMap& headerMap) OVERRIDE; + virtual int GetFlags() OVERRIDE; + virtual void SetFlags(int flags) OVERRIDE; + virtual CefString GetFirstPartyForCookies() OVERRIDE; + virtual void SetFirstPartyForCookies(const CefString& url) OVERRIDE; + virtual ResourceType GetResourceType() OVERRIDE; + virtual TransitionType GetTransitionType() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_REQUEST_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_handler_ctocpp.cc b/libcef_dll/ctocpp/request_handler_ctocpp.cc new file mode 100644 index 000000000..dcea16872 --- /dev/null +++ b/libcef_dll/ctocpp/request_handler_ctocpp.cc @@ -0,0 +1,356 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h" +#include "libcef_dll/cpptoc/auth_callback_cpptoc.h" +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/quota_callback_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h" +#include "libcef_dll/ctocpp/request_handler_ctocpp.h" +#include "libcef_dll/ctocpp/resource_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefRequestHandlerCToCpp::OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, CefRefPtr request, + bool is_redirect) { + if (CEF_MEMBER_MISSING(struct_, on_before_browse)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return false; + + // Execute + int _retval = struct_->on_before_browse(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefRequestCppToC::Wrap(request), + is_redirect); + + // Return type: bool + return _retval?true:false; +} + +bool CefRequestHandlerCToCpp::OnBeforeResourceLoad( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr request) { + if (CEF_MEMBER_MISSING(struct_, on_before_resource_load)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return false; + + // Execute + int _retval = struct_->on_before_resource_load(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefRequestCppToC::Wrap(request)); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefRequestHandlerCToCpp::GetResourceHandler( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr request) { + if (CEF_MEMBER_MISSING(struct_, get_resource_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return NULL; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return NULL; + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return NULL; + + // Execute + cef_resource_handler_t* _retval = struct_->get_resource_handler(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + CefRequestCppToC::Wrap(request)); + + // Return type: refptr_same + return CefResourceHandlerCToCpp::Wrap(_retval); +} + +void CefRequestHandlerCToCpp::OnResourceRedirect(CefRefPtr browser, + CefRefPtr frame, const CefString& old_url, CefString& new_url) { + if (CEF_MEMBER_MISSING(struct_, on_resource_redirect)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; + // Verify param: old_url; type: string_byref_const + DCHECK(!old_url.empty()); + if (old_url.empty()) + return; + + // Execute + struct_->on_resource_redirect(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + old_url.GetStruct(), + new_url.GetWritableStruct()); +} + +bool CefRequestHandlerCToCpp::GetAuthCredentials(CefRefPtr browser, + CefRefPtr frame, bool isProxy, const CefString& host, int port, + const CefString& realm, const CefString& scheme, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, get_auth_credentials)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; + // Verify param: host; type: string_byref_const + DCHECK(!host.empty()); + if (host.empty()) + return false; + // Verify param: scheme; type: string_byref_const + DCHECK(!scheme.empty()); + if (scheme.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: realm + + // Execute + int _retval = struct_->get_auth_credentials(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + isProxy, + host.GetStruct(), + port, + realm.GetStruct(), + scheme.GetStruct(), + CefAuthCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +bool CefRequestHandlerCToCpp::OnQuotaRequest(CefRefPtr browser, + const CefString& origin_url, int64 new_size, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_quota_request)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: origin_url; type: string_byref_const + DCHECK(!origin_url.empty()); + if (origin_url.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->on_quota_request(struct_, + CefBrowserCppToC::Wrap(browser), + origin_url.GetStruct(), + new_size, + CefQuotaCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefRequestHandlerCToCpp::OnProtocolExecution(CefRefPtr browser, + const CefString& url, bool& allow_os_execution) { + if (CEF_MEMBER_MISSING(struct_, on_protocol_execution)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return; + + // Translate param: allow_os_execution; type: bool_byref + int allow_os_executionInt = allow_os_execution; + + // Execute + struct_->on_protocol_execution(struct_, + CefBrowserCppToC::Wrap(browser), + url.GetStruct(), + &allow_os_executionInt); + + // Restore param:allow_os_execution; type: bool_byref + allow_os_execution = allow_os_executionInt?true:false; +} + +bool CefRequestHandlerCToCpp::OnCertificateError(cef_errorcode_t cert_error, + const CefString& request_url, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_certificate_error)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request_url; type: string_byref_const + DCHECK(!request_url.empty()); + if (request_url.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->on_certificate_error(struct_, + cert_error, + request_url.GetStruct(), + CefAllowCertificateErrorCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +bool CefRequestHandlerCToCpp::OnBeforePluginLoad(CefRefPtr browser, + const CefString& url, const CefString& policy_url, + CefRefPtr info) { + if (CEF_MEMBER_MISSING(struct_, on_before_plugin_load)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: info; type: refptr_diff + DCHECK(info.get()); + if (!info.get()) + return false; + // Unverified params: url, policy_url + + // Execute + int _retval = struct_->on_before_plugin_load(struct_, + CefBrowserCppToC::Wrap(browser), + url.GetStruct(), + policy_url.GetStruct(), + CefWebPluginInfoCppToC::Wrap(info)); + + // Return type: bool + return _retval?true:false; +} + +void CefRequestHandlerCToCpp::OnPluginCrashed(CefRefPtr browser, + const CefString& plugin_path) { + if (CEF_MEMBER_MISSING(struct_, on_plugin_crashed)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Verify param: plugin_path; type: string_byref_const + DCHECK(!plugin_path.empty()); + if (plugin_path.empty()) + return; + + // Execute + struct_->on_plugin_crashed(struct_, + CefBrowserCppToC::Wrap(browser), + plugin_path.GetStruct()); +} + +void CefRequestHandlerCToCpp::OnRenderProcessTerminated( + CefRefPtr browser, TerminationStatus status) { + if (CEF_MEMBER_MISSING(struct_, on_render_process_terminated)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_render_process_terminated(struct_, + CefBrowserCppToC::Wrap(browser), + status); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/request_handler_ctocpp.h b/libcef_dll/ctocpp/request_handler_ctocpp.h new file mode 100644 index 000000000..b30ecf267 --- /dev/null +++ b/libcef_dll/ctocpp/request_handler_ctocpp.h @@ -0,0 +1,71 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_request_handler.h" +#include "include/capi/cef_request_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefRequestHandlerCToCpp + : public CefCToCpp { + public: + explicit CefRequestHandlerCToCpp(cef_request_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefRequestHandlerCToCpp() {} + + // CefRequestHandler methods + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, CefRefPtr request, + bool is_redirect) OVERRIDE; + virtual bool OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, CefRefPtr request) OVERRIDE; + virtual CefRefPtr GetResourceHandler( + CefRefPtr browser, CefRefPtr frame, + CefRefPtr request) OVERRIDE; + virtual void OnResourceRedirect(CefRefPtr browser, + CefRefPtr frame, const CefString& old_url, + CefString& new_url) OVERRIDE; + virtual bool GetAuthCredentials(CefRefPtr browser, + CefRefPtr frame, bool isProxy, const CefString& host, int port, + const CefString& realm, const CefString& scheme, + CefRefPtr callback) OVERRIDE; + virtual bool OnQuotaRequest(CefRefPtr browser, + const CefString& origin_url, int64 new_size, + CefRefPtr callback) OVERRIDE; + virtual void OnProtocolExecution(CefRefPtr browser, + const CefString& url, bool& allow_os_execution) OVERRIDE; + virtual bool OnCertificateError(cef_errorcode_t cert_error, + const CefString& request_url, + CefRefPtr callback) OVERRIDE; + virtual bool OnBeforePluginLoad(CefRefPtr browser, + const CefString& url, const CefString& policy_url, + CefRefPtr info) OVERRIDE; + virtual void OnPluginCrashed(CefRefPtr browser, + const CefString& plugin_path) OVERRIDE; + virtual void OnRenderProcessTerminated(CefRefPtr browser, + TerminationStatus status) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc new file mode 100644 index 000000000..fb6e31584 --- /dev/null +++ b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefResourceBundleHandlerCToCpp::GetLocalizedString(int message_id, + CefString& string) { + if (CEF_MEMBER_MISSING(struct_, get_localized_string)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_localized_string(struct_, + message_id, + string.GetWritableStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefResourceBundleHandlerCToCpp::GetDataResource(int resource_id, + void*& data, size_t& data_size) { + if (CEF_MEMBER_MISSING(struct_, get_data_resource)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_data_resource(struct_, + resource_id, + &data, + &data_size); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h new file mode 100644 index 000000000..bbe56638d --- /dev/null +++ b/libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_resource_bundle_handler.h" +#include "include/capi/cef_resource_bundle_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefResourceBundleHandlerCToCpp + : public CefCToCpp { + public: + explicit CefResourceBundleHandlerCToCpp(cef_resource_bundle_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefResourceBundleHandlerCToCpp() {} + + // CefResourceBundleHandler methods + virtual bool GetLocalizedString(int message_id, CefString& string) OVERRIDE; + virtual bool GetDataResource(int resource_id, void*& data, + size_t& data_size) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RESOURCE_BUNDLE_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/resource_handler_ctocpp.cc b/libcef_dll/ctocpp/resource_handler_ctocpp.cc new file mode 100644 index 000000000..8920a782a --- /dev/null +++ b/libcef_dll/ctocpp/resource_handler_ctocpp.cc @@ -0,0 +1,136 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/callback_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/response_cpptoc.h" +#include "libcef_dll/ctocpp/resource_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefResourceHandlerCToCpp::ProcessRequest(CefRefPtr request, + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, process_request)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->process_request(struct_, + CefRequestCppToC::Wrap(request), + CefCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefResourceHandlerCToCpp::GetResponseHeaders( + CefRefPtr response, int64& response_length, + CefString& redirectUrl) { + if (CEF_MEMBER_MISSING(struct_, get_response_headers)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: response; type: refptr_diff + DCHECK(response.get()); + if (!response.get()) + return; + + // Execute + struct_->get_response_headers(struct_, + CefResponseCppToC::Wrap(response), + &response_length, + redirectUrl.GetWritableStruct()); +} + +bool CefResourceHandlerCToCpp::ReadResponse(void* data_out, int bytes_to_read, + int& bytes_read, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, read_response)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: data_out; type: simple_byaddr + DCHECK(data_out); + if (!data_out) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = struct_->read_response(struct_, + data_out, + bytes_to_read, + &bytes_read, + CefCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +bool CefResourceHandlerCToCpp::CanGetCookie(const CefCookie& cookie) { + if (CEF_MEMBER_MISSING(struct_, can_get_cookie)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_get_cookie(struct_, + &cookie); + + // Return type: bool + return _retval?true:false; +} + +bool CefResourceHandlerCToCpp::CanSetCookie(const CefCookie& cookie) { + if (CEF_MEMBER_MISSING(struct_, can_set_cookie)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->can_set_cookie(struct_, + &cookie); + + // Return type: bool + return _retval?true:false; +} + +void CefResourceHandlerCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/resource_handler_ctocpp.h b/libcef_dll/ctocpp/resource_handler_ctocpp.h new file mode 100644 index 000000000..e0b7dbaaf --- /dev/null +++ b/libcef_dll/ctocpp/resource_handler_ctocpp.h @@ -0,0 +1,50 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RESOURCE_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RESOURCE_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_resource_handler.h" +#include "include/capi/cef_resource_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefResourceHandlerCToCpp + : public CefCToCpp { + public: + explicit CefResourceHandlerCToCpp(cef_resource_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefResourceHandlerCToCpp() {} + + // CefResourceHandler methods + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) OVERRIDE; + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, CefString& redirectUrl) OVERRIDE; + virtual bool ReadResponse(void* data_out, int bytes_to_read, int& bytes_read, + CefRefPtr callback) OVERRIDE; + virtual bool CanGetCookie(const CefCookie& cookie) OVERRIDE; + virtual bool CanSetCookie(const CefCookie& cookie) OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RESOURCE_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/response_ctocpp.cc b/libcef_dll/ctocpp/response_ctocpp.cc new file mode 100644 index 000000000..6a89c1929 --- /dev/null +++ b/libcef_dll/ctocpp/response_ctocpp.cc @@ -0,0 +1,202 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/response_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefResponse::Create() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_response_t* _retval = cef_response_create(); + + // Return type: refptr_same + return CefResponseCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefResponseCToCpp::IsReadOnly() { + if (CEF_MEMBER_MISSING(struct_, is_read_only)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_read_only(struct_); + + // Return type: bool + return _retval?true:false; +} + +int CefResponseCToCpp::GetStatus() { + if (CEF_MEMBER_MISSING(struct_, get_status)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_status(struct_); + + // Return type: simple + return _retval; +} + +void CefResponseCToCpp::SetStatus(int status) { + if (CEF_MEMBER_MISSING(struct_, set_status)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->set_status(struct_, + status); +} + +CefString CefResponseCToCpp::GetStatusText() { + if (CEF_MEMBER_MISSING(struct_, get_status_text)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_status_text(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefResponseCToCpp::SetStatusText(const CefString& statusText) { + if (CEF_MEMBER_MISSING(struct_, set_status_text)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: statusText; type: string_byref_const + DCHECK(!statusText.empty()); + if (statusText.empty()) + return; + + // Execute + struct_->set_status_text(struct_, + statusText.GetStruct()); +} + +CefString CefResponseCToCpp::GetMimeType() { + if (CEF_MEMBER_MISSING(struct_, get_mime_type)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_mime_type(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefResponseCToCpp::SetMimeType(const CefString& mimeType) { + if (CEF_MEMBER_MISSING(struct_, set_mime_type)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: mimeType; type: string_byref_const + DCHECK(!mimeType.empty()); + if (mimeType.empty()) + return; + + // Execute + struct_->set_mime_type(struct_, + mimeType.GetStruct()); +} + +CefString CefResponseCToCpp::GetHeader(const CefString& name) { + if (CEF_MEMBER_MISSING(struct_, get_header)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_header(struct_, + name.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +void CefResponseCToCpp::GetHeaderMap(HeaderMap& headerMap) { + if (CEF_MEMBER_MISSING(struct_, get_header_map)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: headerMap; type: string_map_multi_byref + cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc(); + DCHECK(headerMapMultimap); + if (headerMapMultimap) + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + struct_->get_header_map(struct_, + headerMapMultimap); + + // Restore param:headerMap; type: string_map_multi_byref + if (headerMapMultimap) { + headerMap.clear(); + transfer_string_multimap_contents(headerMapMultimap, headerMap); + cef_string_multimap_free(headerMapMultimap); + } +} + +void CefResponseCToCpp::SetHeaderMap(const HeaderMap& headerMap) { + if (CEF_MEMBER_MISSING(struct_, set_header_map)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: headerMap; type: string_map_multi_byref_const + cef_string_multimap_t headerMapMultimap = cef_string_multimap_alloc(); + DCHECK(headerMapMultimap); + if (headerMapMultimap) + transfer_string_multimap_contents(headerMap, headerMapMultimap); + + // Execute + struct_->set_header_map(struct_, + headerMapMultimap); + + // Restore param:headerMap; type: string_map_multi_byref_const + if (headerMapMultimap) + cef_string_multimap_free(headerMapMultimap); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/response_ctocpp.h b/libcef_dll/ctocpp/response_ctocpp.h new file mode 100644 index 000000000..8dd92d519 --- /dev/null +++ b/libcef_dll/ctocpp/response_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_response.h" +#include "include/capi/cef_response_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefResponseCToCpp + : public CefCToCpp { + public: + explicit CefResponseCToCpp(cef_response_t* str) + : CefCToCpp(str) {} + virtual ~CefResponseCToCpp() {} + + // CefResponse methods + virtual bool IsReadOnly() OVERRIDE; + virtual int GetStatus() OVERRIDE; + virtual void SetStatus(int status) OVERRIDE; + virtual CefString GetStatusText() OVERRIDE; + virtual void SetStatusText(const CefString& statusText) OVERRIDE; + virtual CefString GetMimeType() OVERRIDE; + virtual void SetMimeType(const CefString& mimeType) OVERRIDE; + virtual CefString GetHeader(const CefString& name) OVERRIDE; + virtual void GetHeaderMap(HeaderMap& headerMap) OVERRIDE; + virtual void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc new file mode 100644 index 000000000..69b4f9063 --- /dev/null +++ b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc @@ -0,0 +1,54 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_host_cpptoc.h" +#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefRunFileDialogCallbackCToCpp::OnFileDialogDismissed( + CefRefPtr browser_host, + const std::vector& file_paths) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser_host; type: refptr_diff + DCHECK(browser_host.get()); + if (!browser_host.get()) + return; + + // Translate param: file_paths; type: string_vec_byref_const + cef_string_list_t file_pathsList = cef_string_list_alloc(); + DCHECK(file_pathsList); + if (file_pathsList) + transfer_string_list_contents(file_paths, file_pathsList); + + // Execute + struct_->cont(struct_, + CefBrowserHostCppToC::Wrap(browser_host), + file_pathsList); + + // Restore param:file_paths; type: string_vec_byref_const + if (file_pathsList) + cef_string_list_free(file_pathsList); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h new file mode 100644 index 000000000..85e947fab --- /dev/null +++ b/libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include +#include "include/cef_browser.h" +#include "include/capi/cef_browser_capi.h" +#include "include/cef_client.h" +#include "include/capi/cef_client_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefRunFileDialogCallbackCToCpp + : public CefCToCpp { + public: + explicit CefRunFileDialogCallbackCToCpp(cef_run_file_dialog_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefRunFileDialogCallbackCToCpp() {} + + // CefRunFileDialogCallback methods + virtual void OnFileDialogDismissed(CefRefPtr browser_host, + const std::vector& file_paths) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_RUN_FILE_DIALOG_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc new file mode 100644 index 000000000..19e54acbf --- /dev/null +++ b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc @@ -0,0 +1,56 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/ctocpp/resource_handler_ctocpp.h" +#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefSchemeHandlerFactoryCToCpp::Create( + CefRefPtr browser, CefRefPtr frame, + const CefString& scheme_name, CefRefPtr request) { + if (CEF_MEMBER_MISSING(struct_, create)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: scheme_name; type: string_byref_const + DCHECK(!scheme_name.empty()); + if (scheme_name.empty()) + return NULL; + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return NULL; + // Unverified params: browser, frame + + // Execute + cef_resource_handler_t* _retval = struct_->create(struct_, + CefBrowserCppToC::Wrap(browser), + CefFrameCppToC::Wrap(frame), + scheme_name.GetStruct(), + CefRequestCppToC::Wrap(request)); + + // Return type: refptr_same + return CefResourceHandlerCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h new file mode 100644 index 000000000..a7ef13e62 --- /dev/null +++ b/libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_SCHEME_HANDLER_FACTORY_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_SCHEME_HANDLER_FACTORY_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefSchemeHandlerFactoryCToCpp + : public CefCToCpp { + public: + explicit CefSchemeHandlerFactoryCToCpp(cef_scheme_handler_factory_t* str) + : CefCToCpp(str) {} + virtual ~CefSchemeHandlerFactoryCToCpp() {} + + // CefSchemeHandlerFactory methods + virtual CefRefPtr Create(CefRefPtr browser, + CefRefPtr frame, const CefString& scheme_name, + CefRefPtr request) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_SCHEME_HANDLER_FACTORY_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc b/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc new file mode 100644 index 000000000..6416cadf4 --- /dev/null +++ b/libcef_dll/ctocpp/scheme_registrar_ctocpp.cc @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefSchemeRegistrarCToCpp::AddCustomScheme(const CefString& scheme_name, + bool is_standard, bool is_local, bool is_display_isolated) { + if (CEF_MEMBER_MISSING(struct_, add_custom_scheme)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: scheme_name; type: string_byref_const + DCHECK(!scheme_name.empty()); + if (scheme_name.empty()) + return false; + + // Execute + int _retval = struct_->add_custom_scheme(struct_, + scheme_name.GetStruct(), + is_standard, + is_local, + is_display_isolated); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/scheme_registrar_ctocpp.h b/libcef_dll/ctocpp/scheme_registrar_ctocpp.h new file mode 100644 index 000000000..14658e135 --- /dev/null +++ b/libcef_dll/ctocpp/scheme_registrar_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefSchemeRegistrarCToCpp + : public CefCToCpp { + public: + explicit CefSchemeRegistrarCToCpp(cef_scheme_registrar_t* str) + : CefCToCpp(str) {} + virtual ~CefSchemeRegistrarCToCpp() {} + + // CefSchemeRegistrar methods + virtual bool AddCustomScheme(const CefString& scheme_name, bool is_standard, + bool is_local, bool is_display_isolated) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_SCHEME_REGISTRAR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/stream_reader_ctocpp.cc b/libcef_dll/ctocpp/stream_reader_ctocpp.cc new file mode 100644 index 000000000..62553adbc --- /dev/null +++ b/libcef_dll/ctocpp/stream_reader_ctocpp.cc @@ -0,0 +1,154 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/read_handler_cpptoc.h" +#include "libcef_dll/ctocpp/stream_reader_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefStreamReader::CreateForFile( + const CefString& fileName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(!fileName.empty()); + if (fileName.empty()) + return NULL; + + // Execute + cef_stream_reader_t* _retval = cef_stream_reader_create_for_file( + fileName.GetStruct()); + + // Return type: refptr_same + return CefStreamReaderCToCpp::Wrap(_retval); +} + +CefRefPtr CefStreamReader::CreateForData(void* data, + size_t size) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return NULL; + + // Execute + cef_stream_reader_t* _retval = cef_stream_reader_create_for_data( + data, + size); + + // Return type: refptr_same + return CefStreamReaderCToCpp::Wrap(_retval); +} + +CefRefPtr CefStreamReader::CreateForHandler( + CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: handler; type: refptr_diff + DCHECK(handler.get()); + if (!handler.get()) + return NULL; + + // Execute + cef_stream_reader_t* _retval = cef_stream_reader_create_for_handler( + CefReadHandlerCppToC::Wrap(handler)); + + // Return type: refptr_same + return CefStreamReaderCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +size_t CefStreamReaderCToCpp::Read(void* ptr, size_t size, size_t n) { + if (CEF_MEMBER_MISSING(struct_, read)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = struct_->read(struct_, + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CefStreamReaderCToCpp::Seek(int64 offset, int whence) { + if (CEF_MEMBER_MISSING(struct_, seek)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->seek(struct_, + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CefStreamReaderCToCpp::Tell() { + if (CEF_MEMBER_MISSING(struct_, tell)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->tell(struct_); + + // Return type: simple + return _retval; +} + +int CefStreamReaderCToCpp::Eof() { + if (CEF_MEMBER_MISSING(struct_, eof)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->eof(struct_); + + // Return type: simple + return _retval; +} + +bool CefStreamReaderCToCpp::MayBlock() { + if (CEF_MEMBER_MISSING(struct_, may_block)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->may_block(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/stream_reader_ctocpp.h b/libcef_dll/ctocpp/stream_reader_ctocpp.h new file mode 100644 index 000000000..7b3f0b790 --- /dev/null +++ b/libcef_dll/ctocpp/stream_reader_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_STREAM_READER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_STREAM_READER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefStreamReaderCToCpp + : public CefCToCpp { + public: + explicit CefStreamReaderCToCpp(cef_stream_reader_t* str) + : CefCToCpp( + str) {} + virtual ~CefStreamReaderCToCpp() {} + + // CefStreamReader methods + virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Eof() OVERRIDE; + virtual bool MayBlock() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_STREAM_READER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/stream_writer_ctocpp.cc b/libcef_dll/ctocpp/stream_writer_ctocpp.cc new file mode 100644 index 000000000..0ae76e394 --- /dev/null +++ b/libcef_dll/ctocpp/stream_writer_ctocpp.cc @@ -0,0 +1,136 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/write_handler_cpptoc.h" +#include "libcef_dll/ctocpp/stream_writer_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefStreamWriter::CreateForFile( + const CefString& fileName) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(!fileName.empty()); + if (fileName.empty()) + return NULL; + + // Execute + cef_stream_writer_t* _retval = cef_stream_writer_create_for_file( + fileName.GetStruct()); + + // Return type: refptr_same + return CefStreamWriterCToCpp::Wrap(_retval); +} + +CefRefPtr CefStreamWriter::CreateForHandler( + CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: handler; type: refptr_diff + DCHECK(handler.get()); + if (!handler.get()) + return NULL; + + // Execute + cef_stream_writer_t* _retval = cef_stream_writer_create_for_handler( + CefWriteHandlerCppToC::Wrap(handler)); + + // Return type: refptr_same + return CefStreamWriterCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +size_t CefStreamWriterCToCpp::Write(const void* ptr, size_t size, size_t n) { + if (CEF_MEMBER_MISSING(struct_, write)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = struct_->write(struct_, + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CefStreamWriterCToCpp::Seek(int64 offset, int whence) { + if (CEF_MEMBER_MISSING(struct_, seek)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->seek(struct_, + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CefStreamWriterCToCpp::Tell() { + if (CEF_MEMBER_MISSING(struct_, tell)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->tell(struct_); + + // Return type: simple + return _retval; +} + +int CefStreamWriterCToCpp::Flush() { + if (CEF_MEMBER_MISSING(struct_, flush)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->flush(struct_); + + // Return type: simple + return _retval; +} + +bool CefStreamWriterCToCpp::MayBlock() { + if (CEF_MEMBER_MISSING(struct_, may_block)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->may_block(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/stream_writer_ctocpp.h b/libcef_dll/ctocpp/stream_writer_ctocpp.h new file mode 100644 index 000000000..6e1b5d779 --- /dev/null +++ b/libcef_dll/ctocpp/stream_writer_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_STREAM_WRITER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_STREAM_WRITER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefStreamWriterCToCpp + : public CefCToCpp { + public: + explicit CefStreamWriterCToCpp(cef_stream_writer_t* str) + : CefCToCpp( + str) {} + virtual ~CefStreamWriterCToCpp() {} + + // CefStreamWriter methods + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Flush() OVERRIDE; + virtual bool MayBlock() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_STREAM_WRITER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/string_visitor_ctocpp.cc b/libcef_dll/ctocpp/string_visitor_ctocpp.cc new file mode 100644 index 000000000..d48f03c33 --- /dev/null +++ b/libcef_dll/ctocpp/string_visitor_ctocpp.cc @@ -0,0 +1,36 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/string_visitor_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefStringVisitorCToCpp::Visit(const CefString& string) { + if (CEF_MEMBER_MISSING(struct_, visit)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: string + + // Execute + struct_->visit(struct_, + string.GetStruct()); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/string_visitor_ctocpp.h b/libcef_dll/ctocpp/string_visitor_ctocpp.h new file mode 100644 index 000000000..b6aaf2ecc --- /dev/null +++ b/libcef_dll/ctocpp/string_visitor_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_STRING_VISITOR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_STRING_VISITOR_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_string_visitor.h" +#include "include/capi/cef_string_visitor_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefStringVisitorCToCpp + : public CefCToCpp { + public: + explicit CefStringVisitorCToCpp(cef_string_visitor_t* str) + : CefCToCpp(str) {} + virtual ~CefStringVisitorCToCpp() {} + + // CefStringVisitor methods + virtual void Visit(const CefString& string) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_STRING_VISITOR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/task_ctocpp.cc b/libcef_dll/ctocpp/task_ctocpp.cc new file mode 100644 index 000000000..fd4a9a5c3 --- /dev/null +++ b/libcef_dll/ctocpp/task_ctocpp.cc @@ -0,0 +1,33 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/task_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefTaskCToCpp::Execute() { + if (CEF_MEMBER_MISSING(struct_, execute)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->execute(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/task_ctocpp.h b/libcef_dll/ctocpp/task_ctocpp.h new file mode 100644 index 000000000..dc8096bf7 --- /dev/null +++ b/libcef_dll/ctocpp/task_ctocpp.h @@ -0,0 +1,40 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_TASK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_TASK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefTaskCToCpp + : public CefCToCpp { + public: + explicit CefTaskCToCpp(cef_task_t* str) + : CefCToCpp(str) {} + virtual ~CefTaskCToCpp() {} + + // CefTask methods + virtual void Execute() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_TASK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/task_runner_ctocpp.cc b/libcef_dll/ctocpp/task_runner_ctocpp.cc new file mode 100644 index 000000000..f7288f914 --- /dev/null +++ b/libcef_dll/ctocpp/task_runner_ctocpp.cc @@ -0,0 +1,134 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/task_cpptoc.h" +#include "libcef_dll/ctocpp/task_runner_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefTaskRunner::GetForCurrentThread() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_task_runner_t* _retval = cef_task_runner_get_for_current_thread(); + + // Return type: refptr_same + return CefTaskRunnerCToCpp::Wrap(_retval); +} + +CefRefPtr CefTaskRunner::GetForThread(CefThreadId threadId) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_task_runner_t* _retval = cef_task_runner_get_for_thread( + threadId); + + // Return type: refptr_same + return CefTaskRunnerCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefTaskRunnerCToCpp::IsSame(CefRefPtr that) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: that; type: refptr_same + DCHECK(that.get()); + if (!that.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefTaskRunnerCToCpp::Unwrap(that)); + + // Return type: bool + return _retval?true:false; +} + +bool CefTaskRunnerCToCpp::BelongsToCurrentThread() { + if (CEF_MEMBER_MISSING(struct_, belongs_to_current_thread)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->belongs_to_current_thread(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefTaskRunnerCToCpp::BelongsToThread(CefThreadId threadId) { + if (CEF_MEMBER_MISSING(struct_, belongs_to_thread)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->belongs_to_thread(struct_, + threadId); + + // Return type: bool + return _retval?true:false; +} + +bool CefTaskRunnerCToCpp::PostTask(CefRefPtr task) { + if (CEF_MEMBER_MISSING(struct_, post_task)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task.get()); + if (!task.get()) + return false; + + // Execute + int _retval = struct_->post_task(struct_, + CefTaskCppToC::Wrap(task)); + + // Return type: bool + return _retval?true:false; +} + +bool CefTaskRunnerCToCpp::PostDelayedTask(CefRefPtr task, + int64 delay_ms) { + if (CEF_MEMBER_MISSING(struct_, post_delayed_task)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task.get()); + if (!task.get()) + return false; + + // Execute + int _retval = struct_->post_delayed_task(struct_, + CefTaskCppToC::Wrap(task), + delay_ms); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/task_runner_ctocpp.h b/libcef_dll/ctocpp/task_runner_ctocpp.h new file mode 100644 index 000000000..39672c412 --- /dev/null +++ b/libcef_dll/ctocpp/task_runner_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefTaskRunnerCToCpp + : public CefCToCpp { + public: + explicit CefTaskRunnerCToCpp(cef_task_runner_t* str) + : CefCToCpp(str) {} + virtual ~CefTaskRunnerCToCpp() {} + + // CefTaskRunner methods + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool BelongsToCurrentThread() OVERRIDE; + virtual bool BelongsToThread(CefThreadId threadId) OVERRIDE; + virtual bool PostTask(CefRefPtr task) OVERRIDE; + virtual bool PostDelayedTask(CefRefPtr task, + int64 delay_ms) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc new file mode 100644 index 000000000..8e721db6a --- /dev/null +++ b/libcef_dll/ctocpp/urlrequest_client_ctocpp.cc @@ -0,0 +1,138 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/auth_callback_cpptoc.h" +#include "libcef_dll/cpptoc/urlrequest_cpptoc.h" +#include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefURLRequestClientCToCpp::OnRequestComplete( + CefRefPtr request) { + if (CEF_MEMBER_MISSING(struct_, on_request_complete)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return; + + // Execute + struct_->on_request_complete(struct_, + CefURLRequestCppToC::Wrap(request)); +} + +void CefURLRequestClientCToCpp::OnUploadProgress( + CefRefPtr request, uint64 current, uint64 total) { + if (CEF_MEMBER_MISSING(struct_, on_upload_progress)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return; + + // Execute + struct_->on_upload_progress(struct_, + CefURLRequestCppToC::Wrap(request), + current, + total); +} + +void CefURLRequestClientCToCpp::OnDownloadProgress( + CefRefPtr request, uint64 current, uint64 total) { + if (CEF_MEMBER_MISSING(struct_, on_download_progress)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return; + + // Execute + struct_->on_download_progress(struct_, + CefURLRequestCppToC::Wrap(request), + current, + total); +} + +void CefURLRequestClientCToCpp::OnDownloadData(CefRefPtr request, + const void* data, size_t data_length) { + if (CEF_MEMBER_MISSING(struct_, on_download_data)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_diff + DCHECK(request.get()); + if (!request.get()) + return; + // Verify param: data; type: simple_byaddr + DCHECK(data); + if (!data) + return; + + // Execute + struct_->on_download_data(struct_, + CefURLRequestCppToC::Wrap(request), + data, + data_length); +} + +bool CefURLRequestClientCToCpp::GetAuthCredentials(bool isProxy, + const CefString& host, int port, const CefString& realm, + const CefString& scheme, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, get_auth_credentials)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: host; type: string_byref_const + DCHECK(!host.empty()); + if (host.empty()) + return false; + // Verify param: scheme; type: string_byref_const + DCHECK(!scheme.empty()); + if (scheme.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: realm + + // Execute + int _retval = struct_->get_auth_credentials(struct_, + isProxy, + host.GetStruct(), + port, + realm.GetStruct(), + scheme.GetStruct(), + CefAuthCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/urlrequest_client_ctocpp.h b/libcef_dll/ctocpp/urlrequest_client_ctocpp.h new file mode 100644 index 000000000..0f6ba9c89 --- /dev/null +++ b/libcef_dll/ctocpp/urlrequest_client_ctocpp.h @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CLIENT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CLIENT_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_urlrequest.h" +#include "include/capi/cef_urlrequest_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefURLRequestClientCToCpp + : public CefCToCpp { + public: + explicit CefURLRequestClientCToCpp(cef_urlrequest_client_t* str) + : CefCToCpp(str) {} + virtual ~CefURLRequestClientCToCpp() {} + + // CefURLRequestClient methods + virtual void OnRequestComplete(CefRefPtr request) OVERRIDE; + virtual void OnUploadProgress(CefRefPtr request, + uint64 current, uint64 total) OVERRIDE; + virtual void OnDownloadProgress(CefRefPtr request, + uint64 current, uint64 total) OVERRIDE; + virtual void OnDownloadData(CefRefPtr request, + const void* data, size_t data_length) OVERRIDE; + virtual bool GetAuthCredentials(bool isProxy, const CefString& host, int port, + const CefString& realm, const CefString& scheme, + CefRefPtr callback) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CLIENT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_ctocpp.cc new file mode 100644 index 000000000..709996847 --- /dev/null +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.cc @@ -0,0 +1,126 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" +#include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/response_ctocpp.h" +#include "libcef_dll/ctocpp/urlrequest_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefURLRequest::Create(CefRefPtr request, + CefRefPtr client) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: request; type: refptr_same + DCHECK(request.get()); + if (!request.get()) + return NULL; + // Verify param: client; type: refptr_diff + DCHECK(client.get()); + if (!client.get()) + return NULL; + + // Execute + cef_urlrequest_t* _retval = cef_urlrequest_create( + CefRequestCToCpp::Unwrap(request), + CefURLRequestClientCppToC::Wrap(client)); + + // Return type: refptr_same + return CefURLRequestCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefURLRequestCToCpp::GetRequest() { + if (CEF_MEMBER_MISSING(struct_, get_request)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_request_t* _retval = struct_->get_request(struct_); + + // Return type: refptr_same + return CefRequestCToCpp::Wrap(_retval); +} + +CefRefPtr CefURLRequestCToCpp::GetClient() { + if (CEF_MEMBER_MISSING(struct_, get_client)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_urlrequest_client_t* _retval = struct_->get_client(struct_); + + // Return type: refptr_diff + return CefURLRequestClientCppToC::Unwrap(_retval); +} + +CefURLRequest::Status CefURLRequestCToCpp::GetRequestStatus() { + if (CEF_MEMBER_MISSING(struct_, get_request_status)) + return UR_UNKNOWN; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_urlrequest_status_t _retval = struct_->get_request_status(struct_); + + // Return type: simple + return _retval; +} + +CefURLRequest::ErrorCode CefURLRequestCToCpp::GetRequestError() { + if (CEF_MEMBER_MISSING(struct_, get_request_error)) + return ERR_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_errorcode_t _retval = struct_->get_request_error(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefURLRequestCToCpp::GetResponse() { + if (CEF_MEMBER_MISSING(struct_, get_response)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_response_t* _retval = struct_->get_response(struct_); + + // Return type: refptr_same + return CefResponseCToCpp::Wrap(_retval); +} + +void CefURLRequestCToCpp::Cancel() { + if (CEF_MEMBER_MISSING(struct_, cancel)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->cancel(struct_); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.h b/libcef_dll/ctocpp/urlrequest_ctocpp.h new file mode 100644 index 000000000..b383d967a --- /dev/null +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_urlrequest.h" +#include "include/capi/cef_urlrequest_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefURLRequestCToCpp + : public CefCToCpp { + public: + explicit CefURLRequestCToCpp(cef_urlrequest_t* str) + : CefCToCpp(str) {} + virtual ~CefURLRequestCToCpp() {} + + // CefURLRequest methods + virtual CefRefPtr GetRequest() OVERRIDE; + virtual CefRefPtr GetClient() OVERRIDE; + virtual Status GetRequestStatus() OVERRIDE; + virtual ErrorCode GetRequestError() OVERRIDE; + virtual CefRefPtr GetResponse() OVERRIDE; + virtual void Cancel() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_URLREQUEST_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8accessor_ctocpp.cc b/libcef_dll/ctocpp/v8accessor_ctocpp.cc new file mode 100644 index 000000000..baae7a175 --- /dev/null +++ b/libcef_dll/ctocpp/v8accessor_ctocpp.cc @@ -0,0 +1,99 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8value_cpptoc.h" +#include "libcef_dll/ctocpp/v8accessor_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefV8AccessorCToCpp::Get(const CefString& name, + const CefRefPtr object, CefRefPtr& retval, + CefString& exception) { + if (CEF_MEMBER_MISSING(struct_, get)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return false; + // Verify param: object; type: refptr_diff + DCHECK(object.get()); + if (!object.get()) + return false; + + // Translate param: retval; type: refptr_diff_byref + cef_v8value_t* retvalStruct = NULL; + if (retval.get()) + retvalStruct = CefV8ValueCppToC::Wrap(retval); + cef_v8value_t* retvalOrig = retvalStruct; + + // Execute + int _retval = struct_->get(struct_, + name.GetStruct(), + CefV8ValueCppToC::Wrap(object), + &retvalStruct, + exception.GetWritableStruct()); + + // Restore param:retval; type: refptr_diff_byref + if (retvalStruct) { + if (retvalStruct != retvalOrig) { + retval = CefV8ValueCppToC::Unwrap(retvalStruct); + } + } else { + retval = NULL; + } + + // Return type: bool + return _retval?true:false; +} + +bool CefV8AccessorCToCpp::Set(const CefString& name, + const CefRefPtr object, const CefRefPtr value, + CefString& exception) { + if (CEF_MEMBER_MISSING(struct_, set)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return false; + // Verify param: object; type: refptr_diff + DCHECK(object.get()); + if (!object.get()) + return false; + // Verify param: value; type: refptr_diff + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set(struct_, + name.GetStruct(), + CefV8ValueCppToC::Wrap(object), + CefV8ValueCppToC::Wrap(value), + exception.GetWritableStruct()); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8accessor_ctocpp.h b/libcef_dll/ctocpp/v8accessor_ctocpp.h new file mode 100644 index 000000000..a53f86eeb --- /dev/null +++ b/libcef_dll/ctocpp/v8accessor_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8ACCESSOR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8ACCESSOR_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefV8AccessorCToCpp + : public CefCToCpp { + public: + explicit CefV8AccessorCToCpp(cef_v8accessor_t* str) + : CefCToCpp(str) {} + virtual ~CefV8AccessorCToCpp() {} + + // CefV8Accessor methods + virtual bool Get(const CefString& name, const CefRefPtr object, + CefRefPtr& retval, CefString& exception) OVERRIDE; + virtual bool Set(const CefString& name, const CefRefPtr object, + const CefRefPtr value, CefString& exception) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8ACCESSOR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8context_ctocpp.cc b/libcef_dll/ctocpp/v8context_ctocpp.cc new file mode 100644 index 000000000..8eaf6aac2 --- /dev/null +++ b/libcef_dll/ctocpp/v8context_ctocpp.cc @@ -0,0 +1,221 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/task_runner_ctocpp.h" +#include "libcef_dll/ctocpp/v8context_ctocpp.h" +#include "libcef_dll/ctocpp/v8exception_ctocpp.h" +#include "libcef_dll/ctocpp/v8value_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefV8Context::GetCurrentContext() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8context_t* _retval = cef_v8context_get_current_context(); + + // Return type: refptr_same + return CefV8ContextCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Context::GetEnteredContext() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8context_t* _retval = cef_v8context_get_entered_context(); + + // Return type: refptr_same + return CefV8ContextCToCpp::Wrap(_retval); +} + +bool CefV8Context::InContext() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_v8context_in_context(); + + // Return type: bool + return _retval?true:false; +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefRefPtr CefV8ContextCToCpp::GetTaskRunner() { + if (CEF_MEMBER_MISSING(struct_, get_task_runner)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_task_runner_t* _retval = struct_->get_task_runner(struct_); + + // Return type: refptr_same + return CefTaskRunnerCToCpp::Wrap(_retval); +} + +bool CefV8ContextCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefV8ContextCToCpp::GetBrowser() { + if (CEF_MEMBER_MISSING(struct_, get_browser)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_browser_t* _retval = struct_->get_browser(struct_); + + // Return type: refptr_same + return CefBrowserCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8ContextCToCpp::GetFrame() { + if (CEF_MEMBER_MISSING(struct_, get_frame)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_frame_t* _retval = struct_->get_frame(struct_); + + // Return type: refptr_same + return CefFrameCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8ContextCToCpp::GetGlobal() { + if (CEF_MEMBER_MISSING(struct_, get_global)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = struct_->get_global(struct_); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +bool CefV8ContextCToCpp::Enter() { + if (CEF_MEMBER_MISSING(struct_, enter)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->enter(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ContextCToCpp::Exit() { + if (CEF_MEMBER_MISSING(struct_, exit)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->exit(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ContextCToCpp::IsSame(CefRefPtr that) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: that; type: refptr_same + DCHECK(that.get()); + if (!that.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefV8ContextCToCpp::Unwrap(that)); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ContextCToCpp::Eval(const CefString& code, + CefRefPtr& retval, CefRefPtr& exception) { + if (CEF_MEMBER_MISSING(struct_, eval)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: code; type: string_byref_const + DCHECK(!code.empty()); + if (code.empty()) + return false; + + // Translate param: retval; type: refptr_same_byref + cef_v8value_t* retvalStruct = NULL; + if (retval.get()) + retvalStruct = CefV8ValueCToCpp::Unwrap(retval); + cef_v8value_t* retvalOrig = retvalStruct; + // Translate param: exception; type: refptr_same_byref + cef_v8exception_t* exceptionStruct = NULL; + if (exception.get()) + exceptionStruct = CefV8ExceptionCToCpp::Unwrap(exception); + cef_v8exception_t* exceptionOrig = exceptionStruct; + + // Execute + int _retval = struct_->eval(struct_, + code.GetStruct(), + &retvalStruct, + &exceptionStruct); + + // Restore param:retval; type: refptr_same_byref + if (retvalStruct) { + if (retvalStruct != retvalOrig) { + retval = CefV8ValueCToCpp::Wrap(retvalStruct); + } + } else { + retval = NULL; + } + // Restore param:exception; type: refptr_same_byref + if (exceptionStruct) { + if (exceptionStruct != exceptionOrig) { + exception = CefV8ExceptionCToCpp::Wrap(exceptionStruct); + } + } else { + exception = NULL; + } + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8context_ctocpp.h b/libcef_dll/ctocpp/v8context_ctocpp.h new file mode 100644 index 000000000..bc87bdad9 --- /dev/null +++ b/libcef_dll/ctocpp/v8context_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8CONTEXT_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8CONTEXT_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefV8ContextCToCpp + : public CefCToCpp { + public: + explicit CefV8ContextCToCpp(cef_v8context_t* str) + : CefCToCpp(str) {} + virtual ~CefV8ContextCToCpp() {} + + // CefV8Context methods + virtual CefRefPtr GetTaskRunner() OVERRIDE; + virtual bool IsValid() OVERRIDE; + virtual CefRefPtr GetBrowser() OVERRIDE; + virtual CefRefPtr GetFrame() OVERRIDE; + virtual CefRefPtr GetGlobal() OVERRIDE; + virtual bool Enter() OVERRIDE; + virtual bool Exit() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool Eval(const CefString& code, CefRefPtr& retval, + CefRefPtr& exception) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8CONTEXT_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8exception_ctocpp.cc b/libcef_dll/ctocpp/v8exception_ctocpp.cc new file mode 100644 index 000000000..2629704c9 --- /dev/null +++ b/libcef_dll/ctocpp/v8exception_ctocpp.cc @@ -0,0 +1,133 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/v8exception_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefString CefV8ExceptionCToCpp::GetMessage() { + if (CEF_MEMBER_MISSING(struct_, get_message)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_message(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefV8ExceptionCToCpp::GetSourceLine() { + if (CEF_MEMBER_MISSING(struct_, get_source_line)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_source_line(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefV8ExceptionCToCpp::GetScriptResourceName() { + if (CEF_MEMBER_MISSING(struct_, get_script_resource_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_script_resource_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +int CefV8ExceptionCToCpp::GetLineNumber() { + if (CEF_MEMBER_MISSING(struct_, get_line_number)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_line_number(struct_); + + // Return type: simple + return _retval; +} + +int CefV8ExceptionCToCpp::GetStartPosition() { + if (CEF_MEMBER_MISSING(struct_, get_start_position)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_start_position(struct_); + + // Return type: simple + return _retval; +} + +int CefV8ExceptionCToCpp::GetEndPosition() { + if (CEF_MEMBER_MISSING(struct_, get_end_position)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_end_position(struct_); + + // Return type: simple + return _retval; +} + +int CefV8ExceptionCToCpp::GetStartColumn() { + if (CEF_MEMBER_MISSING(struct_, get_start_column)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_start_column(struct_); + + // Return type: simple + return _retval; +} + +int CefV8ExceptionCToCpp::GetEndColumn() { + if (CEF_MEMBER_MISSING(struct_, get_end_column)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_end_column(struct_); + + // Return type: simple + return _retval; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8exception_ctocpp.h b/libcef_dll/ctocpp/v8exception_ctocpp.h new file mode 100644 index 000000000..7ca626e55 --- /dev/null +++ b/libcef_dll/ctocpp/v8exception_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8EXCEPTION_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8EXCEPTION_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefV8ExceptionCToCpp + : public CefCToCpp { + public: + explicit CefV8ExceptionCToCpp(cef_v8exception_t* str) + : CefCToCpp( + str) {} + virtual ~CefV8ExceptionCToCpp() {} + + // CefV8Exception methods + virtual CefString GetMessage() OVERRIDE; + virtual CefString GetSourceLine() OVERRIDE; + virtual CefString GetScriptResourceName() OVERRIDE; + virtual int GetLineNumber() OVERRIDE; + virtual int GetStartPosition() OVERRIDE; + virtual int GetEndPosition() OVERRIDE; + virtual int GetStartColumn() OVERRIDE; + virtual int GetEndColumn() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8EXCEPTION_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8handler_ctocpp.cc b/libcef_dll/ctocpp/v8handler_ctocpp.cc new file mode 100644 index 000000000..afea49a55 --- /dev/null +++ b/libcef_dll/ctocpp/v8handler_ctocpp.cc @@ -0,0 +1,84 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/v8value_cpptoc.h" +#include "libcef_dll/ctocpp/v8handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefV8HandlerCToCpp::Execute(const CefString& name, + CefRefPtr object, const CefV8ValueList& arguments, + CefRefPtr& retval, CefString& exception) { + if (CEF_MEMBER_MISSING(struct_, execute)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return false; + // Verify param: object; type: refptr_diff + DCHECK(object.get()); + if (!object.get()) + return false; + + // Translate param: arguments; type: refptr_vec_diff_byref_const + const size_t argumentsCount = arguments.size(); + cef_v8value_t** argumentsList = NULL; + if (argumentsCount > 0) { + argumentsList = new cef_v8value_t*[argumentsCount]; + DCHECK(argumentsList); + if (argumentsList) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList[i] = CefV8ValueCppToC::Wrap(arguments[i]); + } + } + } + // Translate param: retval; type: refptr_diff_byref + cef_v8value_t* retvalStruct = NULL; + if (retval.get()) + retvalStruct = CefV8ValueCppToC::Wrap(retval); + cef_v8value_t* retvalOrig = retvalStruct; + + // Execute + int _retval = struct_->execute(struct_, + name.GetStruct(), + CefV8ValueCppToC::Wrap(object), + argumentsCount, + argumentsList, + &retvalStruct, + exception.GetWritableStruct()); + + // Restore param:arguments; type: refptr_vec_diff_byref_const + if (argumentsList) + delete [] argumentsList; + // Restore param:retval; type: refptr_diff_byref + if (retvalStruct) { + if (retvalStruct != retvalOrig) { + retval = CefV8ValueCppToC::Unwrap(retvalStruct); + } + } else { + retval = NULL; + } + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8handler_ctocpp.h b/libcef_dll/ctocpp/v8handler_ctocpp.h new file mode 100644 index 000000000..4f8845cbb --- /dev/null +++ b/libcef_dll/ctocpp/v8handler_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefV8HandlerCToCpp + : public CefCToCpp { + public: + explicit CefV8HandlerCToCpp(cef_v8handler_t* str) + : CefCToCpp(str) {} + virtual ~CefV8HandlerCToCpp() {} + + // CefV8Handler methods + virtual bool Execute(const CefString& name, CefRefPtr object, + const CefV8ValueList& arguments, CefRefPtr& retval, + CefString& exception) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc b/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc new file mode 100644 index 000000000..959460314 --- /dev/null +++ b/libcef_dll/ctocpp/v8stack_frame_ctocpp.cc @@ -0,0 +1,134 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefV8StackFrameCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefV8StackFrameCToCpp::GetScriptName() { + if (CEF_MEMBER_MISSING(struct_, get_script_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_script_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefV8StackFrameCToCpp::GetScriptNameOrSourceURL() { + if (CEF_MEMBER_MISSING(struct_, get_script_name_or_source_url)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_script_name_or_source_url( + struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefV8StackFrameCToCpp::GetFunctionName() { + if (CEF_MEMBER_MISSING(struct_, get_function_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_function_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +int CefV8StackFrameCToCpp::GetLineNumber() { + if (CEF_MEMBER_MISSING(struct_, get_line_number)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_line_number(struct_); + + // Return type: simple + return _retval; +} + +int CefV8StackFrameCToCpp::GetColumn() { + if (CEF_MEMBER_MISSING(struct_, get_column)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_column(struct_); + + // Return type: simple + return _retval; +} + +bool CefV8StackFrameCToCpp::IsEval() { + if (CEF_MEMBER_MISSING(struct_, is_eval)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_eval(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8StackFrameCToCpp::IsConstructor() { + if (CEF_MEMBER_MISSING(struct_, is_constructor)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_constructor(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8stack_frame_ctocpp.h b/libcef_dll/ctocpp/v8stack_frame_ctocpp.h new file mode 100644 index 000000000..a6c1fa51a --- /dev/null +++ b/libcef_dll/ctocpp/v8stack_frame_ctocpp.h @@ -0,0 +1,49 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefV8StackFrameCToCpp + : public CefCToCpp { + public: + explicit CefV8StackFrameCToCpp(cef_v8stack_frame_t* str) + : CefCToCpp( + str) {} + virtual ~CefV8StackFrameCToCpp() {} + + // CefV8StackFrame methods + virtual bool IsValid() OVERRIDE; + virtual CefString GetScriptName() OVERRIDE; + virtual CefString GetScriptNameOrSourceURL() OVERRIDE; + virtual CefString GetFunctionName() OVERRIDE; + virtual int GetLineNumber() OVERRIDE; + virtual int GetColumn() OVERRIDE; + virtual bool IsEval() OVERRIDE; + virtual bool IsConstructor() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8STACK_FRAME_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc b/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc new file mode 100644 index 000000000..661aa337f --- /dev/null +++ b/libcef_dll/ctocpp/v8stack_trace_ctocpp.cc @@ -0,0 +1,78 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h" +#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefV8StackTrace::GetCurrent(int frame_limit) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8stack_trace_t* _retval = cef_v8stack_trace_get_current( + frame_limit); + + // Return type: refptr_same + return CefV8StackTraceCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefV8StackTraceCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +int CefV8StackTraceCToCpp::GetFrameCount() { + if (CEF_MEMBER_MISSING(struct_, get_frame_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_frame_count(struct_); + + // Return type: simple + return _retval; +} + +CefRefPtr CefV8StackTraceCToCpp::GetFrame(int index) { + if (CEF_MEMBER_MISSING(struct_, get_frame)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8stack_frame_t* _retval = struct_->get_frame(struct_, + index); + + // Return type: refptr_same + return CefV8StackFrameCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8stack_trace_ctocpp.h b/libcef_dll/ctocpp/v8stack_trace_ctocpp.h new file mode 100644 index 000000000..e94e2ec77 --- /dev/null +++ b/libcef_dll/ctocpp/v8stack_trace_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefV8StackTraceCToCpp + : public CefCToCpp { + public: + explicit CefV8StackTraceCToCpp(cef_v8stack_trace_t* str) + : CefCToCpp( + str) {} + virtual ~CefV8StackTraceCToCpp() {} + + // CefV8StackTrace methods + virtual bool IsValid() OVERRIDE; + virtual int GetFrameCount() OVERRIDE; + virtual CefRefPtr GetFrame(int index) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8STACK_TRACE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/v8value_ctocpp.cc b/libcef_dll/ctocpp/v8value_ctocpp.cc new file mode 100644 index 000000000..1fd71bab0 --- /dev/null +++ b/libcef_dll/ctocpp/v8value_ctocpp.cc @@ -0,0 +1,874 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/base_cpptoc.h" +#include "libcef_dll/cpptoc/v8accessor_cpptoc.h" +#include "libcef_dll/cpptoc/v8handler_cpptoc.h" +#include "libcef_dll/ctocpp/v8context_ctocpp.h" +#include "libcef_dll/ctocpp/v8exception_ctocpp.h" +#include "libcef_dll/ctocpp/v8value_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefV8Value::CreateUndefined() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_undefined(); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateNull() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_null(); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateBool(bool value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_bool( + value); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateInt(int32 value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_int( + value); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateUInt(uint32 value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_uint( + value); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateDouble(double value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_double( + value); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateDate(const CefTime& date) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_date( + &date); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateString(const CefString& value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: value + + // Execute + cef_v8value_t* _retval = cef_v8value_create_string( + value.GetStruct()); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateObject( + CefRefPtr accessor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: accessor + + // Execute + cef_v8value_t* _retval = cef_v8value_create_object( + CefV8AccessorCppToC::Wrap(accessor)); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateArray(int length) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8value_t* _retval = cef_v8value_create_array( + length); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8Value::CreateFunction(const CefString& name, + CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: name; type: string_byref_const + DCHECK(!name.empty()); + if (name.empty()) + return NULL; + // Verify param: handler; type: refptr_diff + DCHECK(handler.get()); + if (!handler.get()) + return NULL; + + // Execute + cef_v8value_t* _retval = cef_v8value_create_function( + name.GetStruct(), + CefV8HandlerCppToC::Wrap(handler)); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefV8ValueCToCpp::IsValid() { + if (CEF_MEMBER_MISSING(struct_, is_valid)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_valid(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsUndefined() { + if (CEF_MEMBER_MISSING(struct_, is_undefined)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_undefined(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsNull() { + if (CEF_MEMBER_MISSING(struct_, is_null)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_null(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsBool() { + if (CEF_MEMBER_MISSING(struct_, is_bool)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_bool(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsInt() { + if (CEF_MEMBER_MISSING(struct_, is_int)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_int(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsUInt() { + if (CEF_MEMBER_MISSING(struct_, is_uint)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_uint(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsDouble() { + if (CEF_MEMBER_MISSING(struct_, is_double)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_double(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsDate() { + if (CEF_MEMBER_MISSING(struct_, is_date)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_date(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsString() { + if (CEF_MEMBER_MISSING(struct_, is_string)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_string(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsObject() { + if (CEF_MEMBER_MISSING(struct_, is_object)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_object(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsArray() { + if (CEF_MEMBER_MISSING(struct_, is_array)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_array(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsFunction() { + if (CEF_MEMBER_MISSING(struct_, is_function)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_function(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::IsSame(CefRefPtr that) { + if (CEF_MEMBER_MISSING(struct_, is_same)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: that; type: refptr_same + DCHECK(that.get()); + if (!that.get()) + return false; + + // Execute + int _retval = struct_->is_same(struct_, + CefV8ValueCToCpp::Unwrap(that)); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::GetBoolValue() { + if (CEF_MEMBER_MISSING(struct_, get_bool_value)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_bool_value(struct_); + + // Return type: bool + return _retval?true:false; +} + +int32 CefV8ValueCToCpp::GetIntValue() { + if (CEF_MEMBER_MISSING(struct_, get_int_value)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int32 _retval = struct_->get_int_value(struct_); + + // Return type: simple + return _retval; +} + +uint32 CefV8ValueCToCpp::GetUIntValue() { + if (CEF_MEMBER_MISSING(struct_, get_uint_value)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + uint32 _retval = struct_->get_uint_value(struct_); + + // Return type: simple + return _retval; +} + +double CefV8ValueCToCpp::GetDoubleValue() { + if (CEF_MEMBER_MISSING(struct_, get_double_value)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + double _retval = struct_->get_double_value(struct_); + + // Return type: simple + return _retval; +} + +CefTime CefV8ValueCToCpp::GetDateValue() { + if (CEF_MEMBER_MISSING(struct_, get_date_value)) + return CefTime(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_time_t _retval = struct_->get_date_value(struct_); + + // Return type: simple + return _retval; +} + +CefString CefV8ValueCToCpp::GetStringValue() { + if (CEF_MEMBER_MISSING(struct_, get_string_value)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_string_value(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefV8ValueCToCpp::IsUserCreated() { + if (CEF_MEMBER_MISSING(struct_, is_user_created)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_user_created(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::HasException() { + if (CEF_MEMBER_MISSING(struct_, has_exception)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_exception(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefV8ValueCToCpp::GetException() { + if (CEF_MEMBER_MISSING(struct_, get_exception)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8exception_t* _retval = struct_->get_exception(struct_); + + // Return type: refptr_same + return CefV8ExceptionCToCpp::Wrap(_retval); +} + +bool CefV8ValueCToCpp::ClearException() { + if (CEF_MEMBER_MISSING(struct_, clear_exception)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->clear_exception(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::WillRethrowExceptions() { + if (CEF_MEMBER_MISSING(struct_, will_rethrow_exceptions)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->will_rethrow_exceptions(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::SetRethrowExceptions(bool rethrow) { + if (CEF_MEMBER_MISSING(struct_, set_rethrow_exceptions)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->set_rethrow_exceptions(struct_, + rethrow); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::HasValue(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, has_value_bykey)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: key + + // Execute + int _retval = struct_->has_value_bykey(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::HasValue(int index) { + if (CEF_MEMBER_MISSING(struct_, has_value_byindex)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->has_value_byindex(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::DeleteValue(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, delete_value_bykey)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: key + + // Execute + int _retval = struct_->delete_value_bykey(struct_, + key.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::DeleteValue(int index) { + if (CEF_MEMBER_MISSING(struct_, delete_value_byindex)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->delete_value_byindex(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefV8ValueCToCpp::GetValue(const CefString& key) { + if (CEF_MEMBER_MISSING(struct_, get_value_bykey)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: key + + // Execute + cef_v8value_t* _retval = struct_->get_value_bykey(struct_, + key.GetStruct()); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8ValueCToCpp::GetValue(int index) { + if (CEF_MEMBER_MISSING(struct_, get_value_byindex)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return NULL; + + // Execute + cef_v8value_t* _retval = struct_->get_value_byindex(struct_, + index); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +bool CefV8ValueCToCpp::SetValue(const CefString& key, + CefRefPtr value, PropertyAttribute attribute) { + if (CEF_MEMBER_MISSING(struct_, set_value_bykey)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + // Unverified params: key + + // Execute + int _retval = struct_->set_value_bykey(struct_, + key.GetStruct(), + CefV8ValueCToCpp::Unwrap(value), + attribute); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::SetValue(int index, CefRefPtr value) { + if (CEF_MEMBER_MISSING(struct_, set_value_byindex)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + // Verify param: value; type: refptr_same + DCHECK(value.get()); + if (!value.get()) + return false; + + // Execute + int _retval = struct_->set_value_byindex(struct_, + index, + CefV8ValueCToCpp::Unwrap(value)); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::SetValue(const CefString& key, AccessControl settings, + PropertyAttribute attribute) { + if (CEF_MEMBER_MISSING(struct_, set_value_byaccessor)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: key + + // Execute + int _retval = struct_->set_value_byaccessor(struct_, + key.GetStruct(), + settings, + attribute); + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::GetKeys(std::vector& keys) { + if (CEF_MEMBER_MISSING(struct_, get_keys)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: keys; type: string_vec_byref + cef_string_list_t keysList = cef_string_list_alloc(); + DCHECK(keysList); + if (keysList) + transfer_string_list_contents(keys, keysList); + + // Execute + int _retval = struct_->get_keys(struct_, + keysList); + + // Restore param:keys; type: string_vec_byref + if (keysList) { + keys.clear(); + transfer_string_list_contents(keysList, keys); + cef_string_list_free(keysList); + } + + // Return type: bool + return _retval?true:false; +} + +bool CefV8ValueCToCpp::SetUserData(CefRefPtr user_data) { + if (CEF_MEMBER_MISSING(struct_, set_user_data)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: user_data + + // Execute + int _retval = struct_->set_user_data(struct_, + CefBaseCppToC::Wrap(user_data)); + + // Return type: bool + return _retval?true:false; +} + +CefRefPtr CefV8ValueCToCpp::GetUserData() { + if (CEF_MEMBER_MISSING(struct_, get_user_data)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_base_t* _retval = struct_->get_user_data(struct_); + + // Return type: refptr_diff + return CefBaseCppToC::Unwrap(_retval); +} + +int CefV8ValueCToCpp::GetExternallyAllocatedMemory() { + if (CEF_MEMBER_MISSING(struct_, get_externally_allocated_memory)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_externally_allocated_memory(struct_); + + // Return type: simple + return _retval; +} + +int CefV8ValueCToCpp::AdjustExternallyAllocatedMemory(int change_in_bytes) { + if (CEF_MEMBER_MISSING(struct_, adjust_externally_allocated_memory)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->adjust_externally_allocated_memory(struct_, + change_in_bytes); + + // Return type: simple + return _retval; +} + +int CefV8ValueCToCpp::GetArrayLength() { + if (CEF_MEMBER_MISSING(struct_, get_array_length)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_array_length(struct_); + + // Return type: simple + return _retval; +} + +CefString CefV8ValueCToCpp::GetFunctionName() { + if (CEF_MEMBER_MISSING(struct_, get_function_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_function_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefV8ValueCToCpp::GetFunctionHandler() { + if (CEF_MEMBER_MISSING(struct_, get_function_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_v8handler_t* _retval = struct_->get_function_handler(struct_); + + // Return type: refptr_diff + return CefV8HandlerCppToC::Unwrap(_retval); +} + +CefRefPtr CefV8ValueCToCpp::ExecuteFunction( + CefRefPtr object, const CefV8ValueList& arguments) { + if (CEF_MEMBER_MISSING(struct_, execute_function)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: object + + // Translate param: arguments; type: refptr_vec_same_byref_const + const size_t argumentsCount = arguments.size(); + cef_v8value_t** argumentsList = NULL; + if (argumentsCount > 0) { + argumentsList = new cef_v8value_t*[argumentsCount]; + DCHECK(argumentsList); + if (argumentsList) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList[i] = CefV8ValueCToCpp::Unwrap(arguments[i]); + } + } + } + + // Execute + cef_v8value_t* _retval = struct_->execute_function(struct_, + CefV8ValueCToCpp::Unwrap(object), + argumentsCount, + argumentsList); + + // Restore param:arguments; type: refptr_vec_same_byref_const + if (argumentsList) + delete [] argumentsList; + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + +CefRefPtr CefV8ValueCToCpp::ExecuteFunctionWithContext( + CefRefPtr context, CefRefPtr object, + const CefV8ValueList& arguments) { + if (CEF_MEMBER_MISSING(struct_, execute_function_with_context)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: context; type: refptr_same + DCHECK(context.get()); + if (!context.get()) + return NULL; + // Unverified params: object + + // Translate param: arguments; type: refptr_vec_same_byref_const + const size_t argumentsCount = arguments.size(); + cef_v8value_t** argumentsList = NULL; + if (argumentsCount > 0) { + argumentsList = new cef_v8value_t*[argumentsCount]; + DCHECK(argumentsList); + if (argumentsList) { + for (size_t i = 0; i < argumentsCount; ++i) { + argumentsList[i] = CefV8ValueCToCpp::Unwrap(arguments[i]); + } + } + } + + // Execute + cef_v8value_t* _retval = struct_->execute_function_with_context(struct_, + CefV8ContextCToCpp::Unwrap(context), + CefV8ValueCToCpp::Unwrap(object), + argumentsCount, + argumentsList); + + // Restore param:arguments; type: refptr_vec_same_byref_const + if (argumentsList) + delete [] argumentsList; + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/v8value_ctocpp.h b/libcef_dll/ctocpp/v8value_ctocpp.h new file mode 100644 index 000000000..fb3b168c7 --- /dev/null +++ b/libcef_dll/ctocpp/v8value_ctocpp.h @@ -0,0 +1,89 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefV8ValueCToCpp + : public CefCToCpp { + public: + explicit CefV8ValueCToCpp(cef_v8value_t* str) + : CefCToCpp(str) {} + virtual ~CefV8ValueCToCpp() {} + + // CefV8Value methods + virtual bool IsValid() OVERRIDE; + virtual bool IsUndefined() OVERRIDE; + virtual bool IsNull() OVERRIDE; + virtual bool IsBool() OVERRIDE; + virtual bool IsInt() OVERRIDE; + virtual bool IsUInt() OVERRIDE; + virtual bool IsDouble() OVERRIDE; + virtual bool IsDate() OVERRIDE; + virtual bool IsString() OVERRIDE; + virtual bool IsObject() OVERRIDE; + virtual bool IsArray() OVERRIDE; + virtual bool IsFunction() OVERRIDE; + virtual bool IsSame(CefRefPtr that) OVERRIDE; + virtual bool GetBoolValue() OVERRIDE; + virtual int32 GetIntValue() OVERRIDE; + virtual uint32 GetUIntValue() OVERRIDE; + virtual double GetDoubleValue() OVERRIDE; + virtual CefTime GetDateValue() OVERRIDE; + virtual CefString GetStringValue() OVERRIDE; + virtual bool IsUserCreated() OVERRIDE; + virtual bool HasException() OVERRIDE; + virtual CefRefPtr GetException() OVERRIDE; + virtual bool ClearException() OVERRIDE; + virtual bool WillRethrowExceptions() OVERRIDE; + virtual bool SetRethrowExceptions(bool rethrow) OVERRIDE; + virtual bool HasValue(const CefString& key) OVERRIDE; + virtual bool HasValue(int index) OVERRIDE; + virtual bool DeleteValue(const CefString& key) OVERRIDE; + virtual bool DeleteValue(int index) OVERRIDE; + virtual CefRefPtr GetValue(const CefString& key) OVERRIDE; + virtual CefRefPtr GetValue(int index) OVERRIDE; + virtual bool SetValue(const CefString& key, CefRefPtr value, + PropertyAttribute attribute) OVERRIDE; + virtual bool SetValue(int index, CefRefPtr value) OVERRIDE; + virtual bool SetValue(const CefString& key, AccessControl settings, + PropertyAttribute attribute) OVERRIDE; + virtual bool GetKeys(std::vector& keys) OVERRIDE; + virtual bool SetUserData(CefRefPtr user_data) OVERRIDE; + virtual CefRefPtr GetUserData() OVERRIDE; + virtual int GetExternallyAllocatedMemory() OVERRIDE; + virtual int AdjustExternallyAllocatedMemory(int change_in_bytes) OVERRIDE; + virtual int GetArrayLength() OVERRIDE; + virtual CefString GetFunctionName() OVERRIDE; + virtual CefRefPtr GetFunctionHandler() OVERRIDE; + virtual CefRefPtr ExecuteFunction(CefRefPtr object, + const CefV8ValueList& arguments) OVERRIDE; + virtual CefRefPtr ExecuteFunctionWithContext( + CefRefPtr context, CefRefPtr object, + const CefV8ValueList& arguments) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc new file mode 100644 index 000000000..196b14912 --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_info_ctocpp.cc @@ -0,0 +1,83 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +CefString CefWebPluginInfoCToCpp::GetName() { + if (CEF_MEMBER_MISSING(struct_, get_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefWebPluginInfoCToCpp::GetPath() { + if (CEF_MEMBER_MISSING(struct_, get_path)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_path(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefWebPluginInfoCToCpp::GetVersion() { + if (CEF_MEMBER_MISSING(struct_, get_version)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_version(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefWebPluginInfoCToCpp::GetDescription() { + if (CEF_MEMBER_MISSING(struct_, get_description)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_description(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/web_plugin_info_ctocpp.h b/libcef_dll/ctocpp/web_plugin_info_ctocpp.h new file mode 100644 index 000000000..b241d877a --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_info_ctocpp.h @@ -0,0 +1,45 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefWebPluginInfoCToCpp + : public CefCToCpp { + public: + explicit CefWebPluginInfoCToCpp(cef_web_plugin_info_t* str) + : CefCToCpp(str) {} + virtual ~CefWebPluginInfoCToCpp() {} + + // CefWebPluginInfo methods + virtual CefString GetName() OVERRIDE; + virtual CefString GetPath() OVERRIDE; + virtual CefString GetVersion() OVERRIDE; + virtual CefString GetDescription() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc new file mode 100644 index 000000000..5811d3ef9 --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.cc @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h" +#include "libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefWebPluginInfoVisitorCToCpp::Visit(CefRefPtr info, + int count, int total) { + if (CEF_MEMBER_MISSING(struct_, visit)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: info; type: refptr_diff + DCHECK(info.get()); + if (!info.get()) + return false; + + // Execute + int _retval = struct_->visit(struct_, + CefWebPluginInfoCppToC::Wrap(info), + count, + total); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h new file mode 100644 index 000000000..b4ccf3b0f --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h @@ -0,0 +1,43 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefWebPluginInfoVisitorCToCpp + : public CefCToCpp { + public: + explicit CefWebPluginInfoVisitorCToCpp(cef_web_plugin_info_visitor_t* str) + : CefCToCpp(str) {} + virtual ~CefWebPluginInfoVisitorCToCpp() {} + + // CefWebPluginInfoVisitor methods + virtual bool Visit(CefRefPtr info, int count, + int total) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_INFO_VISITOR_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc new file mode 100644 index 000000000..eab6967e2 --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.cc @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefWebPluginUnstableCallbackCToCpp::IsUnstable(const CefString& path, + bool unstable) { + if (CEF_MEMBER_MISSING(struct_, is_unstable)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + struct_->is_unstable(struct_, + path.GetStruct(), + unstable); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h new file mode 100644 index 000000000..bfef9a951 --- /dev/null +++ b/libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefWebPluginUnstableCallbackCToCpp + : public CefCToCpp { + public: + explicit CefWebPluginUnstableCallbackCToCpp( + cef_web_plugin_unstable_callback_t* str) + : CefCToCpp( + str) {} + virtual ~CefWebPluginUnstableCallbackCToCpp() {} + + // CefWebPluginUnstableCallback methods + virtual void IsUnstable(const CefString& path, bool unstable) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_WEB_PLUGIN_UNSTABLE_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/write_handler_ctocpp.cc b/libcef_dll/ctocpp/write_handler_ctocpp.cc new file mode 100644 index 000000000..45aaec6f0 --- /dev/null +++ b/libcef_dll/ctocpp/write_handler_ctocpp.cc @@ -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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/write_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +size_t CefWriteHandlerCToCpp::Write(const void* ptr, size_t size, size_t n) { + if (CEF_MEMBER_MISSING(struct_, write)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: ptr; type: simple_byaddr + DCHECK(ptr); + if (!ptr) + return 0; + + // Execute + size_t _retval = struct_->write(struct_, + ptr, + size, + n); + + // Return type: simple + return _retval; +} + +int CefWriteHandlerCToCpp::Seek(int64 offset, int whence) { + if (CEF_MEMBER_MISSING(struct_, seek)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->seek(struct_, + offset, + whence); + + // Return type: simple + return _retval; +} + +int64 CefWriteHandlerCToCpp::Tell() { + if (CEF_MEMBER_MISSING(struct_, tell)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->tell(struct_); + + // Return type: simple + return _retval; +} + +int CefWriteHandlerCToCpp::Flush() { + if (CEF_MEMBER_MISSING(struct_, flush)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->flush(struct_); + + // Return type: simple + return _retval; +} + +bool CefWriteHandlerCToCpp::MayBlock() { + if (CEF_MEMBER_MISSING(struct_, may_block)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->may_block(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/write_handler_ctocpp.h b/libcef_dll/ctocpp/write_handler_ctocpp.h new file mode 100644 index 000000000..211cac37b --- /dev/null +++ b/libcef_dll/ctocpp/write_handler_ctocpp.h @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_WRITE_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_WRITE_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_stream.h" +#include "include/capi/cef_stream_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefWriteHandlerCToCpp + : public CefCToCpp { + public: + explicit CefWriteHandlerCToCpp(cef_write_handler_t* str) + : CefCToCpp( + str) {} + virtual ~CefWriteHandlerCToCpp() {} + + // CefWriteHandler methods + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Flush() OVERRIDE; + virtual bool MayBlock() OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_WRITE_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/xml_reader_ctocpp.cc b/libcef_dll/ctocpp/xml_reader_ctocpp.cc new file mode 100644 index 000000000..4c4667b0d --- /dev/null +++ b/libcef_dll/ctocpp/xml_reader_ctocpp.cc @@ -0,0 +1,501 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/stream_reader_ctocpp.h" +#include "libcef_dll/ctocpp/xml_reader_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefXmlReader::Create(CefRefPtr stream, + EncodingType encodingType, const CefString& URI) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: stream; type: refptr_same + DCHECK(stream.get()); + if (!stream.get()) + return NULL; + // Verify param: URI; type: string_byref_const + DCHECK(!URI.empty()); + if (URI.empty()) + return NULL; + + // Execute + cef_xml_reader_t* _retval = cef_xml_reader_create( + CefStreamReaderCToCpp::Unwrap(stream), + encodingType, + URI.GetStruct()); + + // Return type: refptr_same + return CefXmlReaderCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefXmlReaderCToCpp::MoveToNextNode() { + if (CEF_MEMBER_MISSING(struct_, move_to_next_node)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_next_node(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::Close() { + if (CEF_MEMBER_MISSING(struct_, close)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->close(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::HasError() { + if (CEF_MEMBER_MISSING(struct_, has_error)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_error(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefXmlReaderCToCpp::GetError() { + if (CEF_MEMBER_MISSING(struct_, get_error)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_error(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefXmlReader::NodeType CefXmlReaderCToCpp::GetType() { + if (CEF_MEMBER_MISSING(struct_, get_type)) + return XML_NODE_UNSUPPORTED; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_xml_node_type_t _retval = struct_->get_type(struct_); + + // Return type: simple + return _retval; +} + +int CefXmlReaderCToCpp::GetDepth() { + if (CEF_MEMBER_MISSING(struct_, get_depth)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_depth(struct_); + + // Return type: simple + return _retval; +} + +CefString CefXmlReaderCToCpp::GetLocalName() { + if (CEF_MEMBER_MISSING(struct_, get_local_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_local_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetPrefix() { + if (CEF_MEMBER_MISSING(struct_, get_prefix)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_prefix(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetQualifiedName() { + if (CEF_MEMBER_MISSING(struct_, get_qualified_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_qualified_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetNamespaceURI() { + if (CEF_MEMBER_MISSING(struct_, get_namespace_uri)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_namespace_uri(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetBaseURI() { + if (CEF_MEMBER_MISSING(struct_, get_base_uri)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_base_uri(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetXmlLang() { + if (CEF_MEMBER_MISSING(struct_, get_xml_lang)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_xml_lang(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefXmlReaderCToCpp::IsEmptyElement() { + if (CEF_MEMBER_MISSING(struct_, is_empty_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->is_empty_element(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::HasValue() { + if (CEF_MEMBER_MISSING(struct_, has_value)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_value(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefXmlReaderCToCpp::GetValue() { + if (CEF_MEMBER_MISSING(struct_, get_value)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_value(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +bool CefXmlReaderCToCpp::HasAttributes() { + if (CEF_MEMBER_MISSING(struct_, has_attributes)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->has_attributes(struct_); + + // Return type: bool + return _retval?true:false; +} + +size_t CefXmlReaderCToCpp::GetAttributeCount() { + if (CEF_MEMBER_MISSING(struct_, get_attribute_count)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = struct_->get_attribute_count(struct_); + + // Return type: simple + return _retval; +} + +CefString CefXmlReaderCToCpp::GetAttribute(int index) { + if (CEF_MEMBER_MISSING(struct_, get_attribute_byindex)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_attribute_byindex(struct_, + index); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetAttribute(const CefString& qualifiedName) { + if (CEF_MEMBER_MISSING(struct_, get_attribute_byqname)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: qualifiedName; type: string_byref_const + DCHECK(!qualifiedName.empty()); + if (qualifiedName.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_attribute_byqname(struct_, + qualifiedName.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetAttribute(const CefString& localName, + const CefString& namespaceURI) { + if (CEF_MEMBER_MISSING(struct_, get_attribute_bylname)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: localName; type: string_byref_const + DCHECK(!localName.empty()); + if (localName.empty()) + return CefString(); + // Verify param: namespaceURI; type: string_byref_const + DCHECK(!namespaceURI.empty()); + if (namespaceURI.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = struct_->get_attribute_bylname(struct_, + localName.GetStruct(), + namespaceURI.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetInnerXml() { + if (CEF_MEMBER_MISSING(struct_, get_inner_xml)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_inner_xml(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefString CefXmlReaderCToCpp::GetOuterXml() { + if (CEF_MEMBER_MISSING(struct_, get_outer_xml)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_outer_xml(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +int CefXmlReaderCToCpp::GetLineNumber() { + if (CEF_MEMBER_MISSING(struct_, get_line_number)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->get_line_number(struct_); + + // Return type: simple + return _retval; +} + +bool CefXmlReaderCToCpp::MoveToAttribute(int index) { + if (CEF_MEMBER_MISSING(struct_, move_to_attribute_byindex)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: index; type: simple_byval + DCHECK_GE(index, 0); + if (index < 0) + return false; + + // Execute + int _retval = struct_->move_to_attribute_byindex(struct_, + index); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::MoveToAttribute(const CefString& qualifiedName) { + if (CEF_MEMBER_MISSING(struct_, move_to_attribute_byqname)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: qualifiedName; type: string_byref_const + DCHECK(!qualifiedName.empty()); + if (qualifiedName.empty()) + return false; + + // Execute + int _retval = struct_->move_to_attribute_byqname(struct_, + qualifiedName.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::MoveToAttribute(const CefString& localName, + const CefString& namespaceURI) { + if (CEF_MEMBER_MISSING(struct_, move_to_attribute_bylname)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: localName; type: string_byref_const + DCHECK(!localName.empty()); + if (localName.empty()) + return false; + // Verify param: namespaceURI; type: string_byref_const + DCHECK(!namespaceURI.empty()); + if (namespaceURI.empty()) + return false; + + // Execute + int _retval = struct_->move_to_attribute_bylname(struct_, + localName.GetStruct(), + namespaceURI.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::MoveToFirstAttribute() { + if (CEF_MEMBER_MISSING(struct_, move_to_first_attribute)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_first_attribute(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::MoveToNextAttribute() { + if (CEF_MEMBER_MISSING(struct_, move_to_next_attribute)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_next_attribute(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefXmlReaderCToCpp::MoveToCarryingElement() { + if (CEF_MEMBER_MISSING(struct_, move_to_carrying_element)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_carrying_element(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/xml_reader_ctocpp.h b/libcef_dll/ctocpp/xml_reader_ctocpp.h new file mode 100644 index 000000000..a997b8807 --- /dev/null +++ b/libcef_dll/ctocpp/xml_reader_ctocpp.h @@ -0,0 +1,70 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_XML_READER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_XML_READER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_xml_reader.h" +#include "include/capi/cef_xml_reader_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefXmlReaderCToCpp + : public CefCToCpp { + public: + explicit CefXmlReaderCToCpp(cef_xml_reader_t* str) + : CefCToCpp(str) {} + virtual ~CefXmlReaderCToCpp() {} + + // CefXmlReader methods + virtual bool MoveToNextNode() OVERRIDE; + virtual bool Close() OVERRIDE; + virtual bool HasError() OVERRIDE; + virtual CefString GetError() OVERRIDE; + virtual NodeType GetType() OVERRIDE; + virtual int GetDepth() OVERRIDE; + virtual CefString GetLocalName() OVERRIDE; + virtual CefString GetPrefix() OVERRIDE; + virtual CefString GetQualifiedName() OVERRIDE; + virtual CefString GetNamespaceURI() OVERRIDE; + virtual CefString GetBaseURI() OVERRIDE; + virtual CefString GetXmlLang() OVERRIDE; + virtual bool IsEmptyElement() OVERRIDE; + virtual bool HasValue() OVERRIDE; + virtual CefString GetValue() OVERRIDE; + virtual bool HasAttributes() OVERRIDE; + virtual size_t GetAttributeCount() OVERRIDE; + virtual CefString GetAttribute(int index) OVERRIDE; + virtual CefString GetAttribute(const CefString& qualifiedName) OVERRIDE; + virtual CefString GetAttribute(const CefString& localName, + const CefString& namespaceURI) OVERRIDE; + virtual CefString GetInnerXml() OVERRIDE; + virtual CefString GetOuterXml() OVERRIDE; + virtual int GetLineNumber() OVERRIDE; + virtual bool MoveToAttribute(int index) OVERRIDE; + virtual bool MoveToAttribute(const CefString& qualifiedName) OVERRIDE; + virtual bool MoveToAttribute(const CefString& localName, + const CefString& namespaceURI) OVERRIDE; + virtual bool MoveToFirstAttribute() OVERRIDE; + virtual bool MoveToNextAttribute() OVERRIDE; + virtual bool MoveToCarryingElement() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_XML_READER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/zip_reader_ctocpp.cc b/libcef_dll/ctocpp/zip_reader_ctocpp.cc new file mode 100644 index 000000000..576247bdb --- /dev/null +++ b/libcef_dll/ctocpp/zip_reader_ctocpp.cc @@ -0,0 +1,220 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/stream_reader_ctocpp.h" +#include "libcef_dll/ctocpp/zip_reader_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefZipReader::Create( + CefRefPtr stream) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: stream; type: refptr_same + DCHECK(stream.get()); + if (!stream.get()) + return NULL; + + // Execute + cef_zip_reader_t* _retval = cef_zip_reader_create( + CefStreamReaderCToCpp::Unwrap(stream)); + + // Return type: refptr_same + return CefZipReaderCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefZipReaderCToCpp::MoveToFirstFile() { + if (CEF_MEMBER_MISSING(struct_, move_to_first_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_first_file(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefZipReaderCToCpp::MoveToNextFile() { + if (CEF_MEMBER_MISSING(struct_, move_to_next_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->move_to_next_file(struct_); + + // Return type: bool + return _retval?true:false; +} + +bool CefZipReaderCToCpp::MoveToFile(const CefString& fileName, + bool caseSensitive) { + if (CEF_MEMBER_MISSING(struct_, move_to_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: fileName; type: string_byref_const + DCHECK(!fileName.empty()); + if (fileName.empty()) + return false; + + // Execute + int _retval = struct_->move_to_file(struct_, + fileName.GetStruct(), + caseSensitive); + + // Return type: bool + return _retval?true:false; +} + +bool CefZipReaderCToCpp::Close() { + if (CEF_MEMBER_MISSING(struct_, close)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->close(struct_); + + // Return type: bool + return _retval?true:false; +} + +CefString CefZipReaderCToCpp::GetFileName() { + if (CEF_MEMBER_MISSING(struct_, get_file_name)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_file_name(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +int64 CefZipReaderCToCpp::GetFileSize() { + if (CEF_MEMBER_MISSING(struct_, get_file_size)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->get_file_size(struct_); + + // Return type: simple + return _retval; +} + +time_t CefZipReaderCToCpp::GetFileLastModified() { + if (CEF_MEMBER_MISSING(struct_, get_file_last_modified)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + time_t _retval = struct_->get_file_last_modified(struct_); + + // Return type: simple + return _retval; +} + +bool CefZipReaderCToCpp::OpenFile(const CefString& password) { + if (CEF_MEMBER_MISSING(struct_, open_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: password + + // Execute + int _retval = struct_->open_file(struct_, + password.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefZipReaderCToCpp::CloseFile() { + if (CEF_MEMBER_MISSING(struct_, close_file)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->close_file(struct_); + + // Return type: bool + return _retval?true:false; +} + +int CefZipReaderCToCpp::ReadFile(void* buffer, size_t bufferSize) { + if (CEF_MEMBER_MISSING(struct_, read_file)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: buffer; type: simple_byaddr + DCHECK(buffer); + if (!buffer) + return 0; + + // Execute + int _retval = struct_->read_file(struct_, + buffer, + bufferSize); + + // Return type: simple + return _retval; +} + +int64 CefZipReaderCToCpp::Tell() { + if (CEF_MEMBER_MISSING(struct_, tell)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = struct_->tell(struct_); + + // Return type: simple + return _retval; +} + +bool CefZipReaderCToCpp::Eof() { + if (CEF_MEMBER_MISSING(struct_, eof)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->eof(struct_); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/zip_reader_ctocpp.h b/libcef_dll/ctocpp/zip_reader_ctocpp.h new file mode 100644 index 000000000..4bf24604a --- /dev/null +++ b/libcef_dll/ctocpp/zip_reader_ctocpp.h @@ -0,0 +1,52 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_ZIP_READER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_ZIP_READER_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_zip_reader.h" +#include "include/capi/cef_zip_reader_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefZipReaderCToCpp + : public CefCToCpp { + public: + explicit CefZipReaderCToCpp(cef_zip_reader_t* str) + : CefCToCpp(str) {} + virtual ~CefZipReaderCToCpp() {} + + // CefZipReader methods + virtual bool MoveToFirstFile() OVERRIDE; + virtual bool MoveToNextFile() OVERRIDE; + virtual bool MoveToFile(const CefString& fileName, + bool caseSensitive) OVERRIDE; + virtual bool Close() OVERRIDE; + virtual CefString GetFileName() OVERRIDE; + virtual int64 GetFileSize() OVERRIDE; + virtual time_t GetFileLastModified() OVERRIDE; + virtual bool OpenFile(const CefString& password) OVERRIDE; + virtual bool CloseFile() OVERRIDE; + virtual int ReadFile(void* buffer, size_t bufferSize) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual bool Eof() OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_ZIP_READER_CTOCPP_H_ + diff --git a/libcef_dll/libcef.dll.manifest b/libcef_dll/libcef.dll.manifest new file mode 100644 index 000000000..76c638080 --- /dev/null +++ b/libcef_dll/libcef.dll.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc new file mode 100644 index 000000000..2c8544c1e --- /dev/null +++ b/libcef_dll/libcef_dll.cc @@ -0,0 +1,780 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "include/cef_app.h" +#include "include/capi/cef_app_capi.h" +#include "include/cef_geolocation.h" +#include "include/capi/cef_geolocation_capi.h" +#include "include/cef_origin_whitelist.h" +#include "include/capi/cef_origin_whitelist_capi.h" +#include "include/cef_path_util.h" +#include "include/capi/cef_path_util_capi.h" +#include "include/cef_process_util.h" +#include "include/capi/cef_process_util_capi.h" +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "include/cef_trace.h" +#include "include/capi/cef_trace_capi.h" +#include "include/cef_url.h" +#include "include/capi/cef_url_capi.h" +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "libcef_dll/cpptoc/allow_certificate_error_callback_cpptoc.h" +#include "libcef_dll/cpptoc/auth_callback_cpptoc.h" +#include "libcef_dll/cpptoc/before_download_callback_cpptoc.h" +#include "libcef_dll/cpptoc/binary_value_cpptoc.h" +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/browser_host_cpptoc.h" +#include "libcef_dll/cpptoc/callback_cpptoc.h" +#include "libcef_dll/cpptoc/command_line_cpptoc.h" +#include "libcef_dll/cpptoc/context_menu_params_cpptoc.h" +#include "libcef_dll/cpptoc/domdocument_cpptoc.h" +#include "libcef_dll/cpptoc/domevent_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" +#include "libcef_dll/cpptoc/dictionary_value_cpptoc.h" +#include "libcef_dll/cpptoc/download_item_cpptoc.h" +#include "libcef_dll/cpptoc/download_item_callback_cpptoc.h" +#include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/cpptoc/file_dialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" +#include "libcef_dll/cpptoc/geolocation_callback_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/list_value_cpptoc.h" +#include "libcef_dll/cpptoc/menu_model_cpptoc.h" +#include "libcef_dll/cpptoc/print_dialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/print_job_callback_cpptoc.h" +#include "libcef_dll/cpptoc/print_settings_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" +#include "libcef_dll/cpptoc/quota_callback_cpptoc.h" +#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h" +#include "libcef_dll/cpptoc/stream_reader_cpptoc.h" +#include "libcef_dll/cpptoc/stream_writer_cpptoc.h" +#include "libcef_dll/cpptoc/task_runner_cpptoc.h" +#include "libcef_dll/cpptoc/urlrequest_cpptoc.h" +#include "libcef_dll/cpptoc/v8context_cpptoc.h" +#include "libcef_dll/cpptoc/v8exception_cpptoc.h" +#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h" +#include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h" +#include "libcef_dll/cpptoc/v8value_cpptoc.h" +#include "libcef_dll/cpptoc/web_plugin_info_cpptoc.h" +#include "libcef_dll/cpptoc/xml_reader_cpptoc.h" +#include "libcef_dll/cpptoc/zip_reader_cpptoc.h" +#include "libcef_dll/ctocpp/app_ctocpp.h" +#include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h" +#include "libcef_dll/ctocpp/completion_callback_ctocpp.h" +#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h" +#include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" +#include "libcef_dll/ctocpp/domevent_listener_ctocpp.h" +#include "libcef_dll/ctocpp/domvisitor_ctocpp.h" +#include "libcef_dll/ctocpp/dialog_handler_ctocpp.h" +#include "libcef_dll/ctocpp/display_handler_ctocpp.h" +#include "libcef_dll/ctocpp/download_handler_ctocpp.h" +#include "libcef_dll/ctocpp/drag_handler_ctocpp.h" +#include "libcef_dll/ctocpp/end_tracing_callback_ctocpp.h" +#include "libcef_dll/ctocpp/focus_handler_ctocpp.h" +#include "libcef_dll/ctocpp/geolocation_handler_ctocpp.h" +#include "libcef_dll/ctocpp/get_geolocation_callback_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" +#include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h" +#include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" +#include "libcef_dll/ctocpp/load_handler_ctocpp.h" +#include "libcef_dll/ctocpp/print_handler_ctocpp.h" +#include "libcef_dll/ctocpp/read_handler_ctocpp.h" +#include "libcef_dll/ctocpp/render_handler_ctocpp.h" +#include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" +#include "libcef_dll/ctocpp/request_handler_ctocpp.h" +#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h" +#include "libcef_dll/ctocpp/resource_handler_ctocpp.h" +#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h" +#include "libcef_dll/ctocpp/string_visitor_ctocpp.h" +#include "libcef_dll/ctocpp/task_ctocpp.h" +#include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h" +#include "libcef_dll/ctocpp/v8accessor_ctocpp.h" +#include "libcef_dll/ctocpp/v8handler_ctocpp.h" +#include "libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h" +#include "libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h" +#include "libcef_dll/ctocpp/write_handler_ctocpp.h" +#include "libcef_dll/transfer_util.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT int cef_execute_process(const struct _cef_main_args_t* args, + struct _cef_app_t* application, void* windows_sandbox_info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: args; type: struct_byref_const + DCHECK(args); + if (!args) + return 0; + // Unverified params: application, windows_sandbox_info + + // Translate param: args; type: struct_byref_const + CefMainArgs argsObj; + if (args) + argsObj.Set(*args, false); + + // Execute + int _retval = CefExecuteProcess( + argsObj, + CefAppCToCpp::Wrap(application), + windows_sandbox_info); + + // Return type: simple + return _retval; +} + +CEF_EXPORT int cef_initialize(const struct _cef_main_args_t* args, + const struct _cef_settings_t* settings, struct _cef_app_t* application, + void* windows_sandbox_info) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: args; type: struct_byref_const + DCHECK(args); + if (!args) + return 0; + // Verify param: settings; type: struct_byref_const + DCHECK(settings); + if (!settings) + return 0; + // Unverified params: application, windows_sandbox_info + + // Translate param: args; type: struct_byref_const + CefMainArgs argsObj; + if (args) + argsObj.Set(*args, false); + // Translate param: settings; type: struct_byref_const + CefSettings settingsObj; + if (settings) + settingsObj.Set(*settings, false); + + // Execute + bool _retval = CefInitialize( + argsObj, + settingsObj, + CefAppCToCpp::Wrap(application), + windows_sandbox_info); + + // Return type: bool + return _retval; +} + +CEF_EXPORT void cef_shutdown() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefShutdown(); + +#ifndef NDEBUG + // Check that all wrapper objects have been destroyed + DCHECK(base::AtomicRefCountIsZero( + &CefAllowCertificateErrorCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefAuthCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBeforeDownloadCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBinaryValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserHostCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBrowserProcessHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCompletionCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuParamsCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCookieVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventListenerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDownloadItemCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadItemCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragDataCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefEndTracingCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFileDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFocusHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFrameCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefGetGeolocationCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefKeyboardHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLifeSpanHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefListValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLoadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefMenuModelCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintJobCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefQuotaCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRenderProcessHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRequestHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefResourceBundleHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRunFileDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefSchemeHandlerFactoryCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWebPluginInfoCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginInfoVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginUnstableCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWriteHandlerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefXmlReaderCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefZipReaderCppToC::DebugObjCt)); +#endif // !NDEBUG +} + +CEF_EXPORT void cef_do_message_loop_work() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefDoMessageLoopWork(); +} + +CEF_EXPORT void cef_run_message_loop() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRunMessageLoop(); +} + +CEF_EXPORT void cef_quit_message_loop() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefQuitMessageLoop(); +} + +CEF_EXPORT void cef_set_osmodal_loop(int osModalLoop) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefSetOSModalLoop( + osModalLoop?true:false); +} + +CEF_EXPORT int cef_get_geolocation( + struct _cef_get_geolocation_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + + // Execute + bool _retval = CefGetGeolocation( + CefGetGeolocationCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_add_cross_origin_whitelist_entry( + const cef_string_t* source_origin, const cef_string_t* target_protocol, + const cef_string_t* target_domain, int allow_target_subdomains) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: source_origin; type: string_byref_const + DCHECK(source_origin); + if (!source_origin) + return 0; + // Verify param: target_protocol; type: string_byref_const + DCHECK(target_protocol); + if (!target_protocol) + return 0; + // Unverified params: target_domain + + // Execute + bool _retval = CefAddCrossOriginWhitelistEntry( + CefString(source_origin), + CefString(target_protocol), + CefString(target_domain), + allow_target_subdomains?true:false); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_remove_cross_origin_whitelist_entry( + const cef_string_t* source_origin, const cef_string_t* target_protocol, + const cef_string_t* target_domain, int allow_target_subdomains) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: source_origin; type: string_byref_const + DCHECK(source_origin); + if (!source_origin) + return 0; + // Verify param: target_protocol; type: string_byref_const + DCHECK(target_protocol); + if (!target_protocol) + return 0; + // Unverified params: target_domain + + // Execute + bool _retval = CefRemoveCrossOriginWhitelistEntry( + CefString(source_origin), + CefString(target_protocol), + CefString(target_domain), + allow_target_subdomains?true:false); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_clear_cross_origin_whitelist() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + bool _retval = CefClearCrossOriginWhitelist(); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref + DCHECK(path); + if (!path) + return 0; + + // Translate param: path; type: string_byref + CefString pathStr(path); + + // Execute + bool _retval = CefGetPath( + key, + pathStr); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_launch_process(struct _cef_command_line_t* command_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: command_line; type: refptr_same + DCHECK(command_line); + if (!command_line) + return 0; + + // Execute + bool _retval = CefLaunchProcess( + CefCommandLineCppToC::Unwrap(command_line)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_register_scheme_handler_factory( + const cef_string_t* scheme_name, const cef_string_t* domain_name, + struct _cef_scheme_handler_factory_t* factory) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: scheme_name; type: string_byref_const + DCHECK(scheme_name); + if (!scheme_name) + return 0; + // Unverified params: domain_name, factory + + // Execute + bool _retval = CefRegisterSchemeHandlerFactory( + CefString(scheme_name), + CefString(domain_name), + CefSchemeHandlerFactoryCToCpp::Wrap(factory)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_clear_scheme_handler_factories() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + bool _retval = CefClearSchemeHandlerFactories(); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + bool _retval = CefCurrentlyOn( + threadId); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_post_task(cef_thread_id_t threadId, + struct _cef_task_t* task) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task); + if (!task) + return 0; + + // Execute + bool _retval = CefPostTask( + threadId, + CefTaskCToCpp::Wrap(task)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId, + struct _cef_task_t* task, int64 delay_ms) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task); + if (!task) + return 0; + + // Execute + bool _retval = CefPostDelayedTask( + threadId, + CefTaskCToCpp::Wrap(task), + delay_ms); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_begin_tracing(const cef_string_t* categories, + struct _cef_completion_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: categories, callback + + // Execute + bool _retval = CefBeginTracing( + CefString(categories), + CefCompletionCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_end_tracing(const cef_string_t* tracing_file, + struct _cef_end_tracing_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: tracing_file, callback + + // Execute + bool _retval = CefEndTracing( + CefString(tracing_file), + CefEndTracingCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int64 cef_now_from_system_trace_time() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = CefNowFromSystemTraceTime(); + + // Return type: simple + return _retval; +} + +CEF_EXPORT int cef_parse_url(const cef_string_t* url, + struct _cef_urlparts_t* parts) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return 0; + // Verify param: parts; type: struct_byref + DCHECK(parts); + if (!parts) + return 0; + + // Translate param: parts; type: struct_byref + CefURLParts partsObj; + if (parts) + partsObj.AttachTo(*parts); + + // Execute + bool _retval = CefParseURL( + CefString(url), + partsObj); + + // Restore param: parts; type: struct_byref + if (parts) + partsObj.DetachTo(*parts); + + // Return type: bool + return _retval; +} + +CEF_EXPORT int cef_create_url(const struct _cef_urlparts_t* parts, + cef_string_t* url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: parts; type: struct_byref_const + DCHECK(parts); + if (!parts) + return 0; + // Verify param: url; type: string_byref + DCHECK(url); + if (!url) + return 0; + + // Translate param: parts; type: struct_byref_const + CefURLParts partsObj; + if (parts) + partsObj.Set(*parts, false); + // Translate param: url; type: string_byref + CefString urlStr(url); + + // Execute + bool _retval = CefCreateURL( + partsObj, + urlStr); + + // Return type: bool + return _retval; +} + +CEF_EXPORT cef_string_userfree_t cef_get_mime_type( + const cef_string_t* extension) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extension; type: string_byref_const + DCHECK(extension); + if (!extension) + return NULL; + + // Execute + CefString _retval = CefGetMimeType( + CefString(extension)); + + // Return type: string + return _retval.DetachToUserFree(); +} + +CEF_EXPORT void cef_get_extensions_for_mime_type(const cef_string_t* mime_type, + cef_string_list_t extensions) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: mime_type; type: string_byref_const + DCHECK(mime_type); + if (!mime_type) + return; + // Verify param: extensions; type: string_vec_byref + DCHECK(extensions); + if (!extensions) + return; + + // Translate param: extensions; type: string_vec_byref + std::vector extensionsList; + transfer_string_list_contents(extensions, extensionsList); + + // Execute + CefGetExtensionsForMimeType( + CefString(mime_type), + extensionsList); + + // Restore param: extensions; type: string_vec_byref + cef_string_list_clear(extensions); + transfer_string_list_contents(extensionsList, extensions); +} + +CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name, + const cef_string_t* javascript_code, struct _cef_v8handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extension_name; type: string_byref_const + DCHECK(extension_name); + if (!extension_name) + return 0; + // Verify param: javascript_code; type: string_byref_const + DCHECK(javascript_code); + if (!javascript_code) + return 0; + // Unverified params: handler + + // Execute + bool _retval = CefRegisterExtension( + CefString(extension_name), + CefString(javascript_code), + CefV8HandlerCToCpp::Wrap(handler)); + + // Return type: bool + return _retval; +} + +CEF_EXPORT void cef_visit_web_plugin_info( + struct _cef_web_plugin_info_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return; + + // Execute + CefVisitWebPluginInfo( + CefWebPluginInfoVisitorCToCpp::Wrap(visitor)); +} + +CEF_EXPORT void cef_refresh_web_plugins() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefreshWebPlugins(); +} + +CEF_EXPORT void cef_add_web_plugin_path(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefAddWebPluginPath( + CefString(path)); +} + +CEF_EXPORT void cef_add_web_plugin_directory(const cef_string_t* dir) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: dir; type: string_byref_const + DCHECK(dir); + if (!dir) + return; + + // Execute + CefAddWebPluginDirectory( + CefString(dir)); +} + +CEF_EXPORT void cef_remove_web_plugin_path(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefRemoveWebPluginPath( + CefString(path)); +} + +CEF_EXPORT void cef_unregister_internal_web_plugin(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefUnregisterInternalWebPlugin( + CefString(path)); +} + +CEF_EXPORT void cef_force_web_plugin_shutdown(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefForceWebPluginShutdown( + CefString(path)); +} + +CEF_EXPORT void cef_register_web_plugin_crash(const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + + // Execute + CefRegisterWebPluginCrash( + CefString(path)); +} + +CEF_EXPORT void cef_is_web_plugin_unstable(const cef_string_t* path, + struct _cef_web_plugin_unstable_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(path); + if (!path) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return; + + // Execute + CefIsWebPluginUnstable( + CefString(path), + CefWebPluginUnstableCallbackCToCpp::Wrap(callback)); +} + diff --git a/libcef_dll/libcef_dll.rc b/libcef_dll/libcef_dll.rc new file mode 100644 index 000000000..6e5752258 --- /dev/null +++ b/libcef_dll/libcef_dll.rc @@ -0,0 +1,143 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#include "include/cef_version.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#include ""include/version.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ALERT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Alert" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,184,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_CONFIRM DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Confirm" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_PROMPT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Prompt" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,18 + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + EDITTEXT IDC_PROMPTEDIT,15,33,210,14,ES_AUTOHSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION CEF_VERSION_MAJOR,CHROME_VERSION_BUILD,CEF_REVISION,0 + PRODUCTVERSION CEF_VERSION_MAJOR,CHROME_VERSION_BUILD,CEF_REVISION,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Chromium Embedded Framework (CEF) Dynamic Link Library" + VALUE "FileVersion", MAKE_STRING(CEF_VERSION_MAJOR) "." MAKE_STRING(CHROME_VERSION_BUILD) "." MAKE_STRING(CEF_REVISION) + VALUE "InternalName", "libcef" + VALUE "LegalCopyright", "Copyright (C) " MAKE_STRING(COPYRIGHT_YEAR) " The Chromium Embedded Framework Authors" + VALUE "OriginalFilename", "libcef.dll" + VALUE "ProductName", "Chromium Embedded Framework (CEF) Dynamic Link Library" + VALUE "ProductVersion", MAKE_STRING(CEF_VERSION_MAJOR) "." MAKE_STRING(CHROME_VERSION_BUILD) "." MAKE_STRING(CEF_REVISION) + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/libcef_dll/libcef_dll2.cc b/libcef_dll/libcef_dll2.cc new file mode 100644 index 000000000..1a5172313 --- /dev/null +++ b/libcef_dll/libcef_dll2.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// + +#include "include/cef_version.h" +#include + +CEF_EXPORT int cef_build_revision() { + return CEF_REVISION; +} + +CEF_EXPORT int cef_version_info(int entry) { + switch (entry) { + case 0: return CEF_VERSION_MAJOR; + case 1: return CEF_REVISION; + case 2: return CHROME_VERSION_MAJOR; + case 3: return CHROME_VERSION_MINOR; + case 4: return CHROME_VERSION_BUILD; + case 5: return CHROME_VERSION_PATCH; + default: return 0; + } +} + +CEF_EXPORT const char* cef_api_hash(int entry) { + switch (entry) { + case 0: return CEF_API_HASH_PLATFORM; + case 1: return CEF_API_HASH_UNIVERSAL; + default: return NULL; + } +} diff --git a/libcef_dll/resource.h b/libcef_dll/resource.h new file mode 100644 index 000000000..cbeef193d --- /dev/null +++ b/libcef_dll/resource.h @@ -0,0 +1,26 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by libcef_dll.rc +// + +// Avoid files associated with MacOS +#define _X86_ + +#define IDD_ALERT 130 +#define IDD_CONFIRM 131 +#define IDD_PROMPT 132 +#define IDC_PROMPTEDIT 1000 +#define IDC_DIALOGTEXT 1001 + + +// 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 32000 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/libcef_dll/sandbox/sandbox_win.cc b/libcef_dll/sandbox/sandbox_win.cc new file mode 100644 index 000000000..9f5ee10df --- /dev/null +++ b/libcef_dll/sandbox/sandbox_win.cc @@ -0,0 +1,39 @@ +// Copyright 2013 The Chromium Embedded Framework Authors. Portions Copyright +// 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 this first to avoid conflicts with cef_macros.h. +#include "base/macros.h" + +#include "include/cef_sandbox_win.h" + +#include "sandbox/win/src/process_mitigations.h" +#include "sandbox/win/src/sandbox_factory.h" + +namespace { + +// From content/app/startup_helper_win.cc: +void InitializeSandboxInfo(sandbox::SandboxInterfaceInfo* info) { + info->broker_services = sandbox::SandboxFactory::GetBrokerServices(); + if (!info->broker_services) { + info->target_services = sandbox::SandboxFactory::GetTargetServices(); + } else { + // Ensure the proper mitigations are enforced for the browser process. + sandbox::ApplyProcessMitigationsToCurrentProcess( + sandbox::MITIGATION_DEP | + sandbox::MITIGATION_DEP_NO_ATL_THUNK); + } +} + +} // namespace + +void* cef_sandbox_info_create() { + sandbox::SandboxInterfaceInfo* info = new sandbox::SandboxInterfaceInfo(); + memset(info, 0, sizeof(sandbox::SandboxInterfaceInfo)); + InitializeSandboxInfo(info); + return info; +} + +void cef_sandbox_info_destroy(void* sandbox_info) { + delete static_cast(sandbox_info); +} diff --git a/libcef_dll/transfer_util.cpp b/libcef_dll/transfer_util.cpp new file mode 100644 index 000000000..e9d8d4e22 --- /dev/null +++ b/libcef_dll/transfer_util.cpp @@ -0,0 +1,72 @@ +// 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. + +#include "transfer_util.h" + +void transfer_string_list_contents(cef_string_list_t fromList, + StringList& toList) +{ + int size = cef_string_list_size(fromList); + CefString value; + + for(int i = 0; i < size; i++) { + cef_string_list_value(fromList, i, value.GetWritableStruct()); + toList.push_back(value); + } +} + +void transfer_string_list_contents(const StringList& fromList, + cef_string_list_t toList) +{ + size_t size = fromList.size(); + for(size_t i = 0; i < size; ++i) + cef_string_list_append(toList, fromList[i].GetStruct()); +} + +void transfer_string_map_contents(cef_string_map_t fromMap, + StringMap& toMap) +{ + int size = cef_string_map_size(fromMap); + CefString key, value; + + for(int i = 0; i < size; ++i) { + cef_string_map_key(fromMap, i, key.GetWritableStruct()); + cef_string_map_value(fromMap, i, value.GetWritableStruct()); + + toMap.insert(std::make_pair(key, value)); + } +} + +void transfer_string_map_contents(const StringMap& fromMap, + cef_string_map_t toMap) +{ + StringMap::const_iterator it = fromMap.begin(); + for(; it != fromMap.end(); ++it) + cef_string_map_append(toMap, it->first.GetStruct(), it->second.GetStruct()); +} + +void transfer_string_multimap_contents(cef_string_multimap_t fromMap, + StringMultimap& toMap) +{ + int size = cef_string_multimap_size(fromMap); + CefString key, value; + + for(int i = 0; i < size; ++i) { + cef_string_multimap_key(fromMap, i, key.GetWritableStruct()); + cef_string_multimap_value(fromMap, i, value.GetWritableStruct()); + + toMap.insert(std::make_pair(key, value)); + } +} + +void transfer_string_multimap_contents(const StringMultimap& fromMap, + cef_string_multimap_t toMap) +{ + StringMultimap::const_iterator it = fromMap.begin(); + for(; it != fromMap.end(); ++it) { + cef_string_multimap_append(toMap, + it->first.GetStruct(), + it->second.GetStruct()); + } +} diff --git a/libcef_dll/transfer_util.h b/libcef_dll/transfer_util.h new file mode 100644 index 000000000..88dff1a38 --- /dev/null +++ b/libcef_dll/transfer_util.h @@ -0,0 +1,37 @@ +// 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_LIBCEF_DLL_TRANSFER_UTIL_H_ +#define CEF_LIBCEF_DLL_TRANSFER_UTIL_H_ +#pragma once + +#include +#include + +#include "include/internal/cef_string_list.h" +#include "include/internal/cef_string_map.h" +#include "include/internal/cef_string_multimap.h" + +// Copy contents from one list type to another. +typedef std::vector StringList; +void transfer_string_list_contents(cef_string_list_t fromList, + StringList& toList); +void transfer_string_list_contents(const StringList& fromList, + cef_string_list_t toList); + +// Copy contents from one map type to another. +typedef std::map StringMap; +void transfer_string_map_contents(cef_string_map_t fromMap, + StringMap& toMap); +void transfer_string_map_contents(const StringMap& fromMap, + cef_string_map_t toMap); + +// Copy contents from one map type to another. +typedef std::multimap StringMultimap; +void transfer_string_multimap_contents(cef_string_multimap_t fromMap, + StringMultimap& toMap); +void transfer_string_multimap_contents(const StringMultimap& fromMap, + cef_string_multimap_t toMap); + +#endif // CEF_LIBCEF_DLL_TRANSFER_UTIL_H_ diff --git a/libcef_dll/wrapper/cef_browser_info_map.h b/libcef_dll/wrapper/cef_browser_info_map.h new file mode 100644 index 000000000..c2a82d6c3 --- /dev/null +++ b/libcef_dll/wrapper/cef_browser_info_map.h @@ -0,0 +1,265 @@ +// 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_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ +#define CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ +#pragma once + +#include + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" + +// Default traits for CefBrowserInfoMap. Override to provide different object +// destruction behavior. +template +struct DefaultCefBrowserInfoMapTraits { + static void Destruct(ObjectType info) { + delete info; + } +}; + +// Maps an arbitrary IdType to an arbitrary ObjectType on a per-browser basis. +template > +class CefBrowserInfoMap { + public: + // Implement this interface to visit and optionally delete objects in the map. + class Visitor { + public: + typedef IdType InfoIdType; + typedef ObjectType InfoObjectType; + + // Called once for each info object. Set |remove| to true to remove the + // object from the map. It is safe to destruct removed objects in this + // callback. Return true to continue iterating or false to stop iterating. + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) =0; + + protected: + virtual ~Visitor() {} + }; + + CefBrowserInfoMap() {} + + ~CefBrowserInfoMap() { + clear(); + } + + // Add an object associated with the specified ID values. + void Add(int browser_id, IdType info_id, ObjectType info) { + InfoMap* info_map = NULL; + typename BrowserInfoMap::const_iterator it_browser = + browser_info_map_.find(browser_id); + if (it_browser == browser_info_map_.end()) { + // No InfoMap exists for the browser ID so create it. + info_map = new InfoMap; + browser_info_map_.insert(std::make_pair(browser_id, info_map)); + } else { + info_map = it_browser->second; + // The specified ID should not already exist in the map. + DCHECK(info_map->find(info_id) == info_map->end()); + } + + info_map->insert(std::make_pair(info_id, info)); + } + + // Find the object with the specified ID values. |visitor| can optionally be + // used to evaluate or remove the object at the same time. If the object is + // removed using the Visitor the caller is responsible for destroying it. + ObjectType Find(int browser_id, IdType info_id, Visitor* vistor) { + if (browser_info_map_.empty()) + return ObjectType(); + + typename BrowserInfoMap::iterator it_browser = + browser_info_map_.find(browser_id); + if (it_browser == browser_info_map_.end()) + return ObjectType(); + + InfoMap* info_map = it_browser->second; + typename InfoMap::iterator it_info = info_map->find(info_id); + if (it_info == info_map->end()) + return ObjectType(); + + ObjectType info = it_info->second; + + bool remove = false; + if (vistor) + vistor->OnNextInfo(browser_id, it_info->first, info, &remove); + if (remove) { + info_map->erase(it_info); + + if (info_map->empty()) { + // No more entries in the InfoMap so remove it. + browser_info_map_.erase(it_browser); + delete info_map; + } + } + + return info; + } + + // Find all objects. If any objects are removed using the Visitor the caller + // is responsible for destroying them. + void FindAll(Visitor* visitor) { + DCHECK(visitor); + + if (browser_info_map_.empty()) + return; + + bool remove, keepgoing; + + typename BrowserInfoMap::iterator it_browser = browser_info_map_.begin(); + while (it_browser != browser_info_map_.end()) { + InfoMap* info_map = it_browser->second; + + typename InfoMap::iterator it_info = info_map->begin(); + while (it_info != info_map->end()) { + remove = false; + keepgoing = visitor->OnNextInfo(it_browser->first, it_info->first, + it_info->second, &remove); + + if (remove) + info_map->erase(it_info++); + else + ++it_info; + + if (!keepgoing) + break; + } + + if (info_map->empty()) { + // No more entries in the InfoMap so remove it. + browser_info_map_.erase(it_browser++); + delete info_map; + } else { + ++it_browser; + } + + if (!keepgoing) + break; + } + } + + // Find all objects associated with the specified browser. If any objects are + // removed using the Visitor the caller is responsible for destroying them. + void FindAll(int browser_id, Visitor* visitor) { + DCHECK(visitor); + + if (browser_info_map_.empty()) + return; + + typename BrowserInfoMap::iterator it_browser = + browser_info_map_.find(browser_id); + if (it_browser == browser_info_map_.end()) + return; + + InfoMap* info_map = it_browser->second; + bool remove, keepgoing; + + typename InfoMap::iterator it_info = info_map->begin(); + while (it_info != info_map->end()) { + remove = false; + keepgoing = visitor->OnNextInfo(browser_id, it_info->first, + it_info->second, &remove); + + if (remove) + info_map->erase(it_info++); + else + ++it_info; + + if (!keepgoing) + break; + } + + if (info_map->empty()) { + // No more entries in the InfoMap so remove it. + browser_info_map_.erase(it_browser); + delete info_map; + } + } + + // Returns true if the map is empty. + bool empty() const { return browser_info_map_.empty(); } + + // Returns the number of objects in the map. + size_t size() const { + if (browser_info_map_.empty()) + return 0; + + size_t size = 0; + typename BrowserInfoMap::const_iterator it_browser = + browser_info_map_.begin(); + for (; it_browser != browser_info_map_.end(); ++it_browser) + size += it_browser->second->size(); + return size; + } + + // Returns the number of objects in the map that are associated with the + // specified browser. + size_t size(int browser_id) const { + if (browser_info_map_.empty()) + return 0; + + typename BrowserInfoMap::const_iterator it_browser = + browser_info_map_.find(browser_id); + if (it_browser != browser_info_map_.end()) + return it_browser->second->size(); + + return 0; + } + + // Remove all objects from the map. The objects will be destructed. + void clear() { + if (browser_info_map_.empty()) + return; + + typename BrowserInfoMap::const_iterator it_browser = + browser_info_map_.begin(); + for (; it_browser != browser_info_map_.end(); ++it_browser) { + InfoMap* info_map = it_browser->second; + typename InfoMap::const_iterator it_info = info_map->begin(); + for (; it_info != info_map->end(); ++it_info) + Traits::Destruct(it_info->second); + delete info_map; + } + browser_info_map_.clear(); + } + + // Remove all objects from the map that are associated with the specified + // browser. The objects will be destructed. + void clear(int browser_id) { + if (browser_info_map_.empty()) + return; + + typename BrowserInfoMap::iterator it_browser = + browser_info_map_.find(browser_id); + if (it_browser == browser_info_map_.end()) + return; + + InfoMap* info_map = it_browser->second; + typename InfoMap::const_iterator it_info = info_map->begin(); + for (; it_info != info_map->end(); ++it_info) + Traits::Destruct(it_info->second); + + browser_info_map_.erase(it_browser); + delete info_map; + } + + private: + // Map IdType to ObjectType instance. + typedef std::map InfoMap; + // Map browser ID to InfoMap instance. + typedef std::map BrowserInfoMap; + + BrowserInfoMap browser_info_map_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoMap); +}; + + +#endif // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ diff --git a/libcef_dll/wrapper/cef_byte_read_handler.cc b/libcef_dll/wrapper/cef_byte_read_handler.cc new file mode 100644 index 000000000..3d29feebf --- /dev/null +++ b/libcef_dll/wrapper/cef_byte_read_handler.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "include/wrapper/cef_byte_read_handler.h" + +#include +#include +#include + +CefByteReadHandler::CefByteReadHandler(const unsigned char* bytes, size_t size, + CefRefPtr source) + : bytes_(bytes), size_(size), offset_(0), source_(source) { +} + +size_t CefByteReadHandler::Read(void* ptr, size_t size, size_t n) { + base::AutoLock lock_scope(lock_); + size_t s = static_cast(size_ - offset_) / size; + size_t ret = std::min(n, s); + memcpy(ptr, bytes_ + offset_, ret * size); + offset_ += ret * size; + return ret; +} + +int CefByteReadHandler::Seek(int64 offset, int whence) { + int rv = -1L; + base::AutoLock lock_scope(lock_); + switch (whence) { + case SEEK_CUR: + if (offset_ + offset > size_ || offset_ + offset < 0) + break; + offset_ += offset; + rv = 0; + break; + case SEEK_END: { +#if defined(OS_WIN) + int64 offset_abs = _abs64(offset); +#else + int64 offset_abs = std::abs(offset); +#endif + if (offset_abs > size_) + break; + offset_ = size_ - offset_abs; + rv = 0; + break; + } + case SEEK_SET: + if (offset > size_ || offset < 0) + break; + offset_ = offset; + rv = 0; + break; + } + + return rv; +} + +int64 CefByteReadHandler::Tell() { + base::AutoLock lock_scope(lock_); + return offset_; +} + +int CefByteReadHandler::Eof() { + base::AutoLock lock_scope(lock_); + return (offset_ >= size_); +} diff --git a/libcef_dll/wrapper/cef_closure_task.cc b/libcef_dll/wrapper/cef_closure_task.cc new file mode 100644 index 000000000..0b4939053 --- /dev/null +++ b/libcef_dll/wrapper/cef_closure_task.cc @@ -0,0 +1,42 @@ +// 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 "include/wrapper/cef_closure_task.h" +#include "include/base/cef_callback.h" + +namespace { + +class CefClosureTask : public CefTask { + public: + explicit CefClosureTask(const base::Closure& closure) + : closure_(closure) { + } + + // CefTask method + virtual void Execute() OVERRIDE { + closure_.Run(); + closure_.Reset(); + } + + private: + base::Closure closure_; + + IMPLEMENT_REFCOUNTING(CefClosureTask); + DISALLOW_COPY_AND_ASSIGN(CefClosureTask); +}; + +} // namespace + +CefRefPtr CefCreateClosureTask(const base::Closure& closure) { + return new CefClosureTask(closure); +} + +bool CefPostTask(CefThreadId threadId, const base::Closure& closure) { + return CefPostTask(threadId, new CefClosureTask(closure)); +} + +bool CefPostDelayedTask(CefThreadId threadId, const base::Closure& closure, + int64 delay_ms) { + return CefPostDelayedTask(threadId, new CefClosureTask(closure), delay_ms); +} diff --git a/libcef_dll/wrapper/cef_message_router.cc b/libcef_dll/wrapper/cef_message_router.cc new file mode 100644 index 000000000..8966ffa52 --- /dev/null +++ b/libcef_dll/wrapper/cef_message_router.cc @@ -0,0 +1,1149 @@ +// 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 "include/wrapper/cef_message_router.h" + +#include +#include + +#include "include/base/cef_bind.h" +#include "include/base/cef_macros.h" +#include "include/cef_task.h" +#include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_helpers.h" +#include "libcef_dll/wrapper/cef_browser_info_map.h" + +namespace { + +// ID value reserved for internal use. +const int kReservedId = 0; + +// Appended to the JS function name for related IPC messages. +const char kMessageSuffix[] = "Msg"; + +// JS object member argument names for cefQuery. +const char kMemberRequest[] = "request"; +const char kMemberOnSuccess[] = "onSuccess"; +const char kMemberOnFailure[] = "onFailure"; +const char kMemberPersistent[] = "persistent"; + +// Default error information when a query is canceled. +const int kCanceledErrorCode = -1; +const char kCanceledErrorMessage[] = "The query has been canceled"; + +// Validate configuration settings. +bool ValidateConfig(CefMessageRouterConfig& config) { + // Must specify function names. + if (config.js_cancel_function.empty() || + config.js_query_function.empty()) { + return false; + } + + return true; +} + +// Helper template for generated ID values. +template +class IdGenerator { + public: + IdGenerator() : next_id_(kReservedId) {} + + T GetNextId() { + T id = ++next_id_; + if (id == kReservedId) // In case the integer value wraps. + id = ++next_id_; + return id; + } + + private: + T next_id_; + + DISALLOW_COPY_AND_ASSIGN(IdGenerator); +}; + +// Browser-side router implementation. +class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { + public: + // Implementation of the Callback interface. + class CallbackImpl : public CefMessageRouterBrowserSide::Callback { + public: + CallbackImpl(CefRefPtr router, + int browser_id, + int64 query_id, + bool persistent) + : router_(router), + browser_id_(browser_id), + query_id_(query_id), + persistent_(persistent) { + } + virtual ~CallbackImpl() { + // Hitting this DCHECK means that you didn't call Success or Failure + // on the Callback after returning true from Handler::OnQuery. You must + // call Failure to terminate persistent queries. + DCHECK(!router_); + } + + virtual void Success(const CefString& response) OVERRIDE { + if (!CefCurrentlyOn(TID_UI)) { + // Must execute on the UI thread to access member variables. + CefPostTask(TID_UI, + base::Bind(&CallbackImpl::Success, this, response)); + return; + } + + if (router_) { + CefPostTask(TID_UI, + base::Bind(&CefMessageRouterBrowserSideImpl::OnCallbackSuccess, + router_, browser_id_, query_id_, response)); + + if (!persistent_) { + // Non-persistent callbacks are only good for a single use. + router_ = NULL; + } + } + } + + virtual void Failure(int error_code, + const CefString& error_message) OVERRIDE { + if (!CefCurrentlyOn(TID_UI)) { + // Must execute on the UI thread to access member variables. + CefPostTask(TID_UI, + base::Bind(&CallbackImpl::Failure, this, + error_code, error_message)); + return; + } + + if (router_) { + CefPostTask(TID_UI, + base::Bind(&CefMessageRouterBrowserSideImpl::OnCallbackFailure, + router_, browser_id_, query_id_, error_code, + error_message)); + + // Failure always invalidates the callback. + router_ = NULL; + } + } + + void Detach() { + CEF_REQUIRE_UI_THREAD(); + router_ = NULL; + } + + private: + CefRefPtr router_; + const int browser_id_; + const int64 query_id_; + const bool persistent_; + + IMPLEMENT_REFCOUNTING(CallbackImpl); + }; + + explicit CefMessageRouterBrowserSideImpl(const CefMessageRouterConfig& config) + : config_(config), + query_message_name_( + config.js_query_function.ToString() + kMessageSuffix), + cancel_message_name_( + config.js_cancel_function.ToString() + kMessageSuffix) { + } + + virtual ~CefMessageRouterBrowserSideImpl() { + // There should be no pending queries when the router is deleted. + DCHECK(browser_query_info_map_.empty()); + } + + virtual bool AddHandler(Handler* handler, bool first) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + if (handler_set_.find(handler) == handler_set_.end()) { + handler_set_.insert( + first ? handler_set_.begin() : handler_set_.end(), handler); + return true; + } + return false; + } + + virtual bool RemoveHandler(Handler* handler) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + if (handler_set_.erase(handler) > 0) { + CancelPendingFor(NULL, handler, true); + return true; + } + return false; + } + + virtual void CancelPending(CefRefPtr browser, + Handler* handler) OVERRIDE { + CancelPendingFor(browser, handler, true); + } + + virtual int GetPendingCount(CefRefPtr browser, + Handler* handler) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + + if (browser_query_info_map_.empty()) + return 0; + + if (handler) { + // Need to iterate over each QueryInfo object to test the handler. + class Visitor : public BrowserQueryInfoMap::Visitor { + public: + explicit Visitor(Handler* handler) + : handler_(handler), + count_(0) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + if (info->handler == handler_) + count_++; + return true; + } + + int count() const { return count_; } + + private: + Handler* handler_; + int count_; + }; + + Visitor visitor(handler); + + if (browser.get()) { + // Count queries associated with the specified browser. + browser_query_info_map_.FindAll( + browser->GetIdentifier(), &visitor); + } else { + // Count all queries for all browsers. + browser_query_info_map_.FindAll(&visitor); + } + + return visitor.count(); + } else if (browser.get()) { + return static_cast( + browser_query_info_map_.size(browser->GetIdentifier())); + } else { + return static_cast(browser_query_info_map_.size()); + } + + return 0; + } + + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE { + CancelPendingFor(browser, NULL, false); + } + + virtual void OnRenderProcessTerminated( + CefRefPtr browser) OVERRIDE { + CancelPendingFor(browser, NULL, false); + } + + virtual void OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { + if (frame->IsMain()) + CancelPendingFor(browser, NULL, false); + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + CEF_REQUIRE_UI_THREAD(); + + const std::string& message_name = message->GetName(); + if (message_name == query_message_name_) { + CefRefPtr args = message->GetArgumentList(); + DCHECK_EQ(args->GetSize(), 6U); + + const int64 frame_id = CefInt64Set(args->GetInt(0), args->GetInt(1)); + const int context_id = args->GetInt(2); + const int request_id = args->GetInt(3); + const CefString& request = args->GetString(4); + const bool persistent = args->GetBool(5); + + if (handler_set_.empty()) { + // No handlers so cancel the query. + CancelUnhandledQuery(browser, context_id, request_id); + return true; + } + + const int browser_id = browser->GetIdentifier(); + const int64 query_id = query_id_generator_.GetNextId(); + + CefRefPtr frame = browser->GetFrame(frame_id); + CefRefPtr callback( + new CallbackImpl(this, browser_id, query_id, persistent)); + + // Make a copy of the handler list in case the user adds or removes a + // handler while we're iterating. + HandlerSet handler_set = handler_set_; + + bool handled = false; + HandlerSet::const_iterator it_handler = handler_set.begin(); + for (; it_handler != handler_set.end(); ++it_handler) { + handled = (*it_handler)->OnQuery(browser, frame, query_id, request, + persistent, callback.get()); + if (handled) + break; + } + + // If the query isn't handled nothing should be keeping a reference to + // the callback. + DCHECK(handled || callback->HasOneRef()); + + if (handled) { + // Persist the query information until the callback executes. + // It's safe to do this here because the callback will execute + // asynchronously. + QueryInfo* info = new QueryInfo; + info->browser = browser; + info->frame_id = frame_id; + info->context_id = context_id; + info->request_id = request_id; + info->persistent = persistent; + info->callback = callback; + info->handler = *(it_handler); + browser_query_info_map_.Add(browser_id, query_id, info); + } else { + // Invalidate the callback. + callback->Detach(); + + // No one chose to handle the query so cancel it. + CancelUnhandledQuery(browser, context_id, request_id); + } + + return true; + } else if (message_name == cancel_message_name_) { + CefRefPtr args = message->GetArgumentList(); + DCHECK_EQ(args->GetSize(), 2U); + + const int browser_id = browser->GetIdentifier(); + const int context_id = args->GetInt(0); + const int request_id = args->GetInt(1); + + CancelPendingRequest(browser_id, context_id, request_id); + return true; + } + + return false; + } + + private: + // Structure representing a pending query. + struct QueryInfo { + // Browser and frame originated the query. + CefRefPtr browser; + int64 frame_id; + + // IDs that uniquely identify the query in the renderer process. These + // values are opaque to the browser process but must be returned with the + // response. + int context_id; + int request_id; + + // True if the query is persistent. + bool persistent; + + // Callback associated with the query that must be detached when the query + // is canceled. + CefRefPtr callback; + + // Handler that should be notified if the query is automatically canceled. + Handler* handler; + }; + + // Retrieve a QueryInfo object from the map based on the browser-side query + // ID. If |always_remove| is true then the QueryInfo object will always be + // removed from the map. Othewise, the QueryInfo object will only be removed + // if the query is non-persistent. If |removed| is true the caller is + // responsible for deleting the returned QueryInfo object. + QueryInfo* GetQueryInfo(int browser_id, + int64 query_id, + bool always_remove, + bool* removed) { + class Visitor : public BrowserQueryInfoMap::Visitor { + public: + explicit Visitor(bool always_remove) + : always_remove_(always_remove), + removed_(false) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + *remove = removed_ = (always_remove_ || !info->persistent); + return true; + } + + bool removed() const { return removed_; } + + private: + const bool always_remove_; + bool removed_; + }; + + Visitor visitor(always_remove); + QueryInfo* info = + browser_query_info_map_.Find(browser_id, query_id, &visitor); + if (info) + *removed = visitor.removed(); + return info; + } + + // Called by CallbackImpl on success. + void OnCallbackSuccess(int browser_id, + int64 query_id, + const CefString& response) { + CEF_REQUIRE_UI_THREAD(); + + bool removed; + QueryInfo* info = GetQueryInfo(browser_id, query_id, false, &removed); + if (info) { + SendQuerySuccess(info, response); + if (removed) + delete info; + } + } + + // Called by CallbackImpl on failure. + void OnCallbackFailure(int browser_id, + int64 query_id, + int error_code, + const CefString& error_message) { + CEF_REQUIRE_UI_THREAD(); + + bool removed; + QueryInfo* info = GetQueryInfo(browser_id, query_id, true, &removed); + if (info) { + SendQueryFailure(info, error_code, error_message); + DCHECK(removed); + delete info; + } + } + + void SendQuerySuccess(QueryInfo* info, + const CefString& response) { + SendQuerySuccess(info->browser, info->context_id, info->request_id, + response); + } + + void SendQuerySuccess(CefRefPtr browser, + int context_id, + int request_id, + const CefString& response) { + CefRefPtr message = + CefProcessMessage::Create(query_message_name_); + CefRefPtr args = message->GetArgumentList(); + args->SetInt(0, context_id); + args->SetInt(1, request_id); + args->SetBool(2, true); // Indicates a success result. + args->SetString(3, response); + browser->SendProcessMessage(PID_RENDERER, message); + } + + void SendQueryFailure(QueryInfo* info, + int error_code, + const CefString& error_message) { + SendQueryFailure(info->browser, info->context_id, info->request_id, + error_code, error_message); + } + + void SendQueryFailure(CefRefPtr browser, + int context_id, + int request_id, + int error_code, + const CefString& error_message) { + CefRefPtr message = + CefProcessMessage::Create(query_message_name_); + CefRefPtr args = message->GetArgumentList(); + args->SetInt(0, context_id); + args->SetInt(1, request_id); + args->SetBool(2, false); // Indicates a failure result. + args->SetInt(3, error_code); + args->SetString(4, error_message); + browser->SendProcessMessage(PID_RENDERER, message); + } + + // Cancel a query that has not been sent to a handler. + void CancelUnhandledQuery(CefRefPtr browser, int context_id, + int request_id) { + SendQueryFailure(browser, context_id, request_id, kCanceledErrorCode, + kCanceledErrorMessage); + } + + // Cancel a query that has already been sent to a handler. + void CancelQuery(int64 query_id, QueryInfo* info, bool notify_renderer) { + if (notify_renderer) + SendQueryFailure(info, kCanceledErrorCode, kCanceledErrorMessage); + + CefRefPtr frame = info->browser->GetFrame(info->frame_id); + info->handler->OnQueryCanceled(info->browser, frame, query_id); + + // Invalidate the callback. + info->callback->Detach(); + } + + // Cancel all pending queries associated with either |browser| or |handler|. + // If both |browser| and |handler| are NULL all pending queries will be + // canceled. Set |notify_renderer| to true if the renderer should be notified. + void CancelPendingFor(CefRefPtr browser, + Handler* handler, + bool notify_renderer) { + if (!CefCurrentlyOn(TID_UI)) { + // Must execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&CefMessageRouterBrowserSideImpl::CancelPendingFor, this, + browser, handler, notify_renderer)); + return; + } + + if (browser_query_info_map_.empty()) + return; + + class Visitor : public BrowserQueryInfoMap::Visitor { + public: + Visitor(CefMessageRouterBrowserSideImpl* router, + Handler* handler, + bool notify_renderer) + : router_(router), + handler_(handler), + notify_renderer_(notify_renderer) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + if (!handler_ || info->handler == handler_) { + *remove = true; + router_->CancelQuery(info_id, info, notify_renderer_); + delete info; + } + return true; + } + + private: + CefMessageRouterBrowserSideImpl* router_; + Handler* handler_; + const bool notify_renderer_; + }; + + Visitor visitor(this, handler, notify_renderer); + + if (browser.get()) { + // Cancel all queries associated with the specified browser. + browser_query_info_map_.FindAll( + browser->GetIdentifier(), &visitor); + } else { + // Cancel all queries for all browsers. + browser_query_info_map_.FindAll(&visitor); + } + } + + // Cancel a query based on the renderer-side IDs. If |request_id| is + // kReservedId all requests associated with |context_id| will be canceled. + void CancelPendingRequest(int browser_id, int context_id, int request_id) { + class Visitor : public BrowserQueryInfoMap::Visitor { + public: + Visitor(CefMessageRouterBrowserSideImpl* router, + int context_id, + int request_id) + : router_(router), + context_id_(context_id), + request_id_(request_id) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + if (info->context_id == context_id_ && + (request_id_ == kReservedId || info->request_id == request_id_)) { + *remove = true; + router_->CancelQuery(info_id, info, false); + delete info; + + // Stop iterating if only canceling a single request. + return (request_id_ == kReservedId); + } + return true; + } + + private: + CefMessageRouterBrowserSideImpl* router_; + const int context_id_; + const int request_id_; + }; + + Visitor visitor(this, context_id, request_id); + browser_query_info_map_.FindAll(browser_id, &visitor); + } + + const CefMessageRouterConfig config_; + const std::string query_message_name_; + const std::string cancel_message_name_; + + IdGenerator query_id_generator_; + + // Set of currently registered handlers. An entry is added when a handler is + // registered and removed when a handler is unregistered. + typedef std::set HandlerSet; + HandlerSet handler_set_; + + // Map of query ID to QueryInfo instance. An entry is added when a Handler + // indicates that it will handle the query and removed when either the query + // is completed via the Callback, the query is explicitly canceled from the + // renderer process, or the associated context is (or will be) released. + typedef CefBrowserInfoMap BrowserQueryInfoMap; + BrowserQueryInfoMap browser_query_info_map_; + + DISALLOW_COPY_AND_ASSIGN(CefMessageRouterBrowserSideImpl); +}; + +// Renderer-side router implementation. +class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { + public: + class V8HandlerImpl : public CefV8Handler { + public: + V8HandlerImpl( + CefRefPtr router, + const CefMessageRouterConfig& config) + : router_(router), + config_(config), + context_id_(kReservedId) { + } + + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE { + if (name == config_.js_query_function) { + if (arguments.size() != 1 || !arguments[0]->IsObject()) { + exception = "Invalid arguments; expecting a single object"; + return true; + } + + CefRefPtr arg = arguments[0]; + + CefRefPtr requestVal = arg->GetValue(kMemberRequest); + if (!requestVal.get() || !requestVal->IsString()) { + exception = "Invalid arguments; object member '"+ + std::string(kMemberRequest) +"' is required and must " + "have type string"; + return true; + } + + CefRefPtr successVal = NULL; + if (arg->HasValue(kMemberOnSuccess)) { + successVal = arg->GetValue(kMemberOnSuccess); + if (!successVal->IsFunction()) { + exception = "Invalid arguments; object member '"+ + std::string(kMemberOnSuccess) +"' must have type " + "function"; + return true; + } + } + + CefRefPtr failureVal = NULL; + if (arg->HasValue(kMemberOnFailure)) { + failureVal = arg->GetValue(kMemberOnFailure); + if (!failureVal->IsFunction()) { + exception = "Invalid arguments; object member '"+ + std::string(kMemberOnFailure) +"' must have type " + "function"; + return true; + } + } + + CefRefPtr persistentVal = NULL; + if (arg->HasValue(kMemberPersistent)) { + persistentVal = arg->GetValue(kMemberPersistent); + if (!persistentVal->IsBool()) { + exception = "Invalid arguments; object member '"+ + std::string(kMemberPersistent) +"' must have type " + "boolean"; + return true; + } + } + + CefRefPtr context = CefV8Context::GetCurrentContext(); + const int context_id = GetIDForContext(context); + const int64 frame_id = context->GetFrame()->GetIdentifier(); + const bool persistent = + (persistentVal.get() && persistentVal->GetBoolValue()); + + const int request_id = router_->SendQuery( + context->GetBrowser(), frame_id, context_id, + requestVal->GetStringValue(), persistent, successVal, failureVal); + retval = CefV8Value::CreateInt(request_id); + return true; + } else if (name == config_.js_cancel_function) { + if (arguments.size() != 1 || !arguments[0]->IsInt()) { + exception = "Invalid arguments; expecting a single integer"; + return true; + } + + bool result = false; + const int request_id = arguments[0]->GetIntValue(); + if (request_id != kReservedId) { + CefRefPtr context = CefV8Context::GetCurrentContext(); + const int context_id = GetIDForContext(context); + const int64 frame_id = context->GetFrame()->GetIdentifier(); + + result = router_->SendCancel(context->GetBrowser(), frame_id, + context_id, request_id); + } + retval = CefV8Value::CreateBool(result); + return true; + } + + return false; + } + + private: + // Don't create the context ID until it's actually needed. + int GetIDForContext(CefRefPtr context) { + if (context_id_ == kReservedId) + context_id_ = router_->CreateIDForContext(context); + return context_id_; + } + + CefRefPtr router_; + const CefMessageRouterConfig config_; + int context_id_; + + IMPLEMENT_REFCOUNTING(V8HandlerImpl); + }; + + explicit CefMessageRouterRendererSideImpl(const CefMessageRouterConfig& config) + : config_(config), + query_message_name_( + config.js_query_function.ToString() + kMessageSuffix), + cancel_message_name_( + config.js_cancel_function.ToString() + kMessageSuffix) { + } + + virtual ~CefMessageRouterRendererSideImpl() { + } + + virtual int GetPendingCount(CefRefPtr browser, + CefRefPtr context) OVERRIDE { + CEF_REQUIRE_RENDERER_THREAD(); + + if (browser_request_info_map_.empty()) + return 0; + + if (context.get()) { + const int context_id = GetIDForContext(context, false); + if (context_id == kReservedId) + return 0; // Nothing associated with the specified context. + + // Need to iterate over each RequestInfo object to test the context. + class Visitor : public BrowserRequestInfoMap::Visitor { + public: + explicit Visitor(int context_id) + : context_id_(context_id), + count_(0) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + if (info_id.first == context_id_) + count_++; + return true; + } + + int count() const { return count_; } + + private: + int context_id_; + int count_; + }; + + Visitor visitor(context_id); + + if (browser.get()) { + // Count requests associated with the specified browser. + browser_request_info_map_.FindAll( + browser->GetIdentifier(), &visitor); + } else { + // Count all requests for all browsers. + browser_request_info_map_.FindAll(&visitor); + } + + return visitor.count(); + } else if (browser.get()) { + return static_cast( + browser_request_info_map_.size(browser->GetIdentifier())); + } else { + return static_cast(browser_request_info_map_.size()); + } + + return 0; + } + + virtual void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + CEF_REQUIRE_RENDERER_THREAD(); + + // Register function handlers with the 'window' object. + CefRefPtr window = context->GetGlobal(); + + CefRefPtr handler = new V8HandlerImpl(this, config_); + CefV8Value::PropertyAttribute attributes = + static_cast( + V8_PROPERTY_ATTRIBUTE_READONLY | + V8_PROPERTY_ATTRIBUTE_DONTENUM | + V8_PROPERTY_ATTRIBUTE_DONTDELETE); + + // Add the query function. + CefRefPtr query_func = + CefV8Value::CreateFunction(config_.js_query_function, handler.get()); + window->SetValue(config_.js_query_function, query_func, attributes); + + // Add the cancel function. + CefRefPtr cancel_func = + CefV8Value::CreateFunction(config_.js_cancel_function, handler.get()); + window->SetValue(config_.js_cancel_function, cancel_func, attributes); + } + + virtual void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + CEF_REQUIRE_RENDERER_THREAD(); + + // Get the context ID and remove the context from the map. + const int context_id = GetIDForContext(context, true); + if (context_id != kReservedId) { + // Cancel all pending requests for the context. + SendCancel(browser, frame->GetIdentifier(), context_id, kReservedId); + } + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + CEF_REQUIRE_RENDERER_THREAD(); + + const std::string& message_name = message->GetName(); + if (message_name == query_message_name_) { + CefRefPtr args = message->GetArgumentList(); + DCHECK_GT(args->GetSize(), 3U); + + const int context_id = args->GetInt(0); + const int request_id = args->GetInt(1); + bool is_success = args->GetBool(2); + + if (is_success) { + DCHECK_EQ(args->GetSize(), 4U); + const CefString& response = args->GetString(3); + CefPostTask(TID_RENDERER, + base::Bind( + &CefMessageRouterRendererSideImpl::ExecuteSuccessCallback, this, + browser->GetIdentifier(), context_id, request_id, response)); + } else { + DCHECK_EQ(args->GetSize(), 5U); + int error_code = args->GetInt(3); + const CefString& error_message = args->GetString(4); + CefPostTask(TID_RENDERER, + base::Bind( + &CefMessageRouterRendererSideImpl::ExecuteFailureCallback, this, + browser->GetIdentifier(), context_id, request_id, error_code, + error_message)); + } + + return true; + } + + return false; + } + + private: + // Structure representing a pending request. + struct RequestInfo { + // True if the request is persistent. + bool persistent; + + // Success callback function. May be NULL. + CefRefPtr success_callback; + + // Failure callback function. May be NULL. + CefRefPtr failure_callback; + }; + + // Retrieve a RequestInfo object from the map based on the renderer-side + // IDs. If |always_remove| is true then the RequestInfo object will always be + // removed from the map. Othewise, the RequestInfo object will only be removed + // if the query is non-persistent. If |removed| is true the caller is + // responsible for deleting the returned QueryInfo object. + RequestInfo* GetRequestInfo(int browser_id, + int request_id, + int context_id, + bool always_remove, + bool* removed) { + class Visitor : public BrowserRequestInfoMap::Visitor { + public: + explicit Visitor(bool always_remove) + : always_remove_(always_remove), + removed_(false) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + *remove = removed_ = (always_remove_ || !info->persistent); + return true; + } + + bool removed() const { return removed_; } + + private: + const bool always_remove_; + bool removed_; + }; + + Visitor visitor(always_remove); + RequestInfo* info = browser_request_info_map_.Find(browser_id, + std::make_pair(request_id, context_id), &visitor); + if (info) + *removed = visitor.removed(); + return info; + } + + // Returns the new request ID. + int SendQuery(CefRefPtr browser, + int64 frame_id, + int context_id, + const CefString& request, + bool persistent, + CefRefPtr success_callback, + CefRefPtr failure_callback) { + CEF_REQUIRE_RENDERER_THREAD(); + + const int request_id = request_id_generator_.GetNextId(); + + RequestInfo* info = new RequestInfo; + info->persistent = persistent; + info->success_callback = success_callback; + info->failure_callback = failure_callback; + browser_request_info_map_.Add(browser->GetIdentifier(), + std::make_pair(context_id, request_id), info); + + CefRefPtr message = + CefProcessMessage::Create(query_message_name_); + + CefRefPtr args = message->GetArgumentList(); + args->SetInt(0, CefInt64GetLow(frame_id)); + args->SetInt(1, CefInt64GetHigh(frame_id)); + args->SetInt(2, context_id); + args->SetInt(3, request_id); + args->SetString(4, request); + args->SetBool(5, persistent); + + browser->SendProcessMessage(PID_BROWSER, message); + + return request_id; + } + + // If |request_id| is kReservedId all requests associated with |context_id| + // will be canceled, otherwise only the specified |request_id| will be + // canceled. Returns true if any request was canceled. + bool SendCancel(CefRefPtr browser, + int64 frame_id, + int context_id, + int request_id) { + CEF_REQUIRE_RENDERER_THREAD(); + + const int browser_id = browser->GetIdentifier(); + + int cancel_count = 0; + if (request_id != kReservedId) { + // Cancel a single request. + bool removed; + RequestInfo* info = + GetRequestInfo(browser_id, context_id, request_id, true, &removed); + if (info) { + DCHECK(removed); + delete info; + cancel_count = 1; + } + } else { + // Cancel all requests with the specified context ID. + class Visitor : public BrowserRequestInfoMap::Visitor { + public: + explicit Visitor(int context_id) + : context_id_(context_id), + cancel_count_(0) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + if (info_id.first == context_id_) { + *remove = true; + delete info; + cancel_count_++; + } + return true; + } + + int cancel_count() const { return cancel_count_; } + + private: + const int context_id_; + int cancel_count_; + }; + + Visitor visitor(context_id); + browser_request_info_map_.FindAll(browser_id, &visitor); + cancel_count = visitor.cancel_count(); + } + + if (cancel_count > 0) { + CefRefPtr message = + CefProcessMessage::Create(cancel_message_name_); + + CefRefPtr args = message->GetArgumentList(); + args->SetInt(0, context_id); + args->SetInt(1, request_id); + + browser->SendProcessMessage(PID_BROWSER, message); + return true; + } + + return false; + } + + // Execute the onSuccess JavaScript callback. + void ExecuteSuccessCallback(int browser_id, int context_id, int request_id, + const CefString& response) { + CEF_REQUIRE_RENDERER_THREAD(); + + bool removed; + RequestInfo* info = + GetRequestInfo(browser_id, context_id, request_id, false, &removed); + if (!info) + return; + + CefRefPtr context = GetContextByID(context_id); + if (context && info->success_callback) { + CefV8ValueList args; + args.push_back(CefV8Value::CreateString(response)); + info->success_callback->ExecuteFunctionWithContext(context, NULL, args); + } + + if (removed) + delete info; + } + + // Execute the onFailure JavaScript callback. + void ExecuteFailureCallback(int browser_id, int context_id, int request_id, + int error_code, const CefString& error_message) { + CEF_REQUIRE_RENDERER_THREAD(); + + bool removed; + RequestInfo* info = + GetRequestInfo(browser_id, context_id, request_id, true, &removed); + if (!info) + return; + + CefRefPtr context = GetContextByID(context_id); + if (context && info->failure_callback) { + CefV8ValueList args; + args.push_back(CefV8Value::CreateInt(error_code)); + args.push_back(CefV8Value::CreateString(error_message)); + info->failure_callback->ExecuteFunctionWithContext(context, NULL, args); + } + + DCHECK(removed); + delete info; + } + + int CreateIDForContext(CefRefPtr context) { + CEF_REQUIRE_RENDERER_THREAD(); + + // The context should not already have an associated ID. + DCHECK_EQ(GetIDForContext(context, false), kReservedId); + + const int context_id = context_id_generator_.GetNextId(); + context_map_.insert(std::make_pair(context_id, context)); + return context_id; + } + + // Retrieves the existing ID value associated with the specified |context|. + // If |remove| is true the context will also be removed from the map. + int GetIDForContext(CefRefPtr context, bool remove) { + CEF_REQUIRE_RENDERER_THREAD(); + + ContextMap::iterator it = context_map_.begin(); + for (; it != context_map_.end(); ++it) { + if (it->second->IsSame(context)) { + int context_id = it->first; + if (remove) + context_map_.erase(it); + return context_id; + } + } + + return kReservedId; + } + + CefRefPtr GetContextByID(int context_id) { + CEF_REQUIRE_RENDERER_THREAD(); + + ContextMap::const_iterator it = context_map_.find(context_id); + if (it != context_map_.end()) + return it->second; + return NULL; + } + + const CefMessageRouterConfig config_; + const std::string query_message_name_; + const std::string cancel_message_name_; + + IdGenerator context_id_generator_; + IdGenerator request_id_generator_; + + // Map of (request ID, context ID) to RequestInfo for pending queries. An + // entry is added when a request is initiated via the bound function and + // removed when either the request completes, is canceled via the bound + // function, or the associated context is released. + typedef CefBrowserInfoMap, RequestInfo*> + BrowserRequestInfoMap; + BrowserRequestInfoMap browser_request_info_map_; + + // Map of context ID to CefV8Context for existing contexts. An entry is added + // when a bound function is executed for the first time in the context and + // removed when the context is released. + typedef std::map > ContextMap; + ContextMap context_map_; + + DISALLOW_COPY_AND_ASSIGN(CefMessageRouterRendererSideImpl); +}; + +} // namespace + +CefMessageRouterConfig::CefMessageRouterConfig() + : js_query_function("cefQuery"), + js_cancel_function("cefQueryCancel") { +} + +// static +CefRefPtr CefMessageRouterBrowserSide::Create( + const CefMessageRouterConfig& config) { + CefMessageRouterConfig validated_config = config; + if (!ValidateConfig(validated_config)) + return NULL; + return new CefMessageRouterBrowserSideImpl(validated_config); +} + +// static +CefRefPtr CefMessageRouterRendererSide::Create( + const CefMessageRouterConfig& config) { + CefMessageRouterConfig validated_config = config; + if (!ValidateConfig(validated_config)) + return NULL; + return new CefMessageRouterRendererSideImpl(validated_config); +} diff --git a/libcef_dll/wrapper/cef_stream_resource_handler.cc b/libcef_dll/wrapper/cef_stream_resource_handler.cc new file mode 100644 index 000000000..f7e9868ac --- /dev/null +++ b/libcef_dll/wrapper/cef_stream_resource_handler.cc @@ -0,0 +1,203 @@ +// 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 "include/wrapper/cef_stream_resource_handler.h" + +#include + +#include "include/base/cef_bind.h" +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_callback.h" +#include "include/cef_request.h" +#include "include/cef_stream.h" +#include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_helpers.h" + +// Class that represents a readable/writable character buffer. +class CefStreamResourceHandler::Buffer { + public: + Buffer() + : size_(0), + bytes_requested_(0), + bytes_written_(0), + bytes_read_(0) { + } + + void Reset(int new_size) { + if (size_ < new_size) { + size_ = new_size; + buffer_.reset(new char[size_]); + DCHECK(buffer_); + } + bytes_requested_ = new_size; + bytes_written_ = 0; + bytes_read_ = 0; + } + + bool IsEmpty() const { + return (bytes_written_ == 0); + } + + bool CanRead() const { + return (bytes_read_ < bytes_written_); + } + + int WriteTo(void* data_out, int bytes_to_read) { + const int write_size = + std::min(bytes_to_read, bytes_written_ - bytes_read_); + if (write_size > 0) { + memcpy(data_out, buffer_ .get() + bytes_read_, write_size); + bytes_read_ += write_size; + } + return write_size; + } + + int ReadFrom(CefRefPtr reader) { + // Read until the buffer is full or until Read() returns 0 to indicate no + // more data. + int bytes_read; + do { + bytes_read = static_cast( + reader->Read(buffer_.get() + bytes_written_, 1, + bytes_requested_ - bytes_written_)); + bytes_written_ += bytes_read; + } while (bytes_read != 0 && bytes_written_ < bytes_requested_); + + return bytes_written_; + } + + private: + scoped_ptr buffer_; + int size_; + int bytes_requested_; + int bytes_written_; + int bytes_read_; + + DISALLOW_COPY_AND_ASSIGN(Buffer); +}; + +CefStreamResourceHandler::CefStreamResourceHandler( + const CefString& mime_type, + CefRefPtr stream) + : status_code_(200), + status_text_("OK"), + mime_type_(mime_type), + stream_(stream) +#ifndef NDEBUG + , buffer_owned_by_file_thread_(false) +#endif +{ + DCHECK(!mime_type_.empty()); + DCHECK(stream_.get()); + read_on_file_thread_ = stream_->MayBlock(); +} + +CefStreamResourceHandler::CefStreamResourceHandler( + int status_code, + const CefString& status_text, + const CefString& mime_type, + CefResponse::HeaderMap header_map, + CefRefPtr stream) + : status_code_(status_code), + status_text_(status_text), + mime_type_(mime_type), + header_map_(header_map), + stream_(stream) { + DCHECK(!mime_type_.empty()); + DCHECK(stream_.get()); + read_on_file_thread_ = stream_->MayBlock(); +} + +CefStreamResourceHandler::~CefStreamResourceHandler() { +} + +bool CefStreamResourceHandler::ProcessRequest(CefRefPtr request, + CefRefPtr callback) { + callback->Continue(); + return true; +} + +void CefStreamResourceHandler::GetResponseHeaders( + CefRefPtr response, + int64& response_length, + CefString& redirectUrl) { + response->SetStatus(status_code_); + response->SetStatusText(status_text_); + response->SetMimeType(mime_type_); + + if (!header_map_.empty()) + response->SetHeaderMap(header_map_); + + response_length = -1; +} + +bool CefStreamResourceHandler::ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) { + DCHECK_GT(bytes_to_read, 0); + + if (read_on_file_thread_) { +#ifndef NDEBUG + DCHECK(!buffer_owned_by_file_thread_); +#endif + if (buffer_ && (buffer_->CanRead() || buffer_->IsEmpty())) { + if (buffer_->CanRead()) { + // Provide data from the buffer. + bytes_read = buffer_->WriteTo(data_out, bytes_to_read); + return (bytes_read > 0); + } else { + // End of the steam. + bytes_read = 0; + return false; + } + } else { + // Perform another read on the file thread. + bytes_read = 0; +#ifndef NDEBUG + buffer_owned_by_file_thread_ = true; +#endif + CefPostTask(TID_FILE, + base::Bind(&CefStreamResourceHandler::ReadOnFileThread, this, + bytes_to_read, callback)); + return true; + } + } else { + // Read until the buffer is full or until Read() returns 0 to indicate no + // more data. + bytes_read = 0; + int read = 0; + do { + read = static_cast( + stream_->Read(static_cast(data_out) + bytes_read, 1, + bytes_to_read - bytes_read)); + bytes_read += read; + } while (read != 0 && bytes_read < bytes_to_read); + + return (bytes_read > 0); + } +} + +void CefStreamResourceHandler::Cancel() { +} + +void CefStreamResourceHandler::ReadOnFileThread( + int bytes_to_read, + CefRefPtr callback) { + CEF_REQUIRE_FILE_THREAD(); +#ifndef NDEBUG + DCHECK(buffer_owned_by_file_thread_); +#endif + + if (!buffer_) + buffer_.reset(new Buffer()); + buffer_->Reset(bytes_to_read); + buffer_->ReadFrom(stream_); + +#ifndef NDEBUG + buffer_owned_by_file_thread_ = false; +#endif + callback->Continue(); +} diff --git a/libcef_dll/wrapper/cef_xml_object.cc b/libcef_dll/wrapper/cef_xml_object.cc new file mode 100644 index 000000000..e69d67df2 --- /dev/null +++ b/libcef_dll/wrapper/cef_xml_object.cc @@ -0,0 +1,453 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "include/wrapper/cef_xml_object.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/cef_stream.h" + +namespace { + +class CefXmlObjectLoader { + public: + explicit CefXmlObjectLoader(CefRefPtr root_object) + : root_object_(root_object) { + } + + bool Load(CefRefPtr stream, + CefXmlReader::EncodingType encodingType, + const CefString& URI) { + CefRefPtr reader( + CefXmlReader::Create(stream, encodingType, URI)); + if (!reader.get()) + return false; + + bool ret = reader->MoveToNextNode(); + if (ret) { + CefRefPtr cur_object(root_object_), new_object; + CefXmlObject::ObjectVector queue; + int cur_depth, value_depth = -1; + CefXmlReader::NodeType cur_type; + std::stringstream cur_value; + bool last_has_ns = false; + + queue.push_back(root_object_); + + do { + cur_depth = reader->GetDepth(); + if (value_depth >= 0 && cur_depth > value_depth) { + // The current node has already been parsed as part of a value. + continue; + } + + cur_type = reader->GetType(); + if (cur_type == XML_NODE_ELEMENT_START) { + if (cur_depth == value_depth) { + // Add to the current value. + cur_value << std::string(reader->GetOuterXml()); + continue; + } else if (last_has_ns && reader->GetPrefix().empty()) { + if (!cur_object->HasChildren()) { + // Start a new value because the last element has a namespace and + // this element does not. + value_depth = cur_depth; + cur_value << std::string(reader->GetOuterXml()); + } else { + // Value following a child element is not allowed. + std::stringstream ss; + ss << L"Value following child element, line " << + reader->GetLineNumber(); + load_error_ = ss.str(); + ret = false; + break; + } + } else { + // Start a new element. + new_object = new CefXmlObject(reader->GetQualifiedName()); + cur_object->AddChild(new_object); + last_has_ns = !reader->GetPrefix().empty(); + + if (!reader->IsEmptyElement()) { + // The new element potentially has a value and/or children, so + // set the current object and add the object to the queue. + cur_object = new_object; + queue.push_back(cur_object); + } + + if (reader->HasAttributes() && reader->MoveToFirstAttribute()) { + // Read all object attributes. + do { + new_object->SetAttributeValue(reader->GetQualifiedName(), + reader->GetValue()); + } while (reader->MoveToNextAttribute()); + reader->MoveToCarryingElement(); + } + } + } else if (cur_type == XML_NODE_ELEMENT_END) { + if (cur_depth == value_depth) { + // Ending an element that is already in the value. + continue; + } else if (cur_depth < value_depth) { + // Done with parsing the value portion of the current element. + cur_object->SetValue(cur_value.str()); + cur_value.str(""); + value_depth = -1; + } + + // Pop the current element from the queue. + queue.pop_back(); + + if (queue.empty() || + cur_object->GetName() != reader->GetQualifiedName()) { + // Open tag without close tag or close tag without open tag should + // never occur (the parser catches this error). + NOTREACHED(); + std::stringstream ss; + ss << "Mismatched end tag for " << + std::string(cur_object->GetName()) << + ", line " << reader->GetLineNumber(); + load_error_ = ss.str(); + ret = false; + break; + } + + // Set the current object to the previous object in the queue. + cur_object = queue.back().get(); + } else if (cur_type == XML_NODE_TEXT || cur_type == XML_NODE_CDATA || + cur_type == XML_NODE_ENTITY_REFERENCE) { + if (cur_depth == value_depth) { + // Add to the current value. + cur_value << std::string(reader->GetValue()); + } else if (!cur_object->HasChildren()) { + // Start a new value. + value_depth = cur_depth; + cur_value << std::string(reader->GetValue()); + } else { + // Value following a child element is not allowed. + std::stringstream ss; + ss << "Value following child element, line " << + reader->GetLineNumber(); + load_error_ = ss.str(); + ret = false; + break; + } + } + } while (reader->MoveToNextNode()); + } + + if (reader->HasError()) { + load_error_ = reader->GetError(); + return false; + } + + return ret; + } + + CefString GetLoadError() { return load_error_; } + + private: + CefString load_error_; + CefRefPtr root_object_; + + DISALLOW_COPY_AND_ASSIGN(CefXmlObjectLoader); +}; + +} // namespace + +CefXmlObject::CefXmlObject(const CefString& name) + : name_(name), parent_(NULL) { +} + +CefXmlObject::~CefXmlObject() { +} + +bool CefXmlObject::Load(CefRefPtr stream, + CefXmlReader::EncodingType encodingType, + const CefString& URI, CefString* loadError) { + Clear(); + + CefXmlObjectLoader loader(this); + if (!loader.Load(stream, encodingType, URI)) { + if (loadError) + *loadError = loader.GetLoadError(); + return false; + } + return true; +} + +void CefXmlObject::Set(CefRefPtr object) { + DCHECK(object.get()); + + Clear(); + + name_ = object->GetName(); + Append(object, true); +} + +void CefXmlObject::Append(CefRefPtr object, + bool overwriteAttributes) { + DCHECK(object.get()); + + if (object->HasChildren()) { + ObjectVector children; + object->GetChildren(children); + ObjectVector::const_iterator it = children.begin(); + for (; it != children.end(); ++it) + AddChild((*it)->Duplicate()); + } + + if (object->HasAttributes()) { + AttributeMap attributes; + object->GetAttributes(attributes); + AttributeMap::const_iterator it = attributes.begin(); + for (; it != attributes.end(); ++it) { + if (overwriteAttributes || !HasAttribute(it->first)) + SetAttributeValue(it->first, it->second); + } + } +} + +CefRefPtr CefXmlObject::Duplicate() { + CefRefPtr new_obj; + { + base::AutoLock lock_scope(lock_); + new_obj = new CefXmlObject(name_); + new_obj->Append(this, true); + } + return new_obj; +} + +void CefXmlObject::Clear() { + ClearChildren(); + ClearAttributes(); +} + +CefString CefXmlObject::GetName() { + CefString name; + { + base::AutoLock lock_scope(lock_); + name = name_; + } + return name; +} + +bool CefXmlObject::SetName(const CefString& name) { + DCHECK(!name.empty()); + if (name.empty()) + return false; + + base::AutoLock lock_scope(lock_); + name_ = name; + return true; +} + +bool CefXmlObject::HasParent() { + base::AutoLock lock_scope(lock_); + return (parent_ != NULL); +} + +CefRefPtr CefXmlObject::GetParent() { + CefRefPtr parent; + { + base::AutoLock lock_scope(lock_); + parent = parent_; + } + return parent; +} + +bool CefXmlObject::HasValue() { + base::AutoLock lock_scope(lock_); + return !value_.empty(); +} + +CefString CefXmlObject::GetValue() { + CefString value; + { + base::AutoLock lock_scope(lock_); + value = value_; + } + return value; +} + +bool CefXmlObject::SetValue(const CefString& value) { + base::AutoLock lock_scope(lock_); + DCHECK(children_.empty()); + if (!children_.empty()) + return false; + value_ = value; + return true; +} + +bool CefXmlObject::HasAttributes() { + base::AutoLock lock_scope(lock_); + return !attributes_.empty(); +} + +size_t CefXmlObject::GetAttributeCount() { + base::AutoLock lock_scope(lock_); + return attributes_.size(); +} + +bool CefXmlObject::HasAttribute(const CefString& name) { + if (name.empty()) + return false; + + base::AutoLock lock_scope(lock_); + AttributeMap::const_iterator it = attributes_.find(name); + return (it != attributes_.end()); +} + +CefString CefXmlObject::GetAttributeValue(const CefString& name) { + DCHECK(!name.empty()); + CefString value; + if (!name.empty()) { + base::AutoLock lock_scope(lock_); + AttributeMap::const_iterator it = attributes_.find(name); + if (it != attributes_.end()) + value = it->second; + } + return value; +} + +bool CefXmlObject::SetAttributeValue(const CefString& name, + const CefString& value) { + DCHECK(!name.empty()); + if (name.empty()) + return false; + + base::AutoLock lock_scope(lock_); + AttributeMap::iterator it = attributes_.find(name); + if (it != attributes_.end()) { + it->second = value; + } else { + attributes_.insert(std::make_pair(name, value)); + } + return true; +} + +size_t CefXmlObject::GetAttributes(AttributeMap& attributes) { + base::AutoLock lock_scope(lock_); + attributes = attributes_; + return attributes_.size(); +} + +void CefXmlObject::ClearAttributes() { + base::AutoLock lock_scope(lock_); + attributes_.clear(); +} + +bool CefXmlObject::HasChildren() { + base::AutoLock lock_scope(lock_); + return !children_.empty(); +} + +size_t CefXmlObject::GetChildCount() { + base::AutoLock lock_scope(lock_); + return children_.size(); +} + +bool CefXmlObject::HasChild(CefRefPtr child) { + DCHECK(child.get()); + + base::AutoLock lock_scope(lock_); + ObjectVector::const_iterator it = children_.begin(); + for (; it != children_.end(); ++it) { + if ((*it).get() == child.get()) + return true; + } + return false; +} + +bool CefXmlObject::AddChild(CefRefPtr child) { + DCHECK(child.get()); + if (!child.get()) + return false; + + CefRefPtr parent = child->GetParent(); + DCHECK(!parent); + if (parent) + return false; + + base::AutoLock lock_scope(lock_); + + children_.push_back(child); + child->SetParent(this); + return true; +} + +bool CefXmlObject::RemoveChild(CefRefPtr child) { + DCHECK(child.get()); + + base::AutoLock lock_scope(lock_); + ObjectVector::iterator it = children_.begin(); + for (; it != children_.end(); ++it) { + if ((*it).get() == child.get()) { + children_.erase(it); + child->SetParent(NULL); + return true; + } + } + return false; +} + +size_t CefXmlObject::GetChildren(ObjectVector& children) { + base::AutoLock lock_scope(lock_); + children = children_; + return children_.size(); +} + +void CefXmlObject::ClearChildren() { + base::AutoLock lock_scope(lock_); + ObjectVector::iterator it = children_.begin(); + for (; it != children_.end(); ++it) + (*it)->SetParent(NULL); + children_.clear(); +} + +CefRefPtr CefXmlObject::FindChild(const CefString& name) { + DCHECK(!name.empty()); + if (name.empty()) + return NULL; + + base::AutoLock lock_scope(lock_); + ObjectVector::const_iterator it = children_.begin(); + for (; it != children_.end(); ++it) { + if ((*it)->GetName() == name) + return (*it); + } + return NULL; +} + +size_t CefXmlObject::FindChildren(const CefString& name, + ObjectVector& children) { + DCHECK(!name.empty()); + if (name.empty()) + return 0; + + size_t ct = 0; + + base::AutoLock lock_scope(lock_); + ObjectVector::const_iterator it = children_.begin(); + for (; it != children_.end(); ++it) { + if ((*it)->GetName() == name) { + children.push_back(*it); + ct++; + } + } + return ct; +} + +void CefXmlObject::SetParent(CefXmlObject* parent) { + base::AutoLock lock_scope(lock_); + if (parent) { + DCHECK(parent_ == NULL); + parent_ = parent; + } else { + DCHECK(parent_ != NULL); + parent_ = NULL; + } +} diff --git a/libcef_dll/wrapper/cef_zip_archive.cc b/libcef_dll/wrapper/cef_zip_archive.cc new file mode 100644 index 000000000..05448a428 --- /dev/null +++ b/libcef_dll/wrapper/cef_zip_archive.cc @@ -0,0 +1,174 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "include/wrapper/cef_zip_archive.h" + +#include + +#include "include/base/cef_logging.h" +#include "include/base/cef_macros.h" +#include "include/base/cef_scoped_ptr.h" +#include "include/cef_stream.h" +#include "include/cef_zip_reader.h" +#include "include/wrapper/cef_byte_read_handler.h" + +#if defined(OS_LINUX) +#include +#endif + +namespace { + +// Convert |str| to lowercase in a Unicode-friendly manner. +CefString ToLower(const CefString& str) { + std::wstring wstr = str; + std::transform(wstr.begin(), wstr.end(), wstr.begin(), towlower); + return wstr; +} + +class CefZipFile : public CefZipArchive::File { + public: + CefZipFile() : data_size_(0) {} + + bool Initialize(size_t data_size) { + data_.reset(new unsigned char[data_size]); + if (data_) { + data_size_ = data_size; + return true; + } else { + DLOG(ERROR) << "Failed to allocate " << data_size << " bytes of memory"; + data_size_ = 0; + return false; + } + } + + virtual const unsigned char* GetData() const OVERRIDE { return data_.get(); } + + virtual size_t GetDataSize() const OVERRIDE { return data_size_; } + + virtual CefRefPtr GetStreamReader() const OVERRIDE { + CefRefPtr handler( + new CefByteReadHandler(data_.get(), data_size_, + const_cast(this))); + return CefStreamReader::CreateForHandler(handler); + } + + unsigned char* data() { return data_.get(); } + + private: + size_t data_size_; + scoped_ptr data_; + + IMPLEMENT_REFCOUNTING(CefZipFile); + DISALLOW_COPY_AND_ASSIGN(CefZipFile); +}; + +} // namespace + +// CefZipArchive implementation + +CefZipArchive::CefZipArchive() { +} + +CefZipArchive::~CefZipArchive() { +} + +size_t CefZipArchive::Load(CefRefPtr stream, + const CefString& password, + bool overwriteExisting) { + base::AutoLock lock_scope(lock_); + + CefRefPtr reader(CefZipReader::Create(stream)); + if (!reader.get()) + return 0; + + if (!reader->MoveToFirstFile()) + return 0; + + CefRefPtr contents; + FileMap::iterator it; + size_t count = 0; + + do { + const size_t size = static_cast(reader->GetFileSize()); + if (size == 0) { + // Skip directories and empty files. + continue; + } + + if (!reader->OpenFile(password)) + break; + + const CefString& name = ToLower(reader->GetFileName()); + + it = contents_.find(name); + if (it != contents_.end()) { + if (overwriteExisting) + contents_.erase(it); + else // Skip files that already exist. + continue; + } + + CefRefPtr contents = new CefZipFile(); + if (!contents->Initialize(size)) + continue; + unsigned char* data = contents->data(); + size_t offset = 0; + + // Read the file contents. + do { + offset += reader->ReadFile(data + offset, size - offset); + } while (offset < size && !reader->Eof()); + + DCHECK(offset == size); + + reader->CloseFile(); + count++; + + // Add the file to the map. + contents_.insert(std::make_pair(name, contents.get())); + } while (reader->MoveToNextFile()); + + return count; +} + +void CefZipArchive::Clear() { + base::AutoLock lock_scope(lock_); + contents_.clear(); +} + +size_t CefZipArchive::GetFileCount() const { + base::AutoLock lock_scope(lock_); + return contents_.size(); +} + +bool CefZipArchive::HasFile(const CefString& fileName) const { + base::AutoLock lock_scope(lock_); + FileMap::const_iterator it = contents_.find(ToLower(fileName)); + return (it != contents_.end()); +} + +CefRefPtr CefZipArchive::GetFile( + const CefString& fileName) const { + base::AutoLock lock_scope(lock_); + FileMap::const_iterator it = contents_.find(ToLower(fileName)); + if (it != contents_.end()) + return it->second; + return NULL; +} + +bool CefZipArchive::RemoveFile(const CefString& fileName) { + base::AutoLock lock_scope(lock_); + FileMap::iterator it = contents_.find(ToLower(fileName)); + if (it != contents_.end()) { + contents_.erase(it); + return true; + } + return false; +} + +size_t CefZipArchive::GetFiles(FileMap& map) const { + base::AutoLock lock_scope(lock_); + map = contents_; + return contents_.size(); +} diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc new file mode 100644 index 000000000..00d32a42b --- /dev/null +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -0,0 +1,734 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "include/cef_app.h" +#include "include/capi/cef_app_capi.h" +#include "include/cef_geolocation.h" +#include "include/capi/cef_geolocation_capi.h" +#include "include/cef_origin_whitelist.h" +#include "include/capi/cef_origin_whitelist_capi.h" +#include "include/cef_path_util.h" +#include "include/capi/cef_path_util_capi.h" +#include "include/cef_process_util.h" +#include "include/capi/cef_process_util_capi.h" +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" +#include "include/cef_task.h" +#include "include/capi/cef_task_capi.h" +#include "include/cef_trace.h" +#include "include/capi/cef_trace_capi.h" +#include "include/cef_url.h" +#include "include/capi/cef_url_capi.h" +#include "include/cef_v8.h" +#include "include/capi/cef_v8_capi.h" +#include "include/cef_web_plugin.h" +#include "include/capi/cef_web_plugin_capi.h" +#include "include/cef_version.h" +#include "libcef_dll/cpptoc/app_cpptoc.h" +#include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/completion_callback_cpptoc.h" +#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h" +#include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" +#include "libcef_dll/cpptoc/domevent_listener_cpptoc.h" +#include "libcef_dll/cpptoc/domvisitor_cpptoc.h" +#include "libcef_dll/cpptoc/dialog_handler_cpptoc.h" +#include "libcef_dll/cpptoc/display_handler_cpptoc.h" +#include "libcef_dll/cpptoc/download_handler_cpptoc.h" +#include "libcef_dll/cpptoc/drag_handler_cpptoc.h" +#include "libcef_dll/cpptoc/end_tracing_callback_cpptoc.h" +#include "libcef_dll/cpptoc/focus_handler_cpptoc.h" +#include "libcef_dll/cpptoc/geolocation_handler_cpptoc.h" +#include "libcef_dll/cpptoc/get_geolocation_callback_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" +#include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h" +#include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" +#include "libcef_dll/cpptoc/load_handler_cpptoc.h" +#include "libcef_dll/cpptoc/print_handler_cpptoc.h" +#include "libcef_dll/cpptoc/read_handler_cpptoc.h" +#include "libcef_dll/cpptoc/render_handler_cpptoc.h" +#include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/request_handler_cpptoc.h" +#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h" +#include "libcef_dll/cpptoc/resource_handler_cpptoc.h" +#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h" +#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h" +#include "libcef_dll/cpptoc/string_visitor_cpptoc.h" +#include "libcef_dll/cpptoc/task_cpptoc.h" +#include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" +#include "libcef_dll/cpptoc/v8accessor_cpptoc.h" +#include "libcef_dll/cpptoc/v8handler_cpptoc.h" +#include "libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h" +#include "libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h" +#include "libcef_dll/cpptoc/write_handler_cpptoc.h" +#include "libcef_dll/ctocpp/allow_certificate_error_callback_ctocpp.h" +#include "libcef_dll/ctocpp/auth_callback_ctocpp.h" +#include "libcef_dll/ctocpp/before_download_callback_ctocpp.h" +#include "libcef_dll/ctocpp/binary_value_ctocpp.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/browser_host_ctocpp.h" +#include "libcef_dll/ctocpp/callback_ctocpp.h" +#include "libcef_dll/ctocpp/command_line_ctocpp.h" +#include "libcef_dll/ctocpp/context_menu_params_ctocpp.h" +#include "libcef_dll/ctocpp/domdocument_ctocpp.h" +#include "libcef_dll/ctocpp/domevent_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" +#include "libcef_dll/ctocpp/dictionary_value_ctocpp.h" +#include "libcef_dll/ctocpp/download_item_ctocpp.h" +#include "libcef_dll/ctocpp/download_item_callback_ctocpp.h" +#include "libcef_dll/ctocpp/drag_data_ctocpp.h" +#include "libcef_dll/ctocpp/file_dialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" +#include "libcef_dll/ctocpp/geolocation_callback_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/list_value_ctocpp.h" +#include "libcef_dll/ctocpp/menu_model_ctocpp.h" +#include "libcef_dll/ctocpp/print_dialog_callback_ctocpp.h" +#include "libcef_dll/ctocpp/print_job_callback_ctocpp.h" +#include "libcef_dll/ctocpp/print_settings_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" +#include "libcef_dll/ctocpp/quota_callback_ctocpp.h" +#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h" +#include "libcef_dll/ctocpp/stream_reader_ctocpp.h" +#include "libcef_dll/ctocpp/stream_writer_ctocpp.h" +#include "libcef_dll/ctocpp/task_runner_ctocpp.h" +#include "libcef_dll/ctocpp/urlrequest_ctocpp.h" +#include "libcef_dll/ctocpp/v8context_ctocpp.h" +#include "libcef_dll/ctocpp/v8exception_ctocpp.h" +#include "libcef_dll/ctocpp/v8stack_frame_ctocpp.h" +#include "libcef_dll/ctocpp/v8stack_trace_ctocpp.h" +#include "libcef_dll/ctocpp/v8value_ctocpp.h" +#include "libcef_dll/ctocpp/web_plugin_info_ctocpp.h" +#include "libcef_dll/ctocpp/xml_reader_ctocpp.h" +#include "libcef_dll/ctocpp/zip_reader_ctocpp.h" +#include "libcef_dll/transfer_util.h" + +// Define used to facilitate parsing. +#define CEF_GLOBAL + + +// GLOBAL METHODS - Body may be edited by hand. + +CEF_GLOBAL int CefExecuteProcess(const CefMainArgs& args, + CefRefPtr application, void* windows_sandbox_info) { + const char* api_hash = cef_api_hash(0); + if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) { + // The libcef API hash does not match the current header API hash. + NOTREACHED(); + return 0; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: application, windows_sandbox_info + + // Execute + int _retval = cef_execute_process( + &args, + CefAppCppToC::Wrap(application), + windows_sandbox_info); + + // Return type: simple + return _retval; +} + +CEF_GLOBAL bool CefInitialize(const CefMainArgs& args, + const CefSettings& settings, CefRefPtr application, + void* windows_sandbox_info) { + const char* api_hash = cef_api_hash(0); + if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) { + // The libcef API hash does not match the current header API hash. + NOTREACHED(); + return false; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: application, windows_sandbox_info + + // Execute + int _retval = cef_initialize( + &args, + &settings, + CefAppCppToC::Wrap(application), + windows_sandbox_info); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL void CefShutdown() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_shutdown(); + +#ifndef NDEBUG + // Check that all wrapper objects have been destroyed + DCHECK(base::AtomicRefCountIsZero( + &CefAllowCertificateErrorCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefAuthCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBeforeDownloadCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBinaryValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefBrowserHostCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefBrowserProcessHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCompletionCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefContextMenuParamsCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefCookieVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMEventListenerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDownloadItemCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDownloadItemCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragDataCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefDragHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefEndTracingCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFileDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFocusHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefFrameCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefGeolocationHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefGetGeolocationCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefJSDialogHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefKeyboardHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLifeSpanHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefListValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefLoadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefMenuModelCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintDialogCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintJobCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefPrintSettingsCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefProcessMessageCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefQuotaCallbackCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefReadHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRenderHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRenderProcessHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefRequestHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefResourceBundleHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefRunFileDialogCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefSchemeHandlerFactoryCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWebPluginInfoCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginInfoVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefWebPluginUnstableCallbackCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefWriteHandlerCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefXmlReaderCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefZipReaderCToCpp::DebugObjCt)); +#endif // !NDEBUG +} + +CEF_GLOBAL void CefDoMessageLoopWork() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_do_message_loop_work(); +} + +CEF_GLOBAL void CefRunMessageLoop() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_run_message_loop(); +} + +CEF_GLOBAL void CefQuitMessageLoop() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_quit_message_loop(); +} + +CEF_GLOBAL void CefSetOSModalLoop(bool osModalLoop) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_set_osmodal_loop( + osModalLoop); +} + +CEF_GLOBAL bool CefGetGeolocation( + CefRefPtr callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + + // Execute + int _retval = cef_get_geolocation( + CefGetGeolocationCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin, + const CefString& target_protocol, const CefString& target_domain, + bool allow_target_subdomains) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: source_origin; type: string_byref_const + DCHECK(!source_origin.empty()); + if (source_origin.empty()) + return false; + // Verify param: target_protocol; type: string_byref_const + DCHECK(!target_protocol.empty()); + if (target_protocol.empty()) + return false; + // Unverified params: target_domain + + // Execute + int _retval = cef_add_cross_origin_whitelist_entry( + source_origin.GetStruct(), + target_protocol.GetStruct(), + target_domain.GetStruct(), + allow_target_subdomains); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefRemoveCrossOriginWhitelistEntry( + const CefString& source_origin, const CefString& target_protocol, + const CefString& target_domain, bool allow_target_subdomains) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: source_origin; type: string_byref_const + DCHECK(!source_origin.empty()); + if (source_origin.empty()) + return false; + // Verify param: target_protocol; type: string_byref_const + DCHECK(!target_protocol.empty()); + if (target_protocol.empty()) + return false; + // Unverified params: target_domain + + // Execute + int _retval = cef_remove_cross_origin_whitelist_entry( + source_origin.GetStruct(), + target_protocol.GetStruct(), + target_domain.GetStruct(), + allow_target_subdomains); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefClearCrossOriginWhitelist() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_clear_cross_origin_whitelist(); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefGetPath(PathKey key, CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_get_path( + key, + path.GetWritableStruct()); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefLaunchProcess(CefRefPtr command_line) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: command_line; type: refptr_same + DCHECK(command_line.get()); + if (!command_line.get()) + return false; + + // Execute + int _retval = cef_launch_process( + CefCommandLineCToCpp::Unwrap(command_line)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: scheme_name; type: string_byref_const + DCHECK(!scheme_name.empty()); + if (scheme_name.empty()) + return false; + // Unverified params: domain_name, factory + + // Execute + int _retval = cef_register_scheme_handler_factory( + scheme_name.GetStruct(), + domain_name.GetStruct(), + CefSchemeHandlerFactoryCppToC::Wrap(factory)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefClearSchemeHandlerFactories() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_clear_scheme_handler_factories(); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefCurrentlyOn(CefThreadId threadId) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_currently_on( + threadId); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefPostTask(CefThreadId threadId, CefRefPtr task) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task.get()); + if (!task.get()) + return false; + + // Execute + int _retval = cef_post_task( + threadId, + CefTaskCppToC::Wrap(task)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefPostDelayedTask(CefThreadId threadId, + CefRefPtr task, int64 delay_ms) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: task; type: refptr_diff + DCHECK(task.get()); + if (!task.get()) + return false; + + // Execute + int _retval = cef_post_delayed_task( + threadId, + CefTaskCppToC::Wrap(task), + delay_ms); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefBeginTracing(const CefString& categories, + CefRefPtr callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: categories, callback + + // Execute + int _retval = cef_begin_tracing( + categories.GetStruct(), + CefCompletionCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefEndTracing(const CefString& tracing_file, + CefRefPtr callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: tracing_file, callback + + // Execute + int _retval = cef_end_tracing( + tracing_file.GetStruct(), + CefEndTracingCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL int64 CefNowFromSystemTraceTime() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int64 _retval = cef_now_from_system_trace_time(); + + // Return type: simple + return _retval; +} + +CEF_GLOBAL bool CefParseURL(const CefString& url, CefURLParts& parts) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return false; + + // Execute + int _retval = cef_parse_url( + url.GetStruct(), + &parts); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL bool CefCreateURL(const CefURLParts& parts, CefString& url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = cef_create_url( + &parts, + url.GetWritableStruct()); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL CefString CefGetMimeType(const CefString& extension) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extension; type: string_byref_const + DCHECK(!extension.empty()); + if (extension.empty()) + return CefString(); + + // Execute + cef_string_userfree_t _retval = cef_get_mime_type( + extension.GetStruct()); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CEF_GLOBAL void CefGetExtensionsForMimeType(const CefString& mime_type, + std::vector& extensions) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: mime_type; type: string_byref_const + DCHECK(!mime_type.empty()); + if (mime_type.empty()) + return; + + // Translate param: extensions; type: string_vec_byref + cef_string_list_t extensionsList = cef_string_list_alloc(); + DCHECK(extensionsList); + if (extensionsList) + transfer_string_list_contents(extensions, extensionsList); + + // Execute + cef_get_extensions_for_mime_type( + mime_type.GetStruct(), + extensionsList); + + // Restore param:extensions; type: string_vec_byref + if (extensionsList) { + extensions.clear(); + transfer_string_list_contents(extensionsList, extensions); + cef_string_list_free(extensionsList); + } +} + +CEF_GLOBAL bool CefRegisterExtension(const CefString& extension_name, + const CefString& javascript_code, CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: extension_name; type: string_byref_const + DCHECK(!extension_name.empty()); + if (extension_name.empty()) + return false; + // Verify param: javascript_code; type: string_byref_const + DCHECK(!javascript_code.empty()); + if (javascript_code.empty()) + return false; + // Unverified params: handler + + // Execute + int _retval = cef_register_extension( + extension_name.GetStruct(), + javascript_code.GetStruct(), + CefV8HandlerCppToC::Wrap(handler)); + + // Return type: bool + return _retval?true:false; +} + +CEF_GLOBAL void CefVisitWebPluginInfo( + CefRefPtr visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return; + + // Execute + cef_visit_web_plugin_info( + CefWebPluginInfoVisitorCppToC::Wrap(visitor)); +} + +CEF_GLOBAL void CefRefreshWebPlugins() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_refresh_web_plugins(); +} + +CEF_GLOBAL void CefAddWebPluginPath(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_add_web_plugin_path( + path.GetStruct()); +} + +CEF_GLOBAL void CefAddWebPluginDirectory(const CefString& dir) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: dir; type: string_byref_const + DCHECK(!dir.empty()); + if (dir.empty()) + return; + + // Execute + cef_add_web_plugin_directory( + dir.GetStruct()); +} + +CEF_GLOBAL void CefRemoveWebPluginPath(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_remove_web_plugin_path( + path.GetStruct()); +} + +CEF_GLOBAL void CefUnregisterInternalWebPlugin(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_unregister_internal_web_plugin( + path.GetStruct()); +} + +CEF_GLOBAL void CefForceWebPluginShutdown(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_force_web_plugin_shutdown( + path.GetStruct()); +} + +CEF_GLOBAL void CefRegisterWebPluginCrash(const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + + // Execute + cef_register_web_plugin_crash( + path.GetStruct()); +} + +CEF_GLOBAL void CefIsWebPluginUnstable(const CefString& path, + CefRefPtr callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: path; type: string_byref_const + DCHECK(!path.empty()); + if (path.empty()) + return; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return; + + // Execute + cef_is_web_plugin_unstable( + path.GetStruct(), + CefWebPluginUnstableCallbackCppToC::Wrap(callback)); +} + diff --git a/libcef_dll/wrapper/libcef_dll_wrapper2.cc b/libcef_dll/wrapper/libcef_dll_wrapper2.cc new file mode 100644 index 000000000..dc8ba7b02 --- /dev/null +++ b/libcef_dll/wrapper/libcef_dll_wrapper2.cc @@ -0,0 +1,4 @@ +// 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. + diff --git a/patch/README.txt b/patch/README.txt new file mode 100644 index 000000000..f96fe36a4 --- /dev/null +++ b/patch/README.txt @@ -0,0 +1,20 @@ +There may be instances where CEF requires changes to the Chromium/WebKit code +base that are not desired by the Chromium/WebKit projects as a whole. To address +this situation the CEF project adds a patch capability as part of the CEF GYP +project generation step. The patch capability works as follows: + +1. The CEF developer creates one or more patch files containing all required + changes to the Chromium/WebKit code base and places those patch files in the + "patches" subdirectory. +2. The CEF developer adds an entry for each patch file in the "patch.cfg" file. +3. CEF applies the patches to the Chromium/WebKit source tree using the + patcher.py tool in the tools directory. If necessary the patcher.py tool + also rewrites the "patch_state.h" file which defines the CEF_PATCHES_APPLIED + preprocessor value. + +To disable automatic application of patches to the Chromium/WebKit code base +create an empty "NOPATCH" file in the "patch" directory. Sections of the CEF +code base that otherwise require patches will be disabled using the +CEF_PATCHES_APPLIED preprocessor value defined in the "patch_state.h" file. Be +warned that not applying all required patches may break important CEF +functionality. diff --git a/patch/patch.cfg b/patch/patch.cfg new file mode 100644 index 000000000..1608b6c4f --- /dev/null +++ b/patch/patch.cfg @@ -0,0 +1,121 @@ +# Each map in the list associates a patch file name with a target path and +# optional condition. All paths in the patch file must be relative to the +# target path. Each map should include a comment linking to the code review +# or bug report that the patch relates to. If a condition is provided the +# patch will only be applied if an environment variable with the specified +# name exists. + +patches = [ + { + # Necessary for grit integration + 'name': 'gritsettings', + 'path': '../tools/gritsettings/', + }, + { + # Fix Xcode 4 build on OS X Lion. + # http://codereview.chromium.org/8086022/ + # + # Disable Warning 4702 ("Unreachable code") for Windows VS builds. + # https://code.google.com/p/chromium/issues/detail?id=346399#c55 + # + # Allow use of the make gyp generator on Linux. + # https://code.google.com/p/chromiumembedded/issues/detail?id=1304 + 'name': 'build', + 'path': '../build/', + }, + { + # Support loading of password protected zip archives. + # http://code.google.com/p/chromiumembedded/issues/detail?id=496 + 'name': 'zlib', + 'path': '../third_party/zlib/', + }, + { + # Avoid MessageLoop assertion on OS X. + # http://code.google.com/p/chromiumembedded/issues/detail?id=443 + 'name': 'message_loop_443', + 'path': '../base/message_loop/', + }, + { + # Disable event type assertion in WebNode::addEventListener. + # http://code.google.com/p/chromiumembedded/issues/detail?id=933 + 'name': 'webkit_933', + 'path': '../third_party/WebKit/Source/web/', + }, + { + # Fix ninja output for localization directories on OS X. + # http://code.google.com/p/gyp/issues/detail?id=331 + 'name': 'gyp_331', + 'path': '../tools/gyp/pylib/', + }, + { + # Enable popups in offscreen rendering on OS X. + 'name': 'webkit_popups', + 'path': '../third_party/WebKit/', + }, + { + # Fix export of UnderlayOpenGLHostingWindow for 64-bit OS X builds. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1051 + 'name': 'underlay_1051', + 'path': '../ui/base/cocoa/', + }, + { + # Allow specification of a parent window handle for Widget creation. + # https://code.google.com/p/chromiumembedded/issues/detail?id=180 + 'name': 'views_widget_180', + 'path': '../ui/views/widget/', + }, + { + # Allow continued use of ContentRendererClient::HandleNavigation. + # https://code.google.com/p/chromiumembedded/issues/detail?id=1129 + 'name': 'content_nav_1129', + 'path': '../content/', + }, + { + # Allow customization of the background color on OS X. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1161 + 'name': 'renderer_host_1161', + 'path': '../content/browser/renderer_host/', + }, + { + # Allow customization of the background color with Aura. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1161 + # + # Allow specification of a custom WebContentsView. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1257 + 'name': 'public_browser_1161_1257', + 'path': '../content/public/browser/', + }, + { + # Allow specification of a custom WebContentsView. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1257 + 'name': 'browser_web_contents_1257', + 'path': '../content/browser/web_contents/', + }, + { + # Allow customization of the WebView background color. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1161 + # https://codereview.chromium.org/228603007/ + 'name': 'prefs_content_1161', + 'path': '../content/', + }, + { + # Allow customization of the WebView background color. + # http://code.google.com/p/chromiumembedded/issues/detail?id=1161 + # https://codereview.chromium.org/228603007/ + 'name': 'prefs_webkit_1161', + 'path': '../webkit/', + }, + { + # Fix drag&drop of combined text and URL data on Linux/Aura. + # https://codereview.chromium.org/208313009 + 'name': 'ui_dragdrop_355390', + 'path': '../ui/base/dragdrop/', + }, + { + # Disable scollbar bounce and overlay on OS X. + # http://code.google.com/p/chromiumembedded/issues/detail?id=364 + 'name': 'spi_webcore_364', + 'path': '../third_party/WebKit/Source/', + 'condition': 'CEF_SPI_BUILD', + }, +] diff --git a/patch/patches/browser_web_contents_1257.patch b/patch/patches/browser_web_contents_1257.patch new file mode 100644 index 000000000..95661a899 --- /dev/null +++ b/patch/patches/browser_web_contents_1257.patch @@ -0,0 +1,78 @@ +Index: web_contents_impl.cc +=================================================================== +--- web_contents_impl.cc (revision 286351) ++++ web_contents_impl.cc (working copy) +@@ -1066,22 +1066,29 @@ + params.browser_context, params.site_instance, params.routing_id, + params.main_frame_routing_id); + +- WebContentsViewDelegate* delegate = +- GetContentClient()->browser()->GetWebContentsViewDelegate(this); ++ if (params.view && params.delegate_view) { ++ view_.reset(params.view); ++ render_view_host_delegate_view_ = params.delegate_view; ++ } + +- if (browser_plugin_guest_) { +- scoped_ptr platform_view(CreateWebContentsView( +- this, delegate, &render_view_host_delegate_view_)); ++ if (!view_) { ++ WebContentsViewDelegate* delegate = ++ GetContentClient()->browser()->GetWebContentsViewDelegate(this); + +- WebContentsViewGuest* rv = new WebContentsViewGuest( +- this, browser_plugin_guest_.get(), platform_view.Pass(), +- render_view_host_delegate_view_); +- render_view_host_delegate_view_ = rv; +- view_.reset(rv); +- } else { +- // Regular WebContentsView. +- view_.reset(CreateWebContentsView( +- this, delegate, &render_view_host_delegate_view_)); ++ if (browser_plugin_guest_) { ++ scoped_ptr platform_view(CreateWebContentsView( ++ this, delegate, &render_view_host_delegate_view_)); ++ ++ WebContentsViewGuest* rv = new WebContentsViewGuest( ++ this, browser_plugin_guest_.get(), platform_view.Pass(), ++ render_view_host_delegate_view_); ++ render_view_host_delegate_view_ = rv; ++ view_.reset(rv); ++ } else { ++ // Regular WebContentsView. ++ view_.reset(CreateWebContentsView( ++ this, delegate, &render_view_host_delegate_view_)); ++ } + } + CHECK(render_view_host_delegate_view_); + CHECK(view_.get()); +@@ -1398,6 +1405,9 @@ + static_cast(session_storage_namespace); + CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); + ++ content::WebContentsView* view = NULL; ++ content::RenderViewHostDelegateView* delegate_view = NULL; ++ + if (delegate_ && + !delegate_->ShouldCreateWebContents(this, + route_id, +@@ -1405,7 +1415,9 @@ + params.frame_name, + params.target_url, + partition_id, +- session_storage_namespace)) { ++ session_storage_namespace, ++ &view, ++ &delegate_view)) { + if (route_id != MSG_ROUTING_NONE && + !RenderViewHost::FromID(render_process_id, route_id)) { + // If the embedder didn't create a WebContents for this route, we need to +@@ -1425,6 +1437,8 @@ + create_params.main_frame_routing_id = main_frame_route_id; + create_params.opener = this; + create_params.opener_suppressed = params.opener_suppressed; ++ create_params.view = view; ++ create_params.delegate_view = delegate_view; + if (params.disposition == NEW_BACKGROUND_TAB) + create_params.initially_hidden = true; + diff --git a/patch/patches/build.patch b/patch/patches/build.patch new file mode 100644 index 000000000..5646f374a --- /dev/null +++ b/patch/patches/build.patch @@ -0,0 +1,54 @@ +Index: mac/strip_save_dsym +=================================================================== +--- mac/strip_save_dsym (revision 286351) ++++ mac/strip_save_dsym (working copy) +@@ -48,7 +48,7 @@ + "bundle"] + macho_types_re = "Mach-O (?:64-bit )?(?:" + "|".join(macho_types) + ")" + +- file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "--", macho], ++ file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "-L", "--", macho], + stdout=subprocess.PIPE) + + archs = [] +Index: gyp_chromium +=================================================================== +--- gyp_chromium (revision 286351) ++++ gyp_chromium (working copy) +@@ -251,12 +251,6 @@ + if sys.platform not in ('darwin',): + args.append('--no-circular-check') + +- # We explicitly don't support the make gyp generator (crbug.com/348686). Be +- # nice and fail here, rather than choking in gyp. +- if re.search(r'(^|,|\s)make($|,|\s)', os.environ.get('GYP_GENERATORS', '')): +- print 'Error: make gyp generator not supported (check GYP_GENERATORS).' +- sys.exit(1) +- + # Default to ninja on linux and windows, but only if no generator has + # explicitly been set. + # Also default to ninja on mac, but only when not building chrome/ios. +Index: common.gypi +=================================================================== +--- common.gypi (revision 286351) ++++ common.gypi (working copy) +@@ -9,6 +9,9 @@ + # Variables expected to be overriden on the GYP command line (-D) or by + # ~/.gyp/include.gypi. + 'variables': { ++ # Directory for CEF source files. This will be set by cef.gypi. ++ 'cef_directory%' : '', ++ + # Putting a variables dict inside another variables dict looks kind of + # weird. This is done so that 'host_arch', 'chromeos', etc are defined as + # variables within the outer variables dict here. This is necessary +@@ -5119,6 +5122,9 @@ + # removed as code is fixed. + 4100, 4121, 4125, 4127, 4130, 4131, 4189, 4201, 4238, 4244, 4245, + 4310, 4428, 4481, 4505, 4510, 4512, 4530, 4610, 4611, 4701, 4706, ++ # Disable Warning 4702 ("Unreachable code") ++ # https://code.google.com/p/chromium/issues/detail?id=346399#c55 ++ 4702, + ], + 'msvs_settings': { + 'VCCLCompilerTool': { diff --git a/patch/patches/content_nav_1129.patch b/patch/patches/content_nav_1129.patch new file mode 100644 index 000000000..cc70cc5ab --- /dev/null +++ b/patch/patches/content_nav_1129.patch @@ -0,0 +1,60 @@ +Index: public/renderer/content_renderer_client.cc +=================================================================== +--- public/renderer/content_renderer_client.cc (revision 286351) ++++ public/renderer/content_renderer_client.cc (working copy) +@@ -92,7 +92,6 @@ + return false; + } + +-#ifdef OS_ANDROID + bool ContentRendererClient::HandleNavigation( + RenderFrame* render_frame, + DocumentState* document_state, +@@ -104,7 +103,6 @@ + bool is_redirect) { + return false; + } +-#endif + + bool ContentRendererClient::ShouldFork(blink::WebFrame* frame, + const GURL& url, +Index: public/renderer/content_renderer_client.h +=================================================================== +--- public/renderer/content_renderer_client.h (revision 286351) ++++ public/renderer/content_renderer_client.h (working copy) +@@ -176,7 +176,6 @@ + // Returns true if a popup window should be allowed. + virtual bool AllowPopup(); + +-#ifdef OS_ANDROID + // TODO(sgurun) This callback is deprecated and will be removed as soon + // as android webview completes implementation of a resource throttle based + // shouldoverrideurl implementation. See crbug.com/325351 +@@ -191,7 +190,6 @@ + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, + bool is_redirect); +-#endif + + // Returns true if we should fork a new process for the given navigation. + // If |send_referrer| is set to false (which is the default), no referrer +Index: renderer/render_frame_impl.cc +=================================================================== +--- renderer/render_frame_impl.cc (revision 286351) ++++ renderer/render_frame_impl.cc (working copy) +@@ -3121,7 +3121,6 @@ + WebNavigationType type, + WebNavigationPolicy default_policy, + bool is_redirect) { +-#ifdef OS_ANDROID + // The handlenavigation API is deprecated and will be removed once + // crbug.com/325351 is resolved. + if (request.url() != GURL(kSwappedOutURL) && +@@ -3136,7 +3135,6 @@ + is_redirect)) { + return blink::WebNavigationPolicyIgnore; + } +-#endif + + Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request)); + diff --git a/patch/patches/gritsettings.patch b/patch/patches/gritsettings.patch new file mode 100644 index 000000000..3d4d64137 --- /dev/null +++ b/patch/patches/gritsettings.patch @@ -0,0 +1,17 @@ +Index: resource_ids +=================================================================== +--- resource_ids (revision 286351) ++++ resource_ids (working copy) +@@ -16,6 +16,12 @@ + { + "SRCDIR": "../..", + ++ "cef/libcef/resources/cef_resources.grd": { ++ "includes": [27500], ++ }, ++ "cef/libcef/resources/cef_strings.grd": { ++ "messages": [28000], ++ }, + "chrome/browser/browser_resources.grd": { + "includes": [500], + "structures": [750], diff --git a/patch/patches/gyp_331.patch b/patch/patches/gyp_331.patch new file mode 100644 index 000000000..537118769 --- /dev/null +++ b/patch/patches/gyp_331.patch @@ -0,0 +1,22 @@ +Index: gyp/generator/ninja.py +=================================================================== +--- gyp/generator/ninja.py (revision 1944) ++++ gyp/generator/ninja.py (working copy) +@@ -740,7 +740,16 @@ + for path in copy['files']: + # Normalize the path so trailing slashes don't confuse us. + path = os.path.normpath(path) +- basename = os.path.split(path)[1] ++ (parent_path, basename) = os.path.split(path) ++ ++ # Xcode uses .lproj directories for localized resources. Add a special ++ # case to maintain the localization directory component if present. ++ if parent_path != '': ++ parent_basename = os.path.basename(parent_path) ++ (parent_root, parent_ext) = os.path.splitext(parent_basename) ++ if parent_ext == '.lproj': ++ basename = os.path.join(parent_basename, basename) ++ + src = self.GypPathToNinja(path, env) + dst = self.GypPathToNinja(os.path.join(copy['destination'], basename), + env) diff --git a/patch/patches/message_loop_443.patch b/patch/patches/message_loop_443.patch new file mode 100644 index 000000000..0556f68ce --- /dev/null +++ b/patch/patches/message_loop_443.patch @@ -0,0 +1,13 @@ +Index: message_loop.cc +=================================================================== +--- message_loop.cc (revision 286351) ++++ message_loop.cc (working copy) +@@ -154,7 +154,7 @@ + MessageLoop::~MessageLoop() { + DCHECK_EQ(this, current()); + +- DCHECK(!run_loop_); ++ //DCHECK(!run_loop_); + + // Clean up any unprocessed tasks, but take care: deleting a task could + // result in the addition of more tasks (e.g., via DeleteSoon). We set a diff --git a/patch/patches/prefs_content_1161.patch b/patch/patches/prefs_content_1161.patch new file mode 100644 index 000000000..9e5ce15c5 --- /dev/null +++ b/patch/patches/prefs_content_1161.patch @@ -0,0 +1,25 @@ +Index: public/common/common_param_traits_macros.h +=================================================================== +--- public/common/common_param_traits_macros.h (revision 286351) ++++ public/common/common_param_traits_macros.h (working copy) +@@ -175,6 +175,7 @@ + IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale) + IPC_STRUCT_TRAITS_MEMBER(smart_insert_delete_enabled) + IPC_STRUCT_TRAITS_MEMBER(compositor_touch_hit_testing) ++ IPC_STRUCT_TRAITS_MEMBER(base_background_color) + IPC_STRUCT_TRAITS_MEMBER(cookie_enabled) + IPC_STRUCT_TRAITS_MEMBER(navigate_on_drag_drop) + IPC_STRUCT_TRAITS_MEMBER(spatial_navigation_enabled) +Index: renderer/web_preferences.cc +=================================================================== +--- renderer/web_preferences.cc (revision 286351) ++++ renderer/web_preferences.cc (working copy) +@@ -167,6 +167,8 @@ + + settings->setJavaEnabled(prefs.java_enabled); + ++ web_view->setBaseBackgroundColor(prefs.base_background_color); ++ + // By default, allow_universal_access_from_file_urls is set to false and thus + // we mitigate attacks from local HTML files by not granting file:// URLs + // universal access. Only test shell will enable this. diff --git a/patch/patches/prefs_webkit_1161.patch b/patch/patches/prefs_webkit_1161.patch new file mode 100644 index 000000000..e113108b1 --- /dev/null +++ b/patch/patches/prefs_webkit_1161.patch @@ -0,0 +1,24 @@ +Index: common/webpreferences.cc +=================================================================== +--- common/webpreferences.cc (revision 286351) ++++ common/webpreferences.cc (working copy) +@@ -112,6 +112,7 @@ + use_solid_color_scrollbars(false), + compositor_touch_hit_testing(true), + navigate_on_drag_drop(true), ++ base_background_color(0xFFFFFFFF), // Color::white + cookie_enabled(true), + pepper_accelerated_video_decode_enabled(false) + #if defined(OS_ANDROID) +Index: common/webpreferences.h +=================================================================== +--- common/webpreferences.h (revision 286351) ++++ common/webpreferences.h (working copy) +@@ -148,6 +148,7 @@ + bool use_solid_color_scrollbars; + bool compositor_touch_hit_testing; + bool navigate_on_drag_drop; ++ uint32_t base_background_color; + + // This flags corresponds to a Page's Settings' setCookieEnabled state. It + // only controls whether or not the "document.cookie" field is properly diff --git a/patch/patches/public_browser_1161_1257.patch b/patch/patches/public_browser_1161_1257.patch new file mode 100644 index 000000000..ec7b262b9 --- /dev/null +++ b/patch/patches/public_browser_1161_1257.patch @@ -0,0 +1,132 @@ +Index: content_browser_client.cc +=================================================================== +--- content_browser_client.cc (revision 286351) ++++ content_browser_client.cc (working copy) +@@ -280,6 +280,10 @@ + return true; + } + ++SkColor ContentBrowserClient::GetBaseBackgroundColor(RenderViewHost* rvh) { ++ return SK_ColorWHITE; ++} ++ + base::FilePath ContentBrowserClient::GetDefaultDownloadDirectory() { + return base::FilePath(); + } +Index: content_browser_client.h +=================================================================== +--- content_browser_client.h (revision 286351) ++++ content_browser_client.h (working copy) +@@ -23,6 +23,7 @@ + #include "net/cookies/canonical_cookie.h" + #include "net/url_request/url_request_interceptor.h" + #include "net/url_request/url_request_job_factory.h" ++#include "third_party/skia/include/core/SkColor.h" + #include "third_party/WebKit/public/web/WebNotificationPresenter.h" + #include "ui/base/window_open_disposition.h" + #include "webkit/browser/fileapi/file_system_context.h" +@@ -556,6 +557,9 @@ + // Clears browser cookies. + virtual void ClearCookies(RenderViewHost* rvh) {} + ++ // Returns the base background color. ++ virtual SkColor GetBaseBackgroundColor(RenderViewHost* rvh); ++ + // Returns the default download directory. + // This can be called on any thread. + virtual base::FilePath GetDefaultDownloadDirectory(); +Index: web_contents.cc +=================================================================== +--- web_contents.cc (revision 286351) ++++ web_contents.cc (working copy) +@@ -17,7 +17,9 @@ + main_frame_routing_id(MSG_ROUTING_NONE), + initially_hidden(false), + guest_instance_id(0), +- context(NULL) {} ++ context(NULL), ++ view(NULL), ++ delegate_view(NULL) {} + + WebContents::CreateParams::CreateParams( + BrowserContext* context, SiteInstance* site) +@@ -29,7 +31,9 @@ + main_frame_routing_id(MSG_ROUTING_NONE), + initially_hidden(false), + guest_instance_id(0), +- context(NULL) {} ++ context(NULL), ++ view(NULL), ++ delegate_view(NULL) {} + + WebContents::CreateParams::~CreateParams() { + } +Index: web_contents.h +=================================================================== +--- web_contents.h (revision 286351) ++++ web_contents.h (working copy) +@@ -50,9 +50,11 @@ + class RenderFrameHost; + class RenderProcessHost; + class RenderViewHost; ++class RenderViewHostDelegateView; + class RenderWidgetHostView; + class SiteInstance; + class WebContentsDelegate; ++class WebContentsView; + struct CustomContextMenuContext; + struct DropData; + struct RendererPreferences; +@@ -120,6 +122,10 @@ + // Used to specify the location context which display the new view should + // belong. This can be NULL if not needed. + gfx::NativeView context; ++ ++ // Optionally specify the view and delegate view. ++ content::WebContentsView* view; ++ content::RenderViewHostDelegateView* delegate_view; + }; + + // Creates a new WebContents. +Index: web_contents_delegate.cc +=================================================================== +--- web_contents_delegate.cc (revision 286351) ++++ web_contents_delegate.cc (working copy) +@@ -136,7 +136,9 @@ + const base::string16& frame_name, + const GURL& target_url, + const std::string& partition_id, +- SessionStorageNamespace* session_storage_namespace) { ++ SessionStorageNamespace* session_storage_namespace, ++ content::WebContentsView** view, ++ content::RenderViewHostDelegateView** delegate_view) { + return true; + } + +Index: web_contents_delegate.h +=================================================================== +--- web_contents_delegate.h (revision 286351) ++++ web_contents_delegate.h (working copy) +@@ -36,9 +36,11 @@ + class JavaScriptDialogManager; + class PageState; + class RenderViewHost; ++class RenderViewHostDelegateView; + class SessionStorageNamespace; + class WebContents; + class WebContentsImpl; ++class WebContentsView; + struct ColorSuggestion; + struct ContextMenuParams; + struct DropData; +@@ -312,7 +314,9 @@ + const base::string16& frame_name, + const GURL& target_url, + const std::string& partition_id, +- SessionStorageNamespace* session_storage_namespace); ++ SessionStorageNamespace* session_storage_namespace, ++ content::WebContentsView** view, ++ content::RenderViewHostDelegateView** delegate_view); + + // Notifies the delegate about the creation of a new WebContents. This + // typically happens when popups are created. diff --git a/patch/patches/renderer_host_1161.patch b/patch/patches/renderer_host_1161.patch new file mode 100644 index 000000000..92cdbf648 --- /dev/null +++ b/patch/patches/renderer_host_1161.patch @@ -0,0 +1,128 @@ +Index: compositing_iosurface_layer_mac.mm +=================================================================== +--- compositing_iosurface_layer_mac.mm (revision 286351) ++++ compositing_iosurface_layer_mac.mm (working copy) +@@ -202,7 +202,7 @@ + TRACE_EVENT0("browser", "CompositingIOSurfaceLayer::drawInCGLContext"); + + if (!iosurface_->HasIOSurface() || context_->cgl_context() != glContext) { +- glClearColor(1, 1, 1, 1); ++ glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + return; + } +Index: compositing_iosurface_mac.mm +=================================================================== +--- compositing_iosurface_mac.mm (revision 286351) ++++ compositing_iosurface_mac.mm (working copy) +@@ -350,7 +350,7 @@ + glUseProgram(0); CHECK_AND_SAVE_GL_ERROR(); + } else { + // Should match the clear color of RenderWidgetHostViewMac. +- glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ++ glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } + +Index: compositing_iosurface_shader_programs_mac.cc +=================================================================== +--- compositing_iosurface_shader_programs_mac.cc (revision 286351) ++++ compositing_iosurface_shader_programs_mac.cc (working copy) +@@ -11,6 +11,8 @@ + #include "base/debug/trace_event.h" + #include "base/logging.h" + #include "base/memory/scoped_ptr.h" ++#include "base/strings/stringprintf.h" ++#include "base/strings/string_number_conversions.h" + #include "base/values.h" + #include "content/browser/gpu/gpu_data_manager_impl.h" + #include "gpu/config/gpu_driver_bug_workaround_type.h" +@@ -51,6 +53,7 @@ + } + ); + ++float bgcolor[] = {1.0f, 1.0f, 1.0f}; + + // Only calculates position. + const char kvsSolidWhite[] = GLSL_PROGRAM_AS_STRING( +@@ -238,6 +241,18 @@ + const GLuint shader = glCreateShader(shader_type); + DCHECK_NE(shader, 0u); + ++ // Support customization of the background color. ++ std::string bg_shader; ++ if (shader_program == SHADER_PROGRAM_SOLID_WHITE && ++ shader_type == GL_FRAGMENT_SHADER) { ++ bg_shader = base::StringPrintf( ++ "void main() { gl_FragColor = vec4(%s, %s, %s, 1.0); }", ++ base::DoubleToString(bgcolor[0]).c_str(), ++ base::DoubleToString(bgcolor[1]).c_str(), ++ base::DoubleToString(bgcolor[2]).c_str()); ++ kFragmentShaderSourceCodeMap[shader_program] = bg_shader.c_str(); ++ } ++ + // Select and compile the shader program source code. + if (shader_type == GL_VERTEX_SHADER) { + const GLchar* source_snippets[] = { +@@ -412,6 +427,14 @@ + Reset(); + } + ++// static ++void CompositingIOSurfaceShaderPrograms::SetBackgroundColor( ++ float r, float g, float b) { ++ bgcolor[0] = r; ++ bgcolor[1] = g; ++ bgcolor[2] = b; ++} ++ + GLuint CompositingIOSurfaceShaderPrograms::GetShaderProgram(int which) { + if (shader_programs_[which] == 0u) { + shader_programs_[which] = +Index: compositing_iosurface_shader_programs_mac.h +=================================================================== +--- compositing_iosurface_shader_programs_mac.h (revision 286351) ++++ compositing_iosurface_shader_programs_mac.h (working copy) +@@ -48,6 +48,8 @@ + return rgb_to_yv12_output_format_; + } + ++ static void SetBackgroundColor(float r, float g, float b); ++ + protected: + FRIEND_TEST_ALL_PREFIXES(CompositingIOSurfaceTransformerTest, + TransformsRGBToYV12); +Index: render_widget_host_view_aura.cc +=================================================================== +--- render_widget_host_view_aura.cc (revision 286351) ++++ render_widget_host_view_aura.cc (working copy) +@@ -1654,8 +1654,14 @@ + // For non-opaque windows, we don't draw anything, since we depend on the + // canvas coming from the compositor to already be initialized as + // transparent. +- if (window_->layer()->fills_bounds_opaquely()) +- canvas->DrawColor(SK_ColorWHITE); ++ if (window_->layer()->fills_bounds_opaquely()) { ++ if (host_->IsRenderView()) { ++ canvas->DrawColor(GetContentClient()->browser()->GetBaseBackgroundColor( ++ RenderViewHost::From(host_))); ++ } else { ++ canvas->DrawColor(SK_ColorWHITE); ++ } ++ } + } + + void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged( +Index: render_widget_host_view_mac.mm +=================================================================== +--- render_widget_host_view_mac.mm (revision 286351) ++++ render_widget_host_view_mac.mm (working copy) +@@ -473,7 +473,7 @@ + + background_layer_.reset([[CALayer alloc] init]); + [background_layer_ +- setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; ++ setBackgroundColor:CGColorGetConstantColor(kCGColorClear)]; + [cocoa_view_ setLayer:background_layer_]; + [cocoa_view_ setWantsLayer:YES]; + diff --git a/patch/patches/spi_webcore_364.patch b/patch/patches/spi_webcore_364.patch new file mode 100644 index 000000000..6be547d7e --- /dev/null +++ b/patch/patches/spi_webcore_364.patch @@ -0,0 +1,34 @@ +Index: core/frame/FrameView.cpp +=================================================================== +--- core/frame/FrameView.cpp (revision 179174) ++++ core/frame/FrameView.cpp (working copy) +@@ -138,8 +138,10 @@ + if (!m_frame->isMainFrame()) + return; + ++#if 0 + ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); + ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); ++#endif + } + + PassRefPtr FrameView::create(LocalFrame* frame) +Index: platform/scroll/ScrollbarThemeMacCommon.mm +=================================================================== +--- platform/scroll/ScrollbarThemeMacCommon.mm (revision 179174) ++++ platform/scroll/ScrollbarThemeMacCommon.mm (working copy) +@@ -355,10 +355,14 @@ + // static + bool ScrollbarThemeMacCommon::isOverlayAPIAvailable() + { ++#if 0 + static bool apiAvailable = + [NSClassFromString(@"NSScrollerImp") respondsToSelector:@selector(scrollerImpWithStyle:controlSize:horizontal:replacingScrollerImp:)] + && [NSClassFromString(@"NSScrollerImpPair") instancesRespondToSelector:@selector(scrollerStyle)]; + return apiAvailable; ++#else ++ return false; ++#endif + } + + } // namespace WebCore diff --git a/patch/patches/ui_dragdrop_355390.patch b/patch/patches/ui_dragdrop_355390.patch new file mode 100644 index 000000000..037471a2a --- /dev/null +++ b/patch/patches/ui_dragdrop_355390.patch @@ -0,0 +1,14 @@ +Index: os_exchange_data_provider_aurax11.cc +=================================================================== +--- os_exchange_data_provider_aurax11.cc (revision 286351) ++++ os_exchange_data_provider_aurax11.cc (working copy) +@@ -155,7 +155,8 @@ + format_map_.Insert(atom_cache_.GetAtom(kMimeTypeMozillaURL), mem); + + // Set a string fallback as well. +- SetString(spec); ++ if (!HasString()) ++ SetString(spec); + + // Return early if this drag already contains file contents (this implies + // that file contents must be populated before URLs). Nautilus (and possibly diff --git a/patch/patches/underlay_1051.patch b/patch/patches/underlay_1051.patch new file mode 100644 index 000000000..369277f80 --- /dev/null +++ b/patch/patches/underlay_1051.patch @@ -0,0 +1,13 @@ +Index: underlay_opengl_hosting_window.h +=================================================================== +--- underlay_opengl_hosting_window.h (revision 286351) ++++ underlay_opengl_hosting_window.h (working copy) +@@ -12,7 +12,7 @@ + // Common base class for windows that host a OpenGL surface that renders under + // the window. Contains methods relating to hole punching so that the OpenGL + // surface is visible through the window. +-UI_BASE_EXPORT ++__attribute__((visibility("default"))) + @interface UnderlayOpenGLHostingWindow : NSWindow + @end + diff --git a/patch/patches/views_widget_180.patch b/patch/patches/views_widget_180.patch new file mode 100644 index 000000000..9edd5fac3 --- /dev/null +++ b/patch/patches/views_widget_180.patch @@ -0,0 +1,223 @@ +Index: desktop_aura/desktop_screen_win.cc +=================================================================== +--- desktop_aura/desktop_screen_win.cc (revision 286351) ++++ desktop_aura/desktop_screen_win.cc (working copy) +@@ -54,6 +54,8 @@ + } + + HWND DesktopScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { ++ if (!window) ++ return NULL; + aura::WindowTreeHost* host = window->GetHost(); + return host ? host->GetAcceleratedWidget() : NULL; + } +Index: desktop_aura/desktop_screen_x11.cc +=================================================================== +--- desktop_aura/desktop_screen_x11.cc (revision 286351) ++++ desktop_aura/desktop_screen_x11.cc (working copy) +@@ -220,6 +220,9 @@ + + gfx::Display DesktopScreenX11::GetDisplayNearestWindow( + gfx::NativeView window) const { ++ if (!window) ++ return GetPrimaryDisplay(); ++ + // Getting screen bounds here safely is hard. + // + // You'd think we'd be able to just call window->GetBoundsInScreen(), but we +Index: desktop_aura/desktop_window_tree_host_win.cc +=================================================================== +--- desktop_aura/desktop_window_tree_host_win.cc (revision 286351) ++++ desktop_aura/desktop_window_tree_host_win.cc (working copy) +@@ -129,7 +129,9 @@ + native_widget_delegate_); + + HWND parent_hwnd = NULL; +- if (params.parent && params.parent->GetHost()) ++ if (params.parent_widget) ++ parent_hwnd = params.parent_widget; ++ else if (params.parent && params.parent->GetHost()) + parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget(); + + message_handler_->set_remove_standard_frame(params.remove_standard_frame); +@@ -774,6 +776,7 @@ + + void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) { + // TODO(beng): inform the native_widget_delegate_. ++ GetWidget()->GetNativeWindow()->Focus(); + InputMethod* input_method = GetInputMethod(); + if (input_method) + input_method->OnFocus(); +@@ -781,6 +784,7 @@ + + void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) { + // TODO(beng): inform the native_widget_delegate_. ++ GetWidget()->GetNativeWindow()->Blur(); + InputMethod* input_method = GetInputMethod(); + if (input_method) + input_method->OnBlur(); +Index: desktop_aura/desktop_window_tree_host_x11.cc +=================================================================== +--- desktop_aura/desktop_window_tree_host_x11.cc (revision 286351) ++++ desktop_aura/desktop_window_tree_host_x11.cc (working copy) +@@ -148,7 +148,8 @@ + window_parent_(NULL), + window_shape_(NULL), + custom_window_shape_(false), +- urgency_hint_set_(false) { ++ urgency_hint_set_(false), ++ xwindow_destroyed_(false) { + } + + DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() { +@@ -348,7 +349,8 @@ + // Actually free our native resources. + if (ui::PlatformEventSource::GetInstance()) + ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); +- XDestroyWindow(xdisplay_, xwindow_); ++ if (!xwindow_destroyed_) ++ XDestroyWindow(xdisplay_, xwindow_); + xwindow_ = None; + + desktop_native_widget_aura_->OnHostClosed(); +@@ -444,6 +446,8 @@ + } + + gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const { ++ if (!screen_bounds_.IsEmpty()) ++ return screen_bounds_; + return bounds_; + } + +@@ -456,6 +460,8 @@ + // Attempts to calculate the rect by asking the NonClientFrameView what it + // thought its GetBoundsForClientView() were broke combobox drop down + // placement. ++ if (!screen_bounds_.IsEmpty()) ++ return screen_bounds_; + return bounds_; + } + +@@ -904,6 +910,8 @@ + } + + gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { ++ if (!screen_bounds_.IsEmpty()) ++ return screen_bounds_.origin(); + return bounds_.origin(); + } + +@@ -1047,9 +1055,13 @@ + } + } + ++ gfx::AcceleratedWidget parent_widget = params.parent_widget; ++ if (parent_widget == gfx::kNullAcceleratedWidget) ++ parent_widget = x_root_window_; ++ + bounds_ = params.bounds; + xwindow_ = XCreateWindow( +- xdisplay_, x_root_window_, ++ xdisplay_, parent_widget, + bounds_.x(), bounds_.y(), + bounds_.width(), bounds_.height(), + 0, // border width +@@ -1603,6 +1615,10 @@ + } + break; + } ++ case DestroyNotify: ++ xwindow_destroyed_ = true; ++ CloseNow(); ++ break; + case FocusOut: + if (xev->xfocus.mode != NotifyGrab) { + ReleaseCapture(); +Index: desktop_aura/desktop_window_tree_host_x11.h +=================================================================== +--- desktop_aura/desktop_window_tree_host_x11.h (revision 286351) ++++ desktop_aura/desktop_window_tree_host_x11.h (working copy) +@@ -85,6 +85,8 @@ + // Deallocates the internal list of open windows. + static void CleanUpWindowList(); + ++ void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; } ++ + protected: + // Overridden from DesktopWindowTreeHost: + virtual void Init(aura::Window* content_window, +@@ -254,6 +256,9 @@ + // The bounds of |xwindow_|. + gfx::Rect bounds_; + ++ // Override the screen bounds when the host is a child window. ++ gfx::Rect screen_bounds_; ++ + // Whenever the bounds are set, we keep the previous set of bounds around so + // we can have a better chance of getting the real |restored_bounds_|. Window + // managers tend to send a Configure message with the maximized bounds, and +@@ -337,6 +342,9 @@ + + base::CancelableCallback delayed_resize_task_; + ++ // True if the xwindow has already been destroyed. ++ bool xwindow_destroyed_; ++ + DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11); + }; + +Index: widget.cc +=================================================================== +--- widget.cc (revision 286351) ++++ widget.cc (working copy) +@@ -116,6 +116,7 @@ + show_state(ui::SHOW_STATE_DEFAULT), + double_buffer(false), + parent(NULL), ++ parent_widget(gfx::kNullAcceleratedWidget), + native_widget(NULL), + desktop_window_tree_host(NULL), + layer_type(aura::WINDOW_LAYER_TEXTURED), +@@ -140,6 +141,7 @@ + show_state(ui::SHOW_STATE_DEFAULT), + double_buffer(false), + parent(NULL), ++ parent_widget(gfx::kNullAcceleratedWidget), + native_widget(NULL), + desktop_window_tree_host(NULL), + layer_type(aura::WINDOW_LAYER_TEXTURED), +@@ -314,7 +316,7 @@ + InitParams params = in_params; + + params.child |= (params.type == InitParams::TYPE_CONTROL); +- is_top_level_ = !params.child; ++ is_top_level_ = !params.child || params.parent_widget; + + if (params.opacity == views::Widget::InitParams::INFER_OPACITY && + params.type != views::Widget::InitParams::TYPE_WINDOW && +@@ -375,7 +377,12 @@ + Minimize(); + } else if (params.delegate) { + SetContentsView(params.delegate->GetContentsView()); +- SetInitialBoundsForFramelessWindow(params.bounds); ++ if (params.parent_widget) { ++ // Set the bounds directly instead of applying an inset. ++ SetBounds(params.bounds); ++ } else { ++ SetInitialBoundsForFramelessWindow(params.bounds); ++ } + } + // This must come after SetContentsView() or it might not be able to find + // the correct NativeTheme (on Linux). See http://crbug.com/384492 +Index: widget.h +=================================================================== +--- widget.h (revision 286351) ++++ widget.h (working copy) +@@ -225,6 +225,7 @@ + // Should the widget be double buffered? Default is false. + bool double_buffer; + gfx::NativeView parent; ++ gfx::AcceleratedWidget parent_widget; + // Specifies the initial bounds of the Widget. Default is empty, which means + // the NativeWidget may specify a default size. If the parent is specified, + // |bounds| is in the parent's coordinate system. If the parent is not diff --git a/patch/patches/webkit_933.patch b/patch/patches/webkit_933.patch new file mode 100644 index 000000000..8acb0f3e5 --- /dev/null +++ b/patch/patches/webkit_933.patch @@ -0,0 +1,13 @@ +Index: WebNode.cpp +=================================================================== +--- WebNode.cpp (revision 179174) ++++ WebNode.cpp (working copy) +@@ -173,7 +173,7 @@ + void WebNode::addEventListener(const WebString& eventType, WebDOMEventListener* listener, bool useCapture) + { + // Please do not add more eventTypes to this list without an API review. +- RELEASE_ASSERT(eventType == "mousedown"); ++ // RELEASE_ASSERT(eventType == "mousedown"); + + EventListenerWrapper* listenerWrapper = listener->createEventListenerWrapper(eventType, useCapture, m_private.get()); + // The listenerWrapper is only referenced by the actual Node. Once it goes diff --git a/patch/patches/webkit_popups.patch b/patch/patches/webkit_popups.patch new file mode 100644 index 000000000..c07ce2946 --- /dev/null +++ b/patch/patches/webkit_popups.patch @@ -0,0 +1,76 @@ +Index: public/web/WebView.h +=================================================================== +--- public/web/WebView.h (revision 179174) ++++ public/web/WebView.h (working copy) +@@ -416,6 +416,7 @@ + + // Sets whether select popup menus should be rendered by the browser. + BLINK_EXPORT static void setUseExternalPopupMenus(bool); ++ virtual void setUseExternalPopupMenusThisInstance(bool) = 0; + + // Hides any popup (suggestions, selects...) that might be showing. + virtual void hidePopups() = 0; +Index: Source/web/ChromeClientImpl.cpp +=================================================================== +--- Source/web/ChromeClientImpl.cpp (revision 179174) ++++ Source/web/ChromeClientImpl.cpp (working copy) +@@ -727,7 +727,7 @@ + + PassRefPtr ChromeClientImpl::createPopupMenu(LocalFrame& frame, PopupMenuClient* client) const + { +- if (WebViewImpl::useExternalPopupMenus()) ++ if (m_webView->useExternalPopupMenus()) + return adoptRef(new ExternalPopupMenu(frame, client, *m_webView)); + + return adoptRef(new PopupMenuChromium(frame, client)); +Index: Source/web/WebViewImpl.cpp +=================================================================== +--- Source/web/WebViewImpl.cpp (revision 179174) ++++ Source/web/WebViewImpl.cpp (working copy) +@@ -368,6 +368,7 @@ + , m_fakePageScaleAnimationPageScaleFactor(0) + , m_fakePageScaleAnimationUseAnchor(false) + , m_contextMenuAllowed(false) ++ , m_shouldUseExternalPopupMenus(shouldUseExternalPopupMenus) + , m_doingDragAndDrop(false) + , m_ignoreInputEvents(false) + , m_compositorDeviceScaleFactorOverride(0) +@@ -3673,9 +3674,14 @@ + updateLayerTreeViewport(); + } + ++void WebViewImpl::setUseExternalPopupMenusThisInstance(bool useExternalPopupMenus) ++{ ++ m_shouldUseExternalPopupMenus = useExternalPopupMenus; ++} ++ + bool WebViewImpl::useExternalPopupMenus() + { +- return shouldUseExternalPopupMenus; ++ return m_shouldUseExternalPopupMenus; + } + + void WebViewImpl::startDragging(LocalFrame* frame, +Index: Source/web/WebViewImpl.h +=================================================================== +--- Source/web/WebViewImpl.h (revision 179174) ++++ Source/web/WebViewImpl.h (working copy) +@@ -353,7 +353,8 @@ + + // Returns true if popup menus should be rendered by the browser, false if + // they should be rendered by WebKit (which is the default). +- static bool useExternalPopupMenus(); ++ void setUseExternalPopupMenusThisInstance(bool); ++ bool useExternalPopupMenus(); + + bool contextMenuAllowed() const + { +@@ -629,6 +630,8 @@ + + bool m_contextMenuAllowed; + ++ bool m_shouldUseExternalPopupMenus; ++ + bool m_doingDragAndDrop; + + bool m_ignoreInputEvents; diff --git a/patch/patches/zlib.patch b/patch/patches/zlib.patch new file mode 100644 index 000000000..82547479e --- /dev/null +++ b/patch/patches/zlib.patch @@ -0,0 +1,13 @@ +Index: contrib/minizip/unzip.c +=================================================================== +--- contrib/minizip/unzip.c (revision 286351) ++++ contrib/minizip/unzip.c (working copy) +@@ -69,7 +69,7 @@ + #include + + #ifndef NOUNCRYPT +- #define NOUNCRYPT ++// #define NOUNCRYPT + #endif + + #include "third_party/zlib/zlib.h" diff --git a/tests/cefclient/binding_test.cpp b/tests/cefclient/binding_test.cpp new file mode 100644 index 000000000..8fe4a5a14 --- /dev/null +++ b/tests/cefclient/binding_test.cpp @@ -0,0 +1,55 @@ +// 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/binding_test.h" + +#include +#include + +#include "include/wrapper/cef_stream_resource_handler.h" + +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 browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr 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(ClientHandler::MessageHandlerSet& handlers) { + handlers.insert(new Handler()); +} + +} // namespace binding_test diff --git a/tests/cefclient/binding_test.h b/tests/cefclient/binding_test.h new file mode 100644 index 000000000..e8f1e02a4 --- /dev/null +++ b/tests/cefclient/binding_test.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. + +#ifndef CEF_TESTS_CEFCLIENT_BINDING_TEST_H_ +#define CEF_TESTS_CEFCLIENT_BINDING_TEST_H_ +#pragma once + +#include "cefclient/client_handler.h" + +namespace binding_test { + +// Handler creation. Called from ClientHandler. +void CreateMessageHandlers(ClientHandler::MessageHandlerSet& handlers); + +} // namespace binding_test + +#endif // CEF_TESTS_CEFCLIENT_BINDING_TEST_H_ diff --git a/tests/cefclient/bytes_write_handler.cpp b/tests/cefclient/bytes_write_handler.cpp new file mode 100644 index 000000000..7569417a5 --- /dev/null +++ b/tests/cefclient/bytes_write_handler.cpp @@ -0,0 +1,94 @@ +// 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/bytes_write_handler.h" + +#include +#include + +#include "include/wrapper/cef_helpers.h" + +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(size * n) >= datasize_ && + Grow(size * n) == 0) { + rv = 0; + } else { + memcpy(reinterpret_cast(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; +} diff --git a/tests/cefclient/bytes_write_handler.h b/tests/cefclient/bytes_write_handler.h new file mode 100644 index 000000000..24da860ba --- /dev/null +++ b/tests/cefclient/bytes_write_handler.h @@ -0,0 +1,39 @@ +// 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_BYTES_WRITE_HANDLER_H_ +#define CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_ +#pragma once + +#include "include/base/cef_lock.h" +#include "include/cef_stream.h" + +class BytesWriteHandler : public CefWriteHandler { + public: + explicit BytesWriteHandler(size_t grow); + virtual ~BytesWriteHandler(); + + virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE; + virtual int Seek(int64 offset, int whence) OVERRIDE; + virtual int64 Tell() OVERRIDE; + virtual int Flush() OVERRIDE; + virtual bool MayBlock() OVERRIDE { return false; } + + void* GetData() { return data_; } + int64 GetDataSize() { return offset_; } + + protected: + size_t Grow(size_t size); + + size_t grow_; + void* data_; + int64 datasize_; + int64 offset_; + + base::Lock lock_; + + IMPLEMENT_REFCOUNTING(BytesWriteHandler); +}; + +#endif // CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_ diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp new file mode 100644 index 000000000..aa3a5542a --- /dev/null +++ b/tests/cefclient/cefclient.cpp @@ -0,0 +1,195 @@ +// 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/cefclient.h" +#include +#include +#include +#include +#include "include/cef_app.h" +#include "include/cef_browser.h" +#include "include/cef_command_line.h" +#include "include/cef_frame.h" +#include "include/cef_web_plugin.h" +#include "include/wrapper/cef_helpers.h" +#include "cefclient/client_handler.h" +#include "cefclient/client_switches.h" +#include "cefclient/string_util.h" + +CefRefPtr g_handler; +CefRefPtr g_command_line; + +CefRefPtr AppGetBrowser() { + if (!g_handler.get()) + return NULL; + return g_handler->GetBrowser(); +} + +ClientWindowHandle AppGetMainWindowHandle() { + if (!g_handler.get()) + return kNullWindowHandle; + return g_handler->GetMainWindowHandle(); +} + +void AppInitCommandLine(int argc, const char* const* argv) { + g_command_line = CefCommandLine::CreateCommandLine(); +#if defined(OS_WIN) + g_command_line->InitFromString(::GetCommandLineW()); +#else + g_command_line->InitFromArgv(argc, argv); +#endif +} + +// Returns the application command line object. +CefRefPtr AppGetCommandLine() { + return g_command_line; +} + +// Returns the application settings based on command line arguments. +void AppGetSettings(CefSettings& settings) { + DCHECK(g_command_line.get()); + if (!g_command_line.get()) + return; + + CefString str; + +#if defined(OS_WIN) + settings.multi_threaded_message_loop = + g_command_line->HasSwitch(cefclient::kMultiThreadedMessageLoop); +#endif + + CefString(&settings.cache_path) = + g_command_line->GetSwitchValue(cefclient::kCachePath); + + if (g_command_line->HasSwitch(cefclient::kOffScreenRenderingEnabled)) + settings.windowless_rendering_enabled = true; +} + +void AppGetBrowserSettings(CefBrowserSettings& settings) { + DCHECK(g_command_line.get()); + if (!g_command_line.get()) + return; + + if (g_command_line->HasSwitch(cefclient::kOffScreenFrameRate)) { + settings.windowless_frame_rate = atoi(g_command_line-> + GetSwitchValue(cefclient::kOffScreenFrameRate).ToString().c_str()); + } +} + +bool AppIsOffScreenRenderingEnabled() { + DCHECK(g_command_line.get()); + if (!g_command_line.get()) + return false; + + return g_command_line->HasSwitch(cefclient::kOffScreenRenderingEnabled); +} + +void RunGetSourceTest(CefRefPtr browser) { + class Visitor : public CefStringVisitor { + public: + explicit Visitor(CefRefPtr browser) : browser_(browser) {} + virtual void Visit(const CefString& string) OVERRIDE { + std::string source = StringReplace(string, "<", "<"); + source = StringReplace(source, ">", ">"); + std::stringstream ss; + ss << "Source:
" << source <<
+            "
"; + browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/getsource"); + } + private: + CefRefPtr browser_; + IMPLEMENT_REFCOUNTING(Visitor); + }; + + browser->GetMainFrame()->GetSource(new Visitor(browser)); +} + +void RunGetTextTest(CefRefPtr browser) { + class Visitor : public CefStringVisitor { + public: + explicit Visitor(CefRefPtr browser) : browser_(browser) {} + virtual void Visit(const CefString& string) OVERRIDE { + std::string text = StringReplace(string, "<", "<"); + text = StringReplace(text, ">", ">"); + std::stringstream ss; + ss << "Text:
" << text <<
+            "
"; + browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/gettext"); + } + private: + CefRefPtr browser_; + IMPLEMENT_REFCOUNTING(Visitor); + }; + + browser->GetMainFrame()->GetText(new Visitor(browser)); +} + +void RunRequestTest(CefRefPtr browser) { + // Create a new request + CefRefPtr 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 postDataElement(CefPostDataElement::Create()); + std::string data = "arg1=val1&arg2=val2"; + postDataElement->SetToBytes(data.length(), data.c_str()); + CefRefPtr 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 RunPopupTest(CefRefPtr browser) { + browser->GetMainFrame()->ExecuteJavaScript( + "window.open('http://www.google.com');", "about:blank", 0); +} + +void RunPluginInfoTest(CefRefPtr browser) { + class Visitor : public CefWebPluginInfoVisitor { + public: + explicit Visitor(CefRefPtr browser) + : browser_(browser) { + html_ = "Plugin Info Test" + "" + "\nInstalled plugins:"; + } + ~Visitor() { + html_ += "\n"; + + // Load the html in the browser. + browser_->GetMainFrame()->LoadString(html_, "http://tests/plugin_info"); + } + + virtual bool Visit(CefRefPtr info, int count, int total) + OVERRIDE { + html_ += "\n

Name: " + info->GetName().ToString() + + "\n
Description: " + info->GetDescription().ToString() + + "\n
Version: " + info->GetVersion().ToString() + + "\n
Path: " + info->GetPath().ToString(); + return true; + } + + private: + std::string html_; + CefRefPtr browser_; + IMPLEMENT_REFCOUNTING(Visitor); + }; + + CefVisitWebPluginInfo(new Visitor(browser)); +} + +void RunOtherTests(CefRefPtr browser) { + browser->GetMainFrame()->LoadURL("http://tests/other_tests"); +} diff --git a/tests/cefclient/cefclient.exe.manifest b/tests/cefclient/cefclient.exe.manifest new file mode 100644 index 000000000..d36f084b6 --- /dev/null +++ b/tests/cefclient/cefclient.exe.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cefclient/cefclient.h b/tests/cefclient/cefclient.h new file mode 100644 index 000000000..da337a29a --- /dev/null +++ b/tests/cefclient/cefclient.h @@ -0,0 +1,56 @@ +// 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_CEFCLIENT_H_ +#define CEF_TESTS_CEFCLIENT_CEFCLIENT_H_ +#pragma once + +#include +#include "include/cef_base.h" +#include "cefclient/client_app.h" +#include "cefclient/client_handler.h" + +class CefApp; +class CefBrowser; +class CefCommandLine; + +// Returns the main browser window instance. +CefRefPtr AppGetBrowser(); + +// Returns the main application window handle. +ClientWindowHandle AppGetMainWindowHandle(); + +// Returns the application working directory. +std::string AppGetWorkingDirectory(); + +// Initialize the application command line. +void AppInitCommandLine(int argc, const char* const* argv); + +// Returns the application command line object. +CefRefPtr AppGetCommandLine(); + +// Returns the application settings based on command line arguments. +void AppGetSettings(CefSettings& settings); +void AppGetBrowserSettings(CefBrowserSettings& settings); + +// Returns true if off-screen rendering is enabled via the command line +// argument. +bool AppIsOffScreenRenderingEnabled(); + +// Quit the application message loop. +void AppQuitMessageLoop(); + +// Implementations for various tests. +void RunGetSourceTest(CefRefPtr browser); +void RunGetTextTest(CefRefPtr browser); +void RunRequestTest(CefRefPtr browser); +void RunPopupTest(CefRefPtr browser); +void RunPluginInfoTest(CefRefPtr browser); +void RunOtherTests(CefRefPtr browser); + +#if defined(OS_WIN) +void RunTransparentPopupTest(CefRefPtr browser); +#endif + +#endif // CEF_TESTS_CEFCLIENT_CEFCLIENT_H_ diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc new file mode 100644 index 000000000..18b8c4f84 --- /dev/null +++ b/tests/cefclient/cefclient.rc @@ -0,0 +1,172 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Binary +// + +IDS_BINDING BINARY "res\\binding.html" +IDS_DIALOGS BINARY "res\\dialogs.html" +IDS_DOMACCESS BINARY "res\\domaccess.html" +IDS_LOCALSTORAGE BINARY "res\\localstorage.html" +IDS_LOGO BINARY "res\\logo.png" +IDS_OSRTEST BINARY "res\\osr_test.html" +IDS_OTHER_TESTS BINARY "res\\other_tests.html" +IDS_PERFORMANCE BINARY "res\\performance.html" +IDS_PERFORMANCE2 BINARY "res\\performance2.html" +IDS_TRANSPARENCY BINARY "res\\transparency.html" +IDS_WINDOW BINARY "res\\window.html" +IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CEFCLIENT ICON "res\cefclient.ico" +IDI_SMALL ICON "res\small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_CEFCLIENT MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Find...", ID_FIND + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END + POPUP "Tests" + BEGIN + MENUITEM "Get Source", ID_TESTS_GETSOURCE + MENUITEM "Get Text", ID_TESTS_GETTEXT + MENUITEM "Popup Window", ID_TESTS_POPUP + MENUITEM "Request", ID_TESTS_REQUEST + MENUITEM "Plugin Info", ID_TESTS_PLUGIN_INFO + MENUITEM "Zoom In", ID_TESTS_ZOOM_IN + MENUITEM "Zoom Out", ID_TESTS_ZOOM_OUT + MENUITEM "Zoom Reset", ID_TESTS_ZOOM_RESET + MENUITEM "Begin Tracing", ID_TESTS_TRACING_BEGIN + MENUITEM "End Tracing", ID_TESTS_TRACING_END + MENUITEM "Print", ID_TESTS_PRINT + MENUITEM "Other Tests", ID_TESTS_OTHER_TESTS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_CEFCLIENT ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 22, 17, 230, 75 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_CEFCLIENT,IDC_MYICON,14,9,16,16 + LTEXT "cefclient Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2008",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "cefclient" + IDC_CEFCLIENT "CEFCLIENT" + IDS_OSR_WIDGET_CLASS "CEFCLIENT-OSR-WIDGET" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tests/cefclient/cefclient_gtk.cpp b/tests/cefclient/cefclient_gtk.cpp new file mode 100644 index 000000000..386508074 --- /dev/null +++ b/tests/cefclient/cefclient_gtk.cpp @@ -0,0 +1,477 @@ +// 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 +#include +#include +#include + +#include +#undef Success // Definition conflicts with cef_message_router.h + +#include +#include +#include + +#include "cefclient/cefclient.h" +#include "include/cef_app.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "include/wrapper/cef_helpers.h" +#include "cefclient/cefclient_osr_widget_gtk.h" +#include "cefclient/client_handler.h" +#include "cefclient/client_switches.h" +#include "cefclient/scheme_test.h" +#include "cefclient/string_util.h" + +// The global ClientHandler reference. +extern CefRefPtr g_handler; + +namespace { + +char szWorkingDir[512]; // The current working directory + +// Height of the buttons at the top of the GTK window. +int g_toolbar_height = 0; + +class MainBrowserProvider : public OSRBrowserProvider { + virtual CefRefPtr GetBrowser() { + if (g_handler.get()) + return g_handler->GetBrowser(); + + return NULL; + } +} g_main_browser_provider; + +void destroy(GtkWidget* widget, gpointer data) { + // Quitting CEF is handled in ClientHandler::OnBeforeClose(). +} + +gboolean delete_event(GtkWidget* widget, GdkEvent* event, + GtkWindow* window) { + if (g_handler.get() && !g_handler->IsClosing()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) { + // 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; +} + +void TerminationSignalHandler(int signatl) { + AppQuitMessageLoop(); +} + +void VboxSizeAllocated(GtkWidget *widget, + GtkAllocation *allocation, + void *data) { + if (g_handler) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser && !browser->GetHost()->IsWindowRenderingDisabled()) { + // Size the browser window to match the GTK widget. + ::Display* xdisplay = cef_get_xdisplay(); + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + XWindowChanges changes = {0}; + changes.width = allocation->width; + changes.height = allocation->height - g_toolbar_height; + XConfigureWindow(xdisplay, xwindow, CWHeight | CWWidth, &changes); + } + } +} + +void ToolbarSizeAllocated(GtkWidget *widget, + GtkAllocation *allocation, + void *data) { + g_toolbar_height = allocation->height; +} + +gboolean WindowFocusIn(GtkWidget* widget, + GdkEventFocus* event, + gpointer user_data) { + if (g_handler && event->in) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser) { + if (browser->GetHost()->IsWindowRenderingDisabled()) { + // Give focus to the off-screen browser. + browser->GetHost()->SendFocusEvent(true); + } else { + // Give focus to the browser window. + browser->GetHost()->SetFocus(true); + return TRUE; + } + } + } + + return FALSE; +} + +// Callback for Tests > Get Source... menu item. +gboolean GetSourceActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunGetSourceTest(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Get Text... menu item. +gboolean GetTextActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunGetTextTest(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Popup Window... menu item. +gboolean PopupWindowActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunPopupTest(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Request... menu item. +gboolean RequestActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunRequestTest(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Plugin Info... menu item. +gboolean PluginInfoActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunPluginInfoTest(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Zoom In... menu item. +gboolean ZoomInActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(browser->GetHost()->GetZoomLevel() + 0.5); + } + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Zoom Out... menu item. +gboolean ZoomOutActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(browser->GetHost()->GetZoomLevel() - 0.5); + } + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Zoom Reset... menu item. +gboolean ZoomResetActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(0.0); + } + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Begin Tracing menu item. +gboolean BeginTracingActivated(GtkWidget* widget) { + if (g_handler.get()) + g_handler->BeginTracing(); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > End Tracing menu item. +gboolean EndTracingActivated(GtkWidget* widget) { + if (g_handler.get()) + g_handler->EndTracing(); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Print menu item. +gboolean PrintActivated(GtkWidget* widget) { + if (g_handler.get()) + g_handler->GetBrowser()->GetHost()->Print(); + + return FALSE; // Don't stop this message. +} + +// Callback for Tests > Other Tests... menu item. +gboolean OtherTestsActivated(GtkWidget* widget) { + if (g_handler.get() && g_handler->GetBrowserId()) + RunOtherTests(g_handler->GetBrowser()); + + return FALSE; // Don't stop this message. +} + +// Callback for when you click the back button. +void BackButtonClicked(GtkButton* button) { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->GoBack(); +} + +// Callback for when you click the forward button. +void ForwardButtonClicked(GtkButton* button) { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->GoForward(); +} + +// Callback for when you click the stop button. +void StopButtonClicked(GtkButton* button) { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->StopLoad(); +} + +// Callback for when you click the reload button. +void ReloadButtonClicked(GtkButton* button) { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->Reload(); +} + +// Callback for when you press enter in the URL box. +void URLEntryActivate(GtkEntry* entry) { + if (!g_handler.get() || !g_handler->GetBrowserId()) + return; + + const gchar* url = gtk_entry_get_text(entry); + g_handler->GetBrowser()->GetMainFrame()->LoadURL(std::string(url).c_str()); +} + +gboolean URLEntryButtonPress(GtkWidget* widget, + GdkEventButton* event, + gpointer user_data) { + // Give focus to the GTK window. + 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; +} + +// GTK utility functions ---------------------------------------------- + +GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, + GCallback callback) { + GtkWidget* entry = gtk_menu_item_new_with_label(text); + g_signal_connect(entry, "activate", callback, NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry); + return entry; +} + +GtkWidget* 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* CreateMenuBar() { + GtkWidget* menu_bar = gtk_menu_bar_new(); + GtkWidget* debug_menu = CreateMenu(menu_bar, "Tests"); + + AddMenuEntry(debug_menu, "Get Source", + G_CALLBACK(GetSourceActivated)); + AddMenuEntry(debug_menu, "Get Text", + G_CALLBACK(GetTextActivated)); + AddMenuEntry(debug_menu, "Popup Window", + G_CALLBACK(PopupWindowActivated)); + AddMenuEntry(debug_menu, "Request", + G_CALLBACK(RequestActivated)); + AddMenuEntry(debug_menu, "Plugin Info", + G_CALLBACK(PluginInfoActivated)); + AddMenuEntry(debug_menu, "Zoom In", + G_CALLBACK(ZoomInActivated)); + AddMenuEntry(debug_menu, "Zoom Out", + G_CALLBACK(ZoomOutActivated)); + AddMenuEntry(debug_menu, "Zoom Reset", + G_CALLBACK(ZoomResetActivated)); + AddMenuEntry(debug_menu, "Begin Tracing", + G_CALLBACK(BeginTracingActivated)); + AddMenuEntry(debug_menu, "End Tracing", + G_CALLBACK(EndTracingActivated)); + AddMenuEntry(debug_menu, "Print", + G_CALLBACK(PrintActivated)); + AddMenuEntry(debug_menu, "Other Tests", + G_CALLBACK(OtherTestsActivated)); + return menu_bar; +} + +} // namespace + +int main(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); + CefRefPtr app(new ClientApp); + + // Execute the secondary process, if any. + int exit_code = CefExecuteProcess(main_args, app.get(), NULL); + if (exit_code >= 0) + return exit_code; + + if (!getcwd(szWorkingDir, sizeof (szWorkingDir))) + return -1; + + // Parse command line arguments. + AppInitCommandLine(argc, argv_copy); + + CefSettings settings; + + // Populate the settings based on command line arguments. + AppGetSettings(settings); + + // Initialize CEF. + CefInitialize(main_args, settings, app.get(), 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); + + // Register the scheme handler. + scheme_test::InitTest(); + + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); + g_signal_connect(window, "focus-in-event", + G_CALLBACK(WindowFocusIn), NULL); + + GtkWidget* vbox = gtk_vbox_new(FALSE, 0); + g_signal_connect(vbox, "size-allocate", + G_CALLBACK(VboxSizeAllocated), NULL); + gtk_container_add(GTK_CONTAINER(window), vbox); + + GtkWidget* menu_bar = CreateMenuBar(); + + 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(ToolbarSizeAllocated), NULL); + + GtkToolItem* back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK); + g_signal_connect(back, "clicked", + G_CALLBACK(BackButtonClicked), NULL); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back, -1 /* append */); + + GtkToolItem* forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD); + g_signal_connect(forward, "clicked", + G_CALLBACK(ForwardButtonClicked), NULL); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward, -1 /* append */); + + GtkToolItem* reload = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH); + g_signal_connect(reload, "clicked", + G_CALLBACK(ReloadButtonClicked), NULL); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload, -1 /* append */); + + GtkToolItem* stop = gtk_tool_button_new_from_stock(GTK_STOCK_STOP); + g_signal_connect(stop, "clicked", + G_CALLBACK(StopButtonClicked), NULL); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop, -1 /* append */); + + GtkWidget* entry = gtk_entry_new(); + g_signal_connect(entry, "activate", + G_CALLBACK(URLEntryActivate), NULL); + g_signal_connect(entry, "button-press-event", + G_CALLBACK(URLEntryButtonPress), NULL); + + GtkToolItem* tool_item = gtk_tool_item_new(); + gtk_container_add(GTK_CONTAINER(tool_item), 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); + + g_signal_connect(G_OBJECT(window), "destroy", + G_CALLBACK(destroy), NULL); + g_signal_connect(G_OBJECT(window), "delete_event", + G_CALLBACK(delete_event), window); + + // Create the handler. + g_handler = new ClientHandler(); + g_handler->SetMainWindowHandle(vbox); + g_handler->SetEditWindowHandle(entry); + g_handler->SetButtonWindowHandles(GTK_WIDGET(back), GTK_WIDGET(forward), + GTK_WIDGET(reload), GTK_WIDGET(stop)); + + CefWindowInfo window_info; + CefBrowserSettings browserSettings; + + // Populate the browser settings based on command line arguments. + AppGetBrowserSettings(browserSettings); + + if (AppIsOffScreenRenderingEnabled()) { + CefRefPtr cmd_line = AppGetCommandLine(); + bool transparent = + cmd_line->HasSwitch(cefclient::kTransparentPaintingEnabled); + + // Create the GTKGL surface. + CefRefPtr osr_window = + OSRWindow::Create(&g_main_browser_provider, transparent, vbox); + + // Show the GTK window. + gtk_widget_show_all(GTK_WIDGET(window)); + + // The GTK window must be visible before we can retrieve the XID. + ::Window xwindow = + GDK_WINDOW_XID(gtk_widget_get_window(osr_window->GetWindowHandle())); + window_info.SetAsWindowless(xwindow, transparent); + g_handler->SetOSRHandler(osr_window.get()); + } else { + // Show the GTK window. + gtk_widget_show_all(GTK_WIDGET(window)); + + // The GTK window must be visible before we can retrieve the XID. + ::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(window)); + window_info.SetAsChild(xwindow, + CefRect(0, g_toolbar_height, 800, 600 - g_toolbar_height)); + } + + // Create the browser window. + CefBrowserHost::CreateBrowserSync( + window_info, g_handler.get(), + g_handler->GetStartupURL(), browserSettings, NULL); + + // Install a signal handler so we clean up after ourselves. + signal(SIGINT, TerminationSignalHandler); + signal(SIGTERM, TerminationSignalHandler); + + CefRunMessageLoop(); + + CefShutdown(); + + return 0; +} + +// Global functions + +std::string AppGetWorkingDirectory() { + return szWorkingDir; +} + +void AppQuitMessageLoop() { + CefQuitMessageLoop(); +} diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm new file mode 100644 index 000000000..c08fb7e16 --- /dev/null +++ b/tests/cefclient/cefclient_mac.mm @@ -0,0 +1,631 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import +#include +#include "cefclient/cefclient.h" +#include "include/cef_app.h" +#import "include/cef_application_mac.h" +#include "include/cef_browser.h" +#include "include/cef_frame.h" +#include "cefclient/cefclient_osr_widget_mac.h" +#include "cefclient/client_handler.h" +#include "cefclient/client_switches.h" +#include "cefclient/resource_util.h" +#include "cefclient/scheme_test.h" +#include "cefclient/string_util.h" + +// The global ClientHandler reference. +extern CefRefPtr g_handler; + +class MainBrowserProvider : public OSRBrowserProvider { + virtual CefRefPtr GetBrowser() { + if (g_handler.get()) + return g_handler->GetBrowser(); + + return NULL; + } +} g_main_browser_provider; + +char szWorkingDir[512]; // The current working directory + +// Sizes for URL bar layout +#define BUTTON_HEIGHT 22 +#define BUTTON_WIDTH 72 +#define BUTTON_MARGIN 8 +#define URLBAR_HEIGHT 32 + +// Content area size for newly created windows. +const int kWindowWidth = 800; +const int kWindowHeight = 600; + +// Receives notifications from the application. Will delete itself when done. +@interface ClientAppDelegate : NSObject +- (void)createApplication:(id)object; +- (void)tryToTerminateApplication:(NSApplication*)app; + +- (IBAction)testGetSource:(id)sender; +- (IBAction)testGetText:(id)sender; +- (IBAction)testPopupWindow:(id)sender; +- (IBAction)testRequest:(id)sender; +- (IBAction)testPluginInfo:(id)sender; +- (IBAction)testZoomIn:(id)sender; +- (IBAction)testZoomOut:(id)sender; +- (IBAction)testZoomReset:(id)sender; +- (IBAction)testBeginTracing:(id)sender; +- (IBAction)testEndTracing:(id)sender; +- (IBAction)testPrint:(id)sender; +- (IBAction)testOtherTests:(id)sender; +@end + +// Provide the CefAppProtocol implementation required by CEF. +@interface ClientApplication : NSApplication { +@private + BOOL handlingSendEvent_; +} +@end + +@implementation ClientApplication +- (BOOL)isHandlingSendEvent { + return handlingSendEvent_; +} + +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent { + handlingSendEvent_ = handlingSendEvent; +} + +- (void)sendEvent:(NSEvent*)event { + CefScopedSendingEvent sendingEventScoper; + [super sendEvent:event]; +} + +// |-terminate:| is the entry point for orderly "quit" operations in Cocoa. This +// includes the application menu's quit menu item and keyboard equivalent, the +// application's dock icon menu's quit menu item, "quit" (not "force quit") in +// the Activity Monitor, and quits triggered by user logout and system restart +// and shutdown. +// +// The default |-terminate:| implementation ends the process by calling exit(), +// and thus never leaves the main run loop. This is unsuitable for Chromium +// since Chromium depends on leaving the main run loop to perform an orderly +// shutdown. We support the normal |-terminate:| interface by overriding the +// default implementation. Our implementation, which is very specific to the +// needs of Chromium, works by asking the application delegate to terminate +// using its |-tryToTerminateApplication:| method. +// +// |-tryToTerminateApplication:| differs from the standard +// |-applicationShouldTerminate:| in that no special event loop is run in the +// case that immediate termination is not possible (e.g., if dialog boxes +// allowing the user to cancel have to be shown). Instead, this method tries to +// close all browsers by calling CloseBrowser(false) via +// ClientHandler::CloseAllBrowsers. Calling CloseBrowser will result in a call +// to ClientHandler::DoClose and execution of |-performClose:| on the NSWindow. +// DoClose sets a flag that is used to differentiate between new close events +// (e.g., user clicked the window close button) and in-progress close events +// (e.g., user approved the close window dialog). The NSWindowDelegate +// |-windowShouldClose:| method checks this flag and either calls +// CloseBrowser(false) in the case of a new close event or destructs the +// NSWindow in the case of an in-progress close event. +// ClientHandler::OnBeforeClose will be called after the CEF NSView hosted in +// the NSWindow is dealloc'ed. +// +// After the final browser window has closed ClientHandler::OnBeforeClose will +// begin actual tear-down of the application by calling CefQuitMessageLoop. +// This ends the NSApplication event loop and execution then returns to the +// main() function for cleanup before application termination. +// +// The standard |-applicationShouldTerminate:| is not supported, and code paths +// leading to it must be redirected. +- (void)terminate:(id)sender { + ClientAppDelegate* delegate = + static_cast([NSApp delegate]); + [delegate tryToTerminateApplication:self]; + // Return, don't exit. The application is responsible for exiting on its own. +} +@end + + +// Receives notifications from controls and the browser window. Will delete +// itself when done. +@interface ClientWindowDelegate : NSObject +- (IBAction)goBack:(id)sender; +- (IBAction)goForward:(id)sender; +- (IBAction)reload:(id)sender; +- (IBAction)stopLoading:(id)sender; +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender; +- (void)alert:(NSString*)title withMessage:(NSString*)message; +- (void)notifyConsoleMessage:(id)object; +- (void)notifyDownloadComplete:(id)object; +- (void)notifyDownloadError:(id)object; +@end + +@implementation ClientWindowDelegate + +- (IBAction)goBack:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->GoBack(); +} + +- (IBAction)goForward:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->GoForward(); +} + +- (IBAction)reload:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->Reload(); +} + +- (IBAction)stopLoading:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->StopLoad(); +} + +- (IBAction)takeURLStringValueFrom:(NSTextField *)sender { + if (!g_handler.get() || !g_handler->GetBrowserId()) + return; + + NSString *url = [sender stringValue]; + + // if it doesn't already have a prefix, add http. If we can't parse it, + // just don't bother rather than making things worse. + NSURL* tempUrl = [NSURL URLWithString:url]; + if (tempUrl && ![tempUrl scheme]) + url = [@"http://" stringByAppendingString:url]; + + std::string urlStr = [url UTF8String]; + g_handler->GetBrowser()->GetMainFrame()->LoadURL(urlStr); +} + +- (void)alert:(NSString*)title withMessage:(NSString*)message { + NSAlert *alert = [NSAlert alertWithMessageText:title + defaultButton:@"OK" + alternateButton:nil + otherButton:nil + informativeTextWithFormat:@"%@", message]; + [alert runModal]; +} + +- (void)notifyConsoleMessage:(id)object { + std::stringstream ss; + ss << "Console messages will be written to " << g_handler->GetLogFile(); + NSString* str = [NSString stringWithUTF8String:(ss.str().c_str())]; + [self alert:@"Console Messages" withMessage:str]; +} + +- (void)notifyDownloadComplete:(id)object { + std::stringstream ss; + ss << "File \"" << g_handler->GetLastDownloadFile() << + "\" downloaded successfully."; + NSString* str = [NSString stringWithUTF8String:(ss.str().c_str())]; + [self alert:@"File Download" withMessage:str]; +} + +- (void)notifyDownloadError:(id)object { + std::stringstream ss; + ss << "File \"" << g_handler->GetLastDownloadFile() << + "\" failed to download."; + NSString* str = [NSString stringWithUTF8String:(ss.str().c_str())]; + [self alert:@"File Download" withMessage:str]; +} + +// Called when we are activated (when we gain focus). +- (void)windowDidBecomeKey:(NSNotification*)notification { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) { + if (AppIsOffScreenRenderingEnabled()) + browser->GetHost()->SendFocusEvent(true); + else + browser->GetHost()->SetFocus(true); + } + } +} + +// Called when we are deactivated (when we lose focus). +- (void)windowDidResignKey:(NSNotification*)notification { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) { + if (AppIsOffScreenRenderingEnabled()) + browser->GetHost()->SendFocusEvent(false); + else + browser->GetHost()->SetFocus(false); + } + } +} + +// Called when we have been minimized. +- (void)windowDidMiniaturize:(NSNotification *)notification { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) + browser->GetHost()->SetWindowVisibility(false); + } +} + +// Called when we have been unminimized. +- (void)windowDidDeminiaturize:(NSNotification *)notification { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) + browser->GetHost()->SetWindowVisibility(true); + } +} + +// Called when the application has been hidden. +- (void)applicationDidHide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![[notification object] isMiniaturized]) { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) + browser->GetHost()->SetWindowVisibility(false); + } + } +} + +// Called when the application has been unhidden. +- (void)applicationDidUnhide:(NSNotification *)notification { + // If the window is miniaturized then nothing has really changed. + if (![[notification object] isMiniaturized]) { + if (g_handler.get()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) + browser->GetHost()->SetWindowVisibility(true); + } + } +} + +// Called when the window is about to close. Perform the self-destruction +// sequence by getting rid of the window. By returning YES, we allow the window +// to be removed from the screen. +- (BOOL)windowShouldClose:(id)window { + if (g_handler.get() && !g_handler->IsClosing()) { + CefRefPtr browser = g_handler->GetBrowser(); + if (browser.get()) { + // 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 NO; + } + } + + // Try to make the window go away. + [window autorelease]; + + // Clean ourselves up after clearing the stack of anything that might have the + // window on it. + [self performSelectorOnMainThread:@selector(cleanup:) + withObject:window + waitUntilDone:NO]; + + // Allow the close. + return YES; +} + +// Deletes itself. +- (void)cleanup:(id)window { + [self release]; +} + +@end + + +NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { + NSButton* button = [[[NSButton alloc] initWithFrame:*rect] autorelease]; + [button setTitle:title]; + [button setBezelStyle:NSSmallSquareBezelStyle]; + [button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)]; + [parent addSubview:button]; + rect->origin.x += BUTTON_WIDTH; + return button; +} + +@implementation ClientAppDelegate + +// Create the application on the UI thread. +- (void)createApplication:(id)object { + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; + + // Set the delegate for application events. + [NSApp setDelegate:self]; + + // Add the Tests menu. + NSMenu* menubar = [NSApp mainMenu]; + NSMenuItem *testItem = [[[NSMenuItem alloc] initWithTitle:@"Tests" + action:nil + keyEquivalent:@""] autorelease]; + NSMenu *testMenu = [[[NSMenu alloc] initWithTitle:@"Tests"] autorelease]; + [testMenu addItemWithTitle:@"Get Source" + action:@selector(testGetSource:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Get Text" + action:@selector(testGetText:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Popup Window" + action:@selector(testPopupWindow:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Request" + action:@selector(testRequest:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Plugin Info" + action:@selector(testPluginInfo:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Zoom In" + action:@selector(testZoomIn:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Zoom Out" + action:@selector(testZoomOut:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Zoom Reset" + action:@selector(testZoomReset:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Begin Tracing" + action:@selector(testBeginTracing:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"End Tracing" + action:@selector(testEndTracing:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Print" + action:@selector(testPrint:) + keyEquivalent:@""]; + [testMenu addItemWithTitle:@"Other Tests" + action:@selector(testOtherTests:) + keyEquivalent:@""]; + [testItem setSubmenu:testMenu]; + [menubar addItem:testItem]; + + // Create the delegate for control and browser window events. + ClientWindowDelegate* delegate = [[ClientWindowDelegate alloc] init]; + + // Create the main application window. + NSRect screen_rect = [[NSScreen mainScreen] visibleFrame]; + NSRect window_rect = { {0, screen_rect.size.height - kWindowHeight}, + {kWindowWidth, kWindowHeight} }; + NSWindow* mainWnd = [[UnderlayOpenGLHostingWindow alloc] + initWithContentRect:window_rect + styleMask:(NSTitledWindowMask | + NSClosableWindowMask | + NSMiniaturizableWindowMask | + NSResizableWindowMask ) + backing:NSBackingStoreBuffered + defer:NO]; + [mainWnd setTitle:@"cefclient"]; + [mainWnd setDelegate:delegate]; + + // Rely on the window delegate to clean us up rather than immediately + // releasing when the window gets closed. We use the delegate to do + // everything from the autorelease pool so the window isn't on the stack + // during cleanup (ie, a window close from javascript). + [mainWnd setReleasedWhenClosed:NO]; + + NSView* contentView = [mainWnd contentView]; + + // Create the buttons. + NSRect button_rect = [contentView bounds]; + button_rect.origin.y = window_rect.size.height - URLBAR_HEIGHT + + (URLBAR_HEIGHT - BUTTON_HEIGHT) / 2; + button_rect.size.height = BUTTON_HEIGHT; + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = BUTTON_WIDTH; + + NSButton* button = MakeButton(&button_rect, @"Back", contentView); + [button setTarget:delegate]; + [button setAction:@selector(goBack:)]; + + button = MakeButton(&button_rect, @"Forward", contentView); + [button setTarget:delegate]; + [button setAction:@selector(goForward:)]; + + button = MakeButton(&button_rect, @"Reload", contentView); + [button setTarget:delegate]; + [button setAction:@selector(reload:)]; + + button = MakeButton(&button_rect, @"Stop", contentView); + [button setTarget:delegate]; + [button setAction:@selector(stopLoading:)]; + + // Create the URL text field. + button_rect.origin.x += BUTTON_MARGIN; + button_rect.size.width = [contentView bounds].size.width - + button_rect.origin.x - BUTTON_MARGIN; + NSTextField* editWnd = [[NSTextField alloc] initWithFrame:button_rect]; + [contentView addSubview:editWnd]; + [editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; + [editWnd setTarget:delegate]; + [editWnd setAction:@selector(takeURLStringValueFrom:)]; + [[editWnd cell] setWraps:NO]; + [[editWnd cell] setScrollable:YES]; + + // Create the handler. + g_handler = new ClientHandler(); + g_handler->SetMainWindowHandle(contentView); + g_handler->SetEditWindowHandle(editWnd); + + // Create the browser view. + CefWindowInfo window_info; + CefBrowserSettings settings; + + // Populate the browser settings based on command line arguments. + AppGetBrowserSettings(settings); + + if (AppIsOffScreenRenderingEnabled()) { + CefRefPtr cmd_line = AppGetCommandLine(); + bool transparent = + cmd_line->HasSwitch(cefclient::kTransparentPaintingEnabled); + + CefRefPtr osr_window = + OSRWindow::Create(&g_main_browser_provider, transparent, contentView, + CefRect(0, 0, kWindowWidth, kWindowHeight)); + window_info.SetAsWindowless(osr_window->GetWindowHandle(), transparent); + g_handler->SetOSRHandler(osr_window->GetRenderHandler().get()); + } else { + // Initialize window info to the defaults for a child window. + window_info.SetAsChild(contentView, 0, 0, kWindowWidth, kWindowHeight); + } + + CefBrowserHost::CreateBrowser(window_info, g_handler.get(), + g_handler->GetStartupURL(), settings, NULL); + + // Show the window. + [mainWnd makeKeyAndOrderFront: nil]; + + // Size the window. + NSRect r = [mainWnd contentRectForFrameRect:[mainWnd frame]]; + r.size.width = kWindowWidth; + r.size.height = kWindowHeight + URLBAR_HEIGHT; + [mainWnd setFrame:[mainWnd frameRectForContentRect:r] display:YES]; +} + +- (void)tryToTerminateApplication:(NSApplication*)app { + if (g_handler.get() && !g_handler->IsClosing()) + g_handler->CloseAllBrowsers(false); +} + +- (IBAction)testGetSource:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunGetSourceTest(g_handler->GetBrowser()); +} + +- (IBAction)testGetText:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunGetTextTest(g_handler->GetBrowser()); +} + +- (IBAction)testPopupWindow:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunPopupTest(g_handler->GetBrowser()); +} + +- (IBAction)testRequest:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunRequestTest(g_handler->GetBrowser()); +} + +- (IBAction)testPluginInfo:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunPluginInfoTest(g_handler->GetBrowser()); +} + +- (IBAction)testZoomIn:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(browser->GetHost()->GetZoomLevel() + 0.5); + } +} + +- (IBAction)testZoomOut:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(browser->GetHost()->GetZoomLevel() - 0.5); + } +} + +- (IBAction)testZoomReset:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) { + CefRefPtr browser = g_handler->GetBrowser(); + browser->GetHost()->SetZoomLevel(0.0); + } +} + +- (IBAction)testBeginTracing:(id)sender { + if (g_handler.get()) + g_handler->BeginTracing(); +} + +- (IBAction)testEndTracing:(id)sender { + if (g_handler.get()) + g_handler->EndTracing(); +} + +- (IBAction)testPrint:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + g_handler->GetBrowser()->GetHost()->Print(); +} + +- (IBAction)testOtherTests:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunOtherTests(g_handler->GetBrowser()); +} + +- (NSApplicationTerminateReply)applicationShouldTerminate: + (NSApplication *)sender { + return NSTerminateNow; +} + +@end + + +int main(int argc, char* argv[]) { + CefMainArgs main_args(argc, argv); + CefRefPtr app(new ClientApp); + + // Execute the secondary process, if any. + int exit_code = CefExecuteProcess(main_args, app.get(), NULL); + if (exit_code >= 0) + return exit_code; + + // Retrieve the current working directory. + getcwd(szWorkingDir, sizeof(szWorkingDir)); + + // Initialize the AutoRelease pool. + NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init]; + + // Initialize the ClientApplication instance. + [ClientApplication sharedApplication]; + + // Parse command line arguments. + AppInitCommandLine(argc, argv); + + CefSettings settings; + + // Populate the settings based on command line arguments. + AppGetSettings(settings); + + // Initialize CEF. + CefInitialize(main_args, settings, app.get(), NULL); + + // Register the scheme handler. + scheme_test::InitTest(); + + // Create the application delegate and window. + NSObject* delegate = [[ClientAppDelegate alloc] init]; + [delegate performSelectorOnMainThread:@selector(createApplication:) + withObject:nil + waitUntilDone:NO]; + + // Run the application message loop. + CefRunMessageLoop(); + + // Shut down CEF. + CefShutdown(); + + // Release the handler. + g_handler = NULL; + + // Release the delegate. + [delegate release]; + + // Release the AutoRelease pool. + [autopool release]; + + return 0; +} + + +// Global functions + +std::string AppGetWorkingDirectory() { + return szWorkingDir; +} + +void AppQuitMessageLoop() { + CefQuitMessageLoop(); +} diff --git a/tests/cefclient/cefclient_osr_dragdrop_win.cpp b/tests/cefclient/cefclient_osr_dragdrop_win.cpp new file mode 100644 index 000000000..051bbb243 --- /dev/null +++ b/tests/cefclient/cefclient_osr_dragdrop_win.cpp @@ -0,0 +1,648 @@ +// 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/cefclient_osr_dragdrop_win.h" + +#include +#include +#include + +#include +#include + +#include "include/wrapper/cef_helpers.h" +#include "cefclient/bytes_write_handler.h" +#include "cefclient/cefclient_osr_widget_win.h" +#include "cefclient/resource.h" + +namespace { + +DWORD DragOperationToDropEffect(CefRenderHandler::DragOperation allowed_ops) { + DWORD effect = DROPEFFECT_NONE; + if (allowed_ops & DRAG_OPERATION_COPY) + effect |= DROPEFFECT_COPY; + if (allowed_ops & DRAG_OPERATION_LINK) + effect |= DROPEFFECT_LINK; + if (allowed_ops & DRAG_OPERATION_MOVE) + effect |= DROPEFFECT_MOVE; + return effect; +} + +CefRenderHandler::DragOperationsMask DropEffectToDragOperation(DWORD effect) { + DWORD operation = DRAG_OPERATION_NONE; + if (effect & DROPEFFECT_COPY) + operation |= DRAG_OPERATION_COPY; + if (effect & DROPEFFECT_LINK) + operation |= DRAG_OPERATION_LINK; + if (effect & DROPEFFECT_MOVE) + operation |= DRAG_OPERATION_MOVE; + return static_cast(operation); +} + +CefMouseEvent ToMouseEvent(POINTL p, DWORD key_state, HWND hWnd) { + CefMouseEvent ev; + POINT screen_point = { p.x, p.y }; + ScreenToClient(hWnd, &screen_point); + ev.x = screen_point.x; + ev.y = screen_point.y; + ev.modifiers = OSRWindow::GetCefMouseModifiers(key_state); + return ev; +} + + +void GetStorageForBytes(STGMEDIUM* storage, const void* data, size_t bytes) { + HANDLE handle = GlobalAlloc(GPTR, static_cast(bytes)); + if (handle) { + memcpy(handle, data, bytes); + } + + storage->hGlobal = handle; + storage->tymed = TYMED_HGLOBAL; + storage->pUnkForRelease = NULL; +} + +template +void GetStorageForString(STGMEDIUM* stgmed, const std::basic_string& data) { + GetStorageForBytes(stgmed, data.c_str(), + (data.size() + 1) * sizeof(std::basic_string::value_type)); +} + +void GetStorageForFileDescriptor(STGMEDIUM* storage, + const std::wstring& file_name) { + DCHECK(!file_name.empty()); + HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); + + FILEGROUPDESCRIPTOR* descriptor = + reinterpret_cast(hdata); + descriptor->cItems = 1; + descriptor->fgd[0].dwFlags = FD_LINKUI; + wcsncpy_s(descriptor->fgd[0].cFileName, MAX_PATH, file_name.c_str(), + std::min(file_name.size(), static_cast(MAX_PATH - 1u))); + + storage->tymed = TYMED_HGLOBAL; + storage->hGlobal = hdata; + storage->pUnkForRelease = NULL; +} + +// Helper method for converting from text/html to MS CF_HTML. +// Documentation for the CF_HTML format is available at +// http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx +std::string HtmlToCFHtml(const std::string& html, const std::string& base_url) { + if (html.empty()) + return std::string(); + +#define MAX_DIGITS 10 +#define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits) +#define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u" +#define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS) + + static const char* header = "Version:0.9\r\n" + "StartHTML:" NUMBER_FORMAT "\r\n" + "EndHTML:" NUMBER_FORMAT "\r\n" + "StartFragment:" NUMBER_FORMAT "\r\n" + "EndFragment:" NUMBER_FORMAT "\r\n"; + static const char* source_url_prefix = "SourceURL:"; + + static const char* start_markup = "\r\n\r\n"; + static const char* end_markup = "\r\n\r\n"; + + // Calculate offsets + size_t start_html_offset = strlen(header) - strlen(NUMBER_FORMAT) * 4 + + MAX_DIGITS * 4; + if (!base_url.empty()) { + start_html_offset += strlen(source_url_prefix) + base_url.length() + + 2; // Add 2 for \r\n. + } + size_t start_fragment_offset = start_html_offset + strlen(start_markup); + size_t end_fragment_offset = start_fragment_offset + html.length(); + size_t end_html_offset = end_fragment_offset + strlen(end_markup); + char raw_result[1024]; + _snprintf(raw_result, sizeof(1024), + header, + start_html_offset, + end_html_offset, + start_fragment_offset, + end_fragment_offset); + std::string result = raw_result; + if (!base_url.empty()) { + result.append(source_url_prefix); + result.append(base_url); + result.append("\r\n"); + } + result.append(start_markup); + result.append(html); + result.append(end_markup); + +#undef MAX_DIGITS +#undef MAKE_NUMBER_FORMAT_1 +#undef MAKE_NUMBER_FORMAT_2 +#undef NUMBER_FORMAT + + return result; +} + +void CFHtmlExtractMetadata(const std::string& cf_html, + std::string* base_url, + size_t* html_start, + size_t* fragment_start, + size_t* fragment_end) { + // Obtain base_url if present. + if (base_url) { + static std::string src_url_str("SourceURL:"); + size_t line_start = cf_html.find(src_url_str); + if (line_start != std::string::npos) { + size_t src_end = cf_html.find("\n", line_start); + size_t src_start = line_start + src_url_str.length(); + if (src_end != std::string::npos && src_start != std::string::npos) { + *base_url = cf_html.substr(src_start, src_end - src_start); + } + } + } + + // Find the markup between "" and "". + // If the comments cannot be found, like copying from OpenOffice Writer, + // we simply fall back to using StartFragment/EndFragment bytecount values + // to determine the fragment indexes. + std::string cf_html_lower = cf_html; + size_t markup_start = cf_html_lower.find("(atoi(cf_html.c_str() + + start_fragment_start + start_fragment_str.length())); + } + + static std::string end_fragment_str("EndFragment:"); + size_t end_fragment_start = cf_html.find(end_fragment_str); + if (end_fragment_start != std::string::npos) { + *fragment_end = static_cast(atoi(cf_html.c_str() + + end_fragment_start + end_fragment_str.length())); + } + } else { + *fragment_start = cf_html.find('>', tag_start) + 1; + size_t tag_end = cf_html.rfind(" + + + +
+ + Result 1: +
Result 2: +
+ +
+ + + + + + + + + + +
NameResult 1 Avg (ms)Result 2 Avg (ms)% Diff
+
+ + + + + diff --git a/tests/cefclient/res/performance2.html b/tests/cefclient/res/performance2.html new file mode 100644 index 000000000..6664de7b2 --- /dev/null +++ b/tests/cefclient/res/performance2.html @@ -0,0 +1,442 @@ + + + + Performance Tests (2) + + + +

Performance Tests (2)

+ +
+ + + + + + + + + + + + + + + + + + + +
Settings:
Iterations:
Samples:
Mode:Asynchronous + Synchronous +
+
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + +
EnabledNameSamples x IterationsMin, msAvg, msMax, msAverage calls/secMeasuring InacurracyMemory, MBMemory delta, MBDescription
+
+ + + + + diff --git a/tests/cefclient/res/small.ico b/tests/cefclient/res/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 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 + + +Transparency Examples + + + + +

Image Transparency

+Hover over an image to make it fully opaque.
+klematis +klematis + +

Block Transparency

+White 0% White 25% White 50% White 75% White 100% +
+Black 0% Black 25% Black 50% Black 75% Black 100% + + + diff --git a/tests/cefclient/res/window.html b/tests/cefclient/res/window.html new file mode 100644 index 000000000..7d4fe6640 --- /dev/null +++ b/tests/cefclient/res/window.html @@ -0,0 +1,48 @@ + + +Window Test + + + +
+Click a button to perform the associated window action. +
+
+
(minimizes and then restores the window as topmost) +
X: Y: Width: Height: +
+ + diff --git a/tests/cefclient/res/xmlhttprequest.html b/tests/cefclient/res/xmlhttprequest.html new file mode 100644 index 000000000..051f81486 --- /dev/null +++ b/tests/cefclient/res/xmlhttprequest.html @@ -0,0 +1,19 @@ + + + +
+URL: +
+
+
+ + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h new file mode 100644 index 000000000..d7a19f12a --- /dev/null +++ b/tests/cefclient/resource.h @@ -0,0 +1,70 @@ +// 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_WARN_CONSOLEMESSAGE 32000 +#define ID_WARN_DOWNLOADCOMPLETE 32001 +#define ID_WARN_DOWNLOADERROR 32002 +#define ID_QUIT 32500 +#define ID_FIND 32501 +#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_POPUP 32704 +#define ID_TESTS_PRINT 32705 +#define ID_TESTS_REQUEST 32706 +#define ID_TESTS_TRACING_BEGIN 32707 +#define ID_TESTS_TRACING_END 32708 +#define ID_TESTS_ZOOM_IN 32709 +#define ID_TESTS_ZOOM_OUT 32710 +#define ID_TESTS_ZOOM_RESET 32711 +#define IDC_STATIC -1 +#define IDS_BINDING 1000 +#define IDS_DIALOGS 1001 +#define IDS_DOMACCESS 1002 +#define IDS_LOCALSTORAGE 1003 +#define IDS_LOGO 1004 +#define IDS_LOGOBALL 1005 +#define IDS_OSRTEST 1006 +#define IDS_OTHER_TESTS 1007 +#define IDS_PERFORMANCE 1008 +#define IDS_TRANSPARENCY 1009 +#define IDS_WINDOW 1010 +#define IDS_XMLHTTPREQUEST 1011 +#define IDS_PERFORMANCE2 1012 + +// Avoid files associated with MacOS +#define _X86_ + +// 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 diff --git a/tests/cefclient/resource_util.h b/tests/cefclient/resource_util.h new file mode 100644 index 000000000..d38830792 --- /dev/null +++ b/tests/cefclient/resource_util.h @@ -0,0 +1,23 @@ +// 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_RESOURCE_UTIL_H_ +#define CEF_TESTS_CEFCLIENT_RESOURCE_UTIL_H_ +#pragma once + +#include +#include "include/cef_stream.h" + +#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 GetBinaryResourceReader(const char* resource_name); + +#endif // CEF_TESTS_CEFCLIENT_RESOURCE_UTIL_H_ diff --git a/tests/cefclient/resource_util_linux.cpp b/tests/cefclient/resource_util_linux.cpp new file mode 100644 index 000000000..8b5c822e0 --- /dev/null +++ b/tests/cefclient/resource_util_linux.cpp @@ -0,0 +1,30 @@ +// 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/resource_util.h" +#include +#include +#include + +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; +} diff --git a/tests/cefclient/resource_util_mac.mm b/tests/cefclient/resource_util_mac.mm new file mode 100644 index 000000000..7bf6d882e --- /dev/null +++ b/tests/cefclient/resource_util_mac.mm @@ -0,0 +1,61 @@ +// 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/resource_util.h" + +#import +#include +#include + +#include "include/base/cef_logging.h" + +namespace { + +bool AmIBundled() { + // Implementation adapted from Chromium's base/mac/foundation_util.mm + ProcessSerialNumber psn = {0, kCurrentProcess}; + + FSRef fsref; + OSStatus pbErr; + if ((pbErr = GetProcessBundleLocation(&psn, &fsref)) != noErr) { + NOTREACHED(); + return false; + } + + FSCatalogInfo info; + OSErr fsErr; + if ((fsErr = FSGetCatalogInfo(&fsref, kFSCatInfoNodeFlags, &info, + NULL, NULL, NULL)) != noErr) { + NOTREACHED(); + return false; + } + + return (info.nodeFlags & kFSNodeIsDirectoryMask); +} + +} // namespace + +bool GetResourceDir(std::string& dir) { + // Implementation adapted from Chromium's base/base_path_mac.mm + if (AmIBundled()) { + // Retrieve the executable directory. + uint32_t pathSize = 0; + _NSGetExecutablePath(NULL, &pathSize); + if (pathSize > 0) { + dir.resize(pathSize); + _NSGetExecutablePath(const_cast(dir.c_str()), &pathSize); + } + + // Trim executable name up to the last separator + std::string::size_type last_separator = dir.find_last_of("/"); + dir.resize(last_separator); + dir.append("/../Resources"); + return true; + } else { + // TODO: Provide unbundled path + NOTIMPLEMENTED(); + return false; + } +} diff --git a/tests/cefclient/resource_util_posix.cpp b/tests/cefclient/resource_util_posix.cpp new file mode 100644 index 000000000..68a4331f6 --- /dev/null +++ b/tests/cefclient/resource_util_posix.cpp @@ -0,0 +1,59 @@ +// 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/resource_util.h" +#include + +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 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); +} diff --git a/tests/cefclient/resource_util_win.cpp b/tests/cefclient/resource_util_win.cpp new file mode 100644 index 000000000..a5a640760 --- /dev/null +++ b/tests/cefclient/resource_util_win.cpp @@ -0,0 +1,92 @@ +// 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/resource_util.h" +#include "include/base/cef_logging.h" +#include "include/cef_stream.h" +#include "include/wrapper/cef_byte_read_handler.h" +#include "cefclient/resource.h" + +namespace { + +bool LoadBinaryResource(int binaryId, DWORD &dwSize, LPBYTE &pBytes) { + HINSTANCE hInst = GetModuleHandle(NULL); + HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(binaryId), + MAKEINTRESOURCE(256)); + if (hRes) { + HGLOBAL hGlob = LoadResource(hInst, hRes); + if (hGlob) { + dwSize = SizeofResource(hInst, hRes); + pBytes = (LPBYTE)LockResource(hGlob); + if (dwSize > 0 && pBytes) + return true; + } + } + + return false; +} + +int GetResourceId(const char* resource_name) { + // Map of resource labels to BINARY id values. + static struct _resource_map { + char* name; + int id; + } resource_map[] = { + {"binding.html", IDS_BINDING}, + {"dialogs.html", IDS_DIALOGS}, + {"domaccess.html", IDS_DOMACCESS}, + {"localstorage.html", IDS_LOCALSTORAGE}, + {"logo.png", IDS_LOGO}, + {"osr_test.html", IDS_OSRTEST}, + {"other_tests.html", IDS_OTHER_TESTS}, + {"performance.html", IDS_PERFORMANCE}, + {"performance2.html", IDS_PERFORMANCE2}, + {"transparency.html", IDS_TRANSPARENCY}, + {"window.html", IDS_WINDOW}, + {"xmlhttprequest.html", IDS_XMLHTTPREQUEST}, + }; + + for (int i = 0; i < sizeof(resource_map)/sizeof(_resource_map); ++i) { + if (!strcmp(resource_map[i].name, resource_name)) + return resource_map[i].id; + } + + return 0; +} + +} // namespace + +bool LoadBinaryResource(const char* resource_name, std::string& resource_data) { + int resource_id = GetResourceId(resource_name); + if (resource_id == 0) + return false; + + DWORD dwSize; + LPBYTE pBytes; + + if (LoadBinaryResource(resource_id, dwSize, pBytes)) { + resource_data = std::string(reinterpret_cast(pBytes), dwSize); + return true; + } + + NOTREACHED(); // The resource should be found. + return false; +} + +CefRefPtr GetBinaryResourceReader(const char* resource_name) { + int resource_id = GetResourceId(resource_name); + if (resource_id == 0) + return NULL; + + DWORD dwSize; + LPBYTE pBytes; + + if (LoadBinaryResource(resource_id, dwSize, pBytes)) { + return CefStreamReader::CreateForHandler( + new CefByteReadHandler(pBytes, dwSize, NULL)); + } + + NOTREACHED(); // The resource should be found. + return NULL; +} diff --git a/tests/cefclient/scheme_test.cpp b/tests/cefclient/scheme_test.cpp new file mode 100644 index 000000000..773247875 --- /dev/null +++ b/tests/cefclient/scheme_test.cpp @@ -0,0 +1,163 @@ +// 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/scheme_test.h" + +#include +#include + +#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/resource_util.h" +#include "cefclient/string_util.h" + +#if defined(OS_WIN) +#include "cefclient/resource.h" +#endif + +namespace scheme_test { + +namespace { + +// Implementation of the schema handler for client:// requests. +class ClientSchemeHandler : public CefResourceHandler { + public: + ClientSchemeHandler() : offset_(0) {} + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr 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_ = "Client Scheme Handler" + "" + "This contents of this page page are served by the " + "ClientSchemeHandler class handling the client:// protocol." + "
You should see an image:" + "
";
+
+      // Output a string representation of the request
+      std::string dump;
+      DumpRequestContents(request, dump);
+      data_.append(dump);
+
+      data_.append("

Try the test form:" + "
" + "" + "" + "" + "
"); + + 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 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 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(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 Create(CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) + OVERRIDE { + CEF_REQUIRE_IO_THREAD(); + return new ClientSchemeHandler(); + } + + IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); +}; + +} // namespace + +void RegisterCustomSchemes(CefRefPtr registrar, + std::vector& cookiable_schemes) { + registrar->AddCustomScheme("client", true, false, false); +} + +void InitTest() { + CefRegisterSchemeHandlerFactory("client", "tests", + new ClientSchemeHandlerFactory()); +} + +} // namespace scheme_test diff --git a/tests/cefclient/scheme_test.h b/tests/cefclient/scheme_test.h new file mode 100644 index 000000000..36f670835 --- /dev/null +++ b/tests/cefclient/scheme_test.h @@ -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_SCHEME_TEST_H_ +#define CEF_TESTS_CEFCLIENT_SCHEME_TEST_H_ +#pragma once + +#include +#include "include/cef_base.h" + +class CefBrowser; +class CefSchemeRegistrar; + +namespace scheme_test { + +// Register the scheme. +void RegisterCustomSchemes(CefRefPtr registrar, + std::vector& cookiable_schemes); + +// Create the scheme handler. +void InitTest(); + +} // namespace scheme_test + +#endif // CEF_TESTS_CEFCLIENT_SCHEME_TEST_H_ diff --git a/tests/cefclient/string_util.cpp b/tests/cefclient/string_util.cpp new file mode 100644 index 000000000..ebeca5c03 --- /dev/null +++ b/tests/cefclient/string_util.cpp @@ -0,0 +1,74 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/string_util.h" +#include +#include +#include "include/cef_request.h" + +void DumpRequestContents(CefRefPtr request, std::string& str) { + 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 postData = request->GetPostData(); + if (postData.get()) { + CefPostData::ElementVector elements; + postData->GetElements(elements); + if (elements.size() > 0) { + ss << "\nPost Data:"; + CefRefPtr 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()); + } + } + } + } + + str = ss.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; +} diff --git a/tests/cefclient/string_util.h b/tests/cefclient/string_util.h new file mode 100644 index 000000000..c43e6f210 --- /dev/null +++ b/tests/cefclient/string_util.h @@ -0,0 +1,21 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef CEF_TESTS_CEFCLIENT_STRING_UTIL_H_ +#define CEF_TESTS_CEFCLIENT_STRING_UTIL_H_ +#pragma once + +#include +#include "include/cef_base.h" + +class CefRequest; + +// Dump the contents of the request into a string. +void DumpRequestContents(CefRefPtr request, std::string& str); + +// Replace all instances of |from| with |to| in |str|. +std::string StringReplace(const std::string& str, const std::string& from, + const std::string& to); + +#endif // CEF_TESTS_CEFCLIENT_STRING_UTIL_H_ diff --git a/tests/cefclient/window_test.cpp b/tests/cefclient/window_test.cpp new file mode 100644 index 000000000..2a86842bf --- /dev/null +++ b/tests/cefclient/window_test.cpp @@ -0,0 +1,102 @@ +// 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/window_test.h" + +#include +#include +#include +#include + +#include "include/wrapper/cef_stream_resource_handler.h" + +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 browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr 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 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) { + SetPos(browser->GetHost()->GetWindowHandle(), + vec[0], vec[1], vec[2], vec[3]); + } + } else if (message_name == kMessageMinimizeName) { + Minimize(browser->GetHost()->GetWindowHandle()); + } else if (message_name == kMessageMaximizeName) { + Maximize(browser->GetHost()->GetWindowHandle()); + } else if (message_name == kMessageRestoreName) { + Restore(browser->GetHost()->GetWindowHandle()); + } else { + NOTREACHED(); + } + + callback->Success(""); + return true; + } +}; + +} // namespace + +void CreateMessageHandlers(ClientHandler::MessageHandlerSet& handlers) { + handlers.insert(new Handler()); +} + +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; +} + +} // namespace window_test diff --git a/tests/cefclient/window_test.h b/tests/cefclient/window_test.h new file mode 100644 index 000000000..3a99a21f1 --- /dev/null +++ b/tests/cefclient/window_test.h @@ -0,0 +1,28 @@ +// 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_WINDOW_TEST_H_ +#define CEF_TESTS_CEFCLIENT_WINDOW_TEST_H_ +#pragma once + +#include "cefclient/client_handler.h" + +namespace window_test { + +/// Handler creation. Called from ClientHandler. +void CreateMessageHandlers(ClientHandler::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(CefWindowHandle handle, int x, int y, int width, int height); +void Minimize(CefWindowHandle handle); +void Maximize(CefWindowHandle handle); +void Restore(CefWindowHandle handle); + +} // namespace window_test + +#endif // CEF_TESTS_CEFCLIENT_WINDOW_TEST_H_ diff --git a/tests/cefclient/window_test_gtk.cpp b/tests/cefclient/window_test_gtk.cpp new file mode 100644 index 000000000..49dd5760a --- /dev/null +++ b/tests/cefclient/window_test_gtk.cpp @@ -0,0 +1,72 @@ +// 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/window_test.h" + +#include + +namespace window_test { + +namespace { + +GtkWindow* GetWindow(CefWindowHandle handle) { + return GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(handle))); +} + +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(CefWindowHandle handle, int x, int y, int width, int height) { + GtkWindow* window = GetWindow(handle); + 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(CefWindowHandle handle) { + GtkWindow* window = GetWindow(handle); + + // Unmaximize the window before minimizing so restore behaves correctly. + if (IsMaximized(window)) + gtk_window_unmaximize(window); + + gtk_window_iconify(window); +} + +void Maximize(CefWindowHandle handle) { + gtk_window_maximize(GetWindow(handle)); +} + +void Restore(CefWindowHandle handle) { + GtkWindow* window = GetWindow(handle); + if (IsMaximized(window)) + gtk_window_unmaximize(window); + else + gtk_window_present(window); +} + +} // namespace window_test diff --git a/tests/cefclient/window_test_mac.mm b/tests/cefclient/window_test_mac.mm new file mode 100644 index 000000000..c61d1b5b1 --- /dev/null +++ b/tests/cefclient/window_test_mac.mm @@ -0,0 +1,69 @@ +// 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/window_test.h" + +#import + +namespace window_test { + +namespace { + +NSWindow* GetWindow(CefWindowHandle handle) { + NSView* view = (NSView*)handle; + return [view window]; +} + +} // namespace + +void SetPos(CefWindowHandle handle, int x, int y, int width, int height) { + NSWindow* window = GetWindow(handle); + + // Make sure the window isn't minimized or maximized. + if ([window isMiniaturized]) + [window deminiaturize:nil]; + else if ([window isZoomed]) + [window performZoom:nil]; + + // Retrieve information for the display that contains the window. + NSScreen* screen = [window screen]; + if (screen == nil) + screen = [NSScreen mainScreen]; + NSRect frame = [screen frame]; + NSRect visibleFrame = [screen visibleFrame]; + + // Make sure the window is inside the display. + CefRect display_rect( + visibleFrame.origin.x, + frame.size.height - visibleFrame.size.height - visibleFrame.origin.y, + visibleFrame.size.width, + visibleFrame.size.height); + CefRect window_rect(x, y, width, height); + ModifyBounds(display_rect, window_rect); + + NSRect newRect; + newRect.origin.x = window_rect.x; + newRect.origin.y = frame.size.height - window_rect.height - window_rect.y; + newRect.size.width = window_rect.width; + newRect.size.height = window_rect.height; + [window setFrame:newRect display:YES]; +} + +void Minimize(CefWindowHandle handle) { + [GetWindow(handle) performMiniaturize:nil]; +} + +void Maximize(CefWindowHandle handle) { + [GetWindow(handle) performZoom:nil]; +} + +void Restore(CefWindowHandle handle) { + NSWindow* window = GetWindow(handle); + if ([window isMiniaturized]) + [window deminiaturize:nil]; + else if ([window isZoomed]) + [window performZoom:nil]; +} + +} // namespace window_test diff --git a/tests/cefclient/window_test_win.cpp b/tests/cefclient/window_test_win.cpp new file mode 100644 index 000000000..f905e4312 --- /dev/null +++ b/tests/cefclient/window_test_win.cpp @@ -0,0 +1,78 @@ +// 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/window_test.h" + +namespace window_test { + +namespace { + +// Toggles the current display state. +void Toggle(CefWindowHandle handle, UINT nCmdShow) { + HWND root_wnd = ::GetAncestor(handle, GA_ROOT); + + // Retrieve current window placement information. + WINDOWPLACEMENT placement; + ::GetWindowPlacement(root_wnd, &placement); + + if (placement.showCmd == nCmdShow) + ::ShowWindow(root_wnd, SW_RESTORE); + else + ::ShowWindow(root_wnd, nCmdShow); +} + +} // namespace + +void SetPos(CefWindowHandle handle, int x, int y, int width, int height) { + HWND root_wnd = ::GetAncestor(handle, GA_ROOT); + + // Retrieve current window placement information. + WINDOWPLACEMENT placement; + ::GetWindowPlacement(root_wnd, &placement); + + // Retrieve information about the display that contains the window. + HMONITOR monitor = MonitorFromRect(&placement.rcNormalPosition, + MONITOR_DEFAULTTONEAREST); + MONITORINFO info; + info.cbSize = sizeof(info); + GetMonitorInfo(monitor, &info); + + // Make sure the window is inside the display. + CefRect display_rect( + info.rcWork.left, + info.rcWork.top, + info.rcWork.right - info.rcWork.left, + info.rcWork.bottom - info.rcWork.top); + CefRect window_rect(x, y, width, height); + ModifyBounds(display_rect, window_rect); + + if (placement.showCmd == SW_MINIMIZE || placement.showCmd == SW_MAXIMIZE) { + // The window is currently minimized or maximized. Restore it to the desired + // position. + placement.rcNormalPosition.left = window_rect.x; + placement.rcNormalPosition.right = window_rect.x + window_rect.width; + placement.rcNormalPosition.top = window_rect.y; + placement.rcNormalPosition.bottom = window_rect.y + window_rect.height; + ::SetWindowPlacement(root_wnd, &placement); + ::ShowWindow(root_wnd, SW_RESTORE); + } else { + // Set the window position. + ::SetWindowPos(root_wnd, NULL, window_rect.x, window_rect.y, + window_rect.width, window_rect.height, SWP_NOZORDER); + } +} + +void Minimize(CefWindowHandle handle) { + Toggle(handle, SW_MINIMIZE); +} + +void Maximize(CefWindowHandle handle) { + Toggle(handle, SW_MAXIMIZE); +} + +void Restore(CefWindowHandle handle) { + ::ShowWindow(::GetAncestor(handle, GA_ROOT), SW_RESTORE); +} + +} // namespace window_test diff --git a/tests/cefsimple/cefsimple.exe.manifest b/tests/cefsimple/cefsimple.exe.manifest new file mode 100644 index 000000000..d36f084b6 --- /dev/null +++ b/tests/cefsimple/cefsimple.exe.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/cefsimple/cefsimple.rc b/tests/cefsimple/cefsimple.rc new file mode 100644 index 000000000..c4f3f2973 --- /dev/null +++ b/tests/cefsimple/cefsimple.rc @@ -0,0 +1,79 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CEFSIMPLE ICON "res\cefsimple.ico" +IDI_SMALL ICON "res\small.ico" + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tests/cefsimple/cefsimple_linux.cpp b/tests/cefsimple/cefsimple_linux.cpp new file mode 100644 index 000000000..18f9c711f --- /dev/null +++ b/tests/cefsimple/cefsimple_linux.cpp @@ -0,0 +1,39 @@ +// 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 "cefsimple/simple_app.h" + +// Entry point function for all processes. +int main(int argc, char* argv[]) { + // Provide CEF with command-line arguments. + CefMainArgs main_args(argc, argv); + + // SimpleApp implements application-level callbacks. It will create the first + // browser instance in OnContextInitialized() after CEF has initialized. + CefRefPtr app(new SimpleApp); + + // CEF applications have multiple sub-processes (render, plugin, GPU, etc) + // that share the same executable. This function checks the command-line and, + // if this is a sub-process, executes the appropriate logic. + int exit_code = CefExecuteProcess(main_args, app.get(), NULL); + if (exit_code >= 0) { + // The sub-process has completed so return here. + return exit_code; + } + + // Specify CEF global settings here. + CefSettings settings; + + // Initialize CEF for the browser process. + CefInitialize(main_args, settings, app.get(), NULL); + + // Run the CEF message loop. This will block until CefQuitMessageLoop() is + // called. + CefRunMessageLoop(); + + // Shut down CEF. + CefShutdown(); + + return 0; +} diff --git a/tests/cefsimple/cefsimple_mac.mm b/tests/cefsimple/cefsimple_mac.mm new file mode 100644 index 000000000..d4052fa3a --- /dev/null +++ b/tests/cefsimple/cefsimple_mac.mm @@ -0,0 +1,150 @@ +// Copyright (c) 2013 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +#include "cefsimple/simple_app.h" +#include "cefsimple/simple_handler.h" +#include "include/cef_application_mac.h" +#include "include/wrapper/cef_helpers.h" + +// Receives notifications from the application. +@interface SimpleAppDelegate : NSObject +- (void)createApplication:(id)object; +- (void)tryToTerminateApplication:(NSApplication*)app; +@end + +// Provide the CefAppProtocol implementation required by CEF. +@interface SimpleApplication : NSApplication { +@private + BOOL handlingSendEvent_; +} +@end + +@implementation SimpleApplication +- (BOOL)isHandlingSendEvent { + return handlingSendEvent_; +} + +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent { + handlingSendEvent_ = handlingSendEvent; +} + +- (void)sendEvent:(NSEvent*)event { + CefScopedSendingEvent sendingEventScoper; + [super sendEvent:event]; +} + +// |-terminate:| is the entry point for orderly "quit" operations in Cocoa. This +// includes the application menu's quit menu item and keyboard equivalent, the +// application's dock icon menu's quit menu item, "quit" (not "force quit") in +// the Activity Monitor, and quits triggered by user logout and system restart +// and shutdown. +// +// The default |-terminate:| implementation ends the process by calling exit(), +// and thus never leaves the main run loop. This is unsuitable for Chromium +// since Chromium depends on leaving the main run loop to perform an orderly +// shutdown. We support the normal |-terminate:| interface by overriding the +// default implementation. Our implementation, which is very specific to the +// needs of Chromium, works by asking the application delegate to terminate +// using its |-tryToTerminateApplication:| method. +// +// |-tryToTerminateApplication:| differs from the standard +// |-applicationShouldTerminate:| in that no special event loop is run in the +// case that immediate termination is not possible (e.g., if dialog boxes +// allowing the user to cancel have to be shown). Instead, this method tries to +// close all browsers by calling CloseBrowser(false) via +// ClientHandler::CloseAllBrowsers. Calling CloseBrowser will result in a call +// to ClientHandler::DoClose and execution of |-performClose:| on the NSWindow. +// DoClose sets a flag that is used to differentiate between new close events +// (e.g., user clicked the window close button) and in-progress close events +// (e.g., user approved the close window dialog). The NSWindowDelegate +// |-windowShouldClose:| method checks this flag and either calls +// CloseBrowser(false) in the case of a new close event or destructs the +// NSWindow in the case of an in-progress close event. +// ClientHandler::OnBeforeClose will be called after the CEF NSView hosted in +// the NSWindow is dealloc'ed. +// +// After the final browser window has closed ClientHandler::OnBeforeClose will +// begin actual tear-down of the application by calling CefQuitMessageLoop. +// This ends the NSApplication event loop and execution then returns to the +// main() function for cleanup before application termination. +// +// The standard |-applicationShouldTerminate:| is not supported, and code paths +// leading to it must be redirected. +- (void)terminate:(id)sender { + SimpleAppDelegate* delegate = + static_cast([NSApp delegate]); + [delegate tryToTerminateApplication:self]; + // Return, don't exit. The application is responsible for exiting on its own. +} +@end + +@implementation SimpleAppDelegate + +// Create the application on the UI thread. +- (void)createApplication:(id)object { + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"MainMenu" owner:NSApp]; + + // Set the delegate for application events. + [NSApp setDelegate:self]; +} + +- (void)tryToTerminateApplication:(NSApplication*)app { + SimpleHandler* handler = SimpleHandler::GetInstance(); + if (handler && !handler->IsClosing()) + handler->CloseAllBrowsers(false); +} + +- (NSApplicationTerminateReply)applicationShouldTerminate: + (NSApplication *)sender { + return NSTerminateNow; +} +@end + + +// Entry point function for the browser process. +int main(int argc, char* argv[]) { + // Provide CEF with command-line arguments. + CefMainArgs main_args(argc, argv); + + // SimpleApp implements application-level callbacks. It will create the first + // browser instance in OnContextInitialized() after CEF has initialized. + CefRefPtr app(new SimpleApp); + + // Initialize the AutoRelease pool. + NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init]; + + // Initialize the SimpleApplication instance. + [SimpleApplication sharedApplication]; + + // Specify CEF global settings here. + CefSettings settings; + + // Initialize CEF for the browser process. + CefInitialize(main_args, settings, app.get(), NULL); + + // Create the application delegate. + NSObject* delegate = [[SimpleAppDelegate alloc] init]; + [delegate performSelectorOnMainThread:@selector(createApplication:) + withObject:nil + waitUntilDone:NO]; + + // Run the CEF message loop. This will block until CefQuitMessageLoop() is + // called. + CefRunMessageLoop(); + + // Shut down CEF. + CefShutdown(); + + // Release the delegate. + [delegate release]; + + // Release the AutoRelease pool. + [autopool release]; + + return 0; +} diff --git a/tests/cefsimple/cefsimple_win.cpp b/tests/cefsimple/cefsimple_win.cpp new file mode 100644 index 000000000..22975d4ee --- /dev/null +++ b/tests/cefsimple/cefsimple_win.cpp @@ -0,0 +1,72 @@ +// 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 + +#include "cefsimple/simple_app.h" +#include "include/cef_sandbox_win.h" + + +// Set to 0 to disable sandbox support. +#define CEF_ENABLE_SANDBOX 1 + +#if CEF_ENABLE_SANDBOX +// The cef_sandbox.lib static library is currently built with VS2010. It may not +// link successfully with other VS versions. +#pragma comment(lib, "cef_sandbox.lib") +#endif + + +// Entry point function for all processes. +int APIENTRY wWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) { + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + void* sandbox_info = NULL; + +#if CEF_ENABLE_SANDBOX + // Manage the life span of the sandbox information object. This is necessary + // for sandbox support on Windows. See cef_sandbox_win.h for complete details. + CefScopedSandboxInfo scoped_sandbox; + sandbox_info = scoped_sandbox.sandbox_info(); +#endif + + // Provide CEF with command-line arguments. + CefMainArgs main_args(hInstance); + + // SimpleApp implements application-level callbacks. It will create the first + // browser instance in OnContextInitialized() after CEF has initialized. + CefRefPtr app(new SimpleApp); + + // CEF applications have multiple sub-processes (render, plugin, GPU, etc) + // that share the same executable. This function checks the command-line and, + // if this is a sub-process, executes the appropriate logic. + int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info); + if (exit_code >= 0) { + // The sub-process has completed so return here. + return exit_code; + } + + // Specify CEF global settings here. + CefSettings settings; + +#if !CEF_ENABLE_SANDBOX + settings.no_sandbox = true; +#endif + + // Initialize CEF. + CefInitialize(main_args, settings, app.get(), sandbox_info); + + // Run the CEF message loop. This will block until CefQuitMessageLoop() is + // called. + CefRunMessageLoop(); + + // Shut down CEF. + CefShutdown(); + + return 0; +} diff --git a/tests/cefsimple/mac/English.lproj/InfoPlist.strings b/tests/cefsimple/mac/English.lproj/InfoPlist.strings new file mode 100644 index 000000000..dc5ebb069 --- /dev/null +++ b/tests/cefsimple/mac/English.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "© Chromium Embedded Framework Authors, 2013"; diff --git a/tests/cefsimple/mac/English.lproj/MainMenu.xib b/tests/cefsimple/mac/English.lproj/MainMenu.xib new file mode 100644 index 000000000..55facd0fb --- /dev/null +++ b/tests/cefsimple/mac/English.lproj/MainMenu.xib @@ -0,0 +1,2880 @@ + + + + 1050 + 10F569 + 820 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 820 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + cefsimple + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + TestShell + + YES + + + About cefsimple + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide cefsimple + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit cefsimple + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling… + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 1048576 + 2147483647 + + + submenuAction: + + Format + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Show Colors + C + 1179648 + 2147483647 + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + cefsimple Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + YES + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + orderFrontColorPanel: + + + + 361 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 299 + + + YES + + + + + + 300 + + + YES + + + + + + + 344 + + + + + 345 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 389 + + + + + + + YES + + YES + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 299.IBPluginDependency + 300.IBEditorWindowLastContentRect + 300.IBPluginDependency + 300.editorWindowContentRectSynchronizationRect + 344.IBPluginDependency + 345.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 389.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{906, 713}, {164, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{375, 955}, {171, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {272, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{675, 493}, {240, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{144, 735}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {164, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{835, 663}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{304, 905}, {197, 73}} + {{541, 736}, {426, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 836}, {430, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{785, 693}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{254, 935}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{719, 693}, {173, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{188, 935}, {176, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {212, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{553, 553}, {193, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{18, 653}, {200, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{633, 533}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{102, 775}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 439 + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSController + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSController.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAlert.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAnimation.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBox.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBoxCell.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDatePickerCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSImage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSRuleEditor.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSound.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechRecognizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechSynthesizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSplitView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTabView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextStorage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenField.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenFieldCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbar.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSMetadata.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSSpellServer.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + Print.framework/Headers/PDEPluginInterface.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + + + NSUserDefaultsController + NSController + + IBFrameworkSource + AppKit.framework/Headers/NSUserDefaultsController.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + + + NSWindow + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../../../../cef.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/tests/cefsimple/mac/Info.plist b/tests/cefsimple/mac/Info.plist new file mode 100644 index 000000000..9ee43b2d5 --- /dev/null +++ b/tests/cefsimple/mac/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + cefsimple.icns + CFBundleIdentifier + org.cef.cefsimple + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/cefsimple/mac/cefsimple.icns b/tests/cefsimple/mac/cefsimple.icns new file mode 100644 index 0000000000000000000000000000000000000000..f36742de2572421b1eaa5569f64ab34e450ddb67 GIT binary patch literal 55080 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%0Ac$%Pvh#VA!uK`rp4)7 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 OV{TRe000a^@Bjd~o7PtV literal 0 HcmV?d00001 diff --git a/tests/cefsimple/mac/helper-Info.plist b/tests/cefsimple/mac/helper-Info.plist new file mode 100644 index 000000000..32763b065 --- /dev/null +++ b/tests/cefsimple/mac/helper-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${EXECUTABLE_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.cef.cefsimple.helper + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSFileQuarantineEnabled + + LSMinimumSystemVersion + 10.5.0 + LSUIElement + 1 + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/tests/cefsimple/process_helper_mac.cpp b/tests/cefsimple/process_helper_mac.cpp new file mode 100644 index 000000000..2ebbc2ddb --- /dev/null +++ b/tests/cefsimple/process_helper_mac.cpp @@ -0,0 +1,14 @@ +// 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 "include/cef_app.h" + +// Entry point function for sub-processes. +int main(int argc, char* argv[]) { + // Provide CEF with command-line arguments. + CefMainArgs main_args(argc, argv); + + // Execute the sub-process. + return CefExecuteProcess(main_args, NULL, NULL); +} diff --git a/tests/cefsimple/res/cefsimple.ico b/tests/cefsimple/res/cefsimple.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 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 + +#include "cefsimple/simple_handler.h" +#include "include/cef_browser.h" +#include "include/cef_command_line.h" +#include "include/wrapper/cef_helpers.h" + +SimpleApp::SimpleApp() { +} + +void SimpleApp::OnContextInitialized() { + CEF_REQUIRE_UI_THREAD(); + + // Information used when creating the native window. + CefWindowInfo window_info; + +#if defined(OS_WIN) + // On Windows we need to specify certain flags that will be passed to + // CreateWindowEx(). + window_info.SetAsPopup(NULL, "cefsimple"); +#endif + + // SimpleHandler implements browser-level callbacks. + CefRefPtr handler(new SimpleHandler()); + + // Specify CEF browser settings here. + CefBrowserSettings browser_settings; + + std::string url; + + // Check if a "--url=" value was provided via the command-line. If so, use + // that instead of the default URL. + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); + url = command_line->GetSwitchValue("url"); + if (url.empty()) + url = "http://www.google.com"; + + // Create the first browser window. + CefBrowserHost::CreateBrowser(window_info, handler.get(), url, + browser_settings, NULL); +} diff --git a/tests/cefsimple/simple_app.h b/tests/cefsimple/simple_app.h new file mode 100644 index 000000000..1e454a428 --- /dev/null +++ b/tests/cefsimple/simple_app.h @@ -0,0 +1,27 @@ +// 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_CEFSIMPLE_SIMPLE_APP_H_ +#define CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_ + +#include "include/cef_app.h" + +class SimpleApp : public CefApp, + public CefBrowserProcessHandler { + public: + SimpleApp(); + + // CefApp methods: + virtual CefRefPtr GetBrowserProcessHandler() + OVERRIDE { return this; } + + // CefBrowserProcessHandler methods: + virtual void OnContextInitialized() OVERRIDE; + + private: + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(SimpleApp); +}; + +#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_ diff --git a/tests/cefsimple/simple_handler.cpp b/tests/cefsimple/simple_handler.cpp new file mode 100644 index 000000000..0d71f0e20 --- /dev/null +++ b/tests/cefsimple/simple_handler.cpp @@ -0,0 +1,111 @@ +// 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 "cefsimple/simple_handler.h" + +#include +#include + +#include "include/base/cef_bind.h" +#include "include/cef_app.h" +#include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_helpers.h" + +namespace { + +SimpleHandler* g_instance = NULL; + +} // namespace + +SimpleHandler::SimpleHandler() + : is_closing_(false) { + DCHECK(!g_instance); + g_instance = this; +} + +SimpleHandler::~SimpleHandler() { + g_instance = NULL; +} + +// static +SimpleHandler* SimpleHandler::GetInstance() { + return g_instance; +} + +void SimpleHandler::OnAfterCreated(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + // Add to the list of existing browsers. + browser_list_.push_back(browser); +} + +bool SimpleHandler::DoClose(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + // Closing the main window requires special handling. See the DoClose() + // documentation in the CEF header for a detailed destription of this + // process. + if (browser_list_.size() == 1) { + // Set a flag to indicate that the window close should be allowed. + is_closing_ = true; + } + + // Allow the close. For windowed browsers this will result in the OS close + // event being sent. + return false; +} + +void SimpleHandler::OnBeforeClose(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + // Remove from the list of existing browsers. + BrowserList::iterator bit = browser_list_.begin(); + for (; bit != browser_list_.end(); ++bit) { + if ((*bit)->IsSame(browser)) { + browser_list_.erase(bit); + break; + } + } + + if (browser_list_.empty()) { + // All browser windows have closed. Quit the application message loop. + CefQuitMessageLoop(); + } +} + +void SimpleHandler::OnLoadError(CefRefPtr browser, + CefRefPtr 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; + + // Display a load error message. + std::stringstream ss; + ss << "" + "

Failed to load URL " << std::string(failedUrl) << + " with error " << std::string(errorText) << " (" << errorCode << + ").

"; + frame->LoadString(ss.str(), failedUrl); +} + +void SimpleHandler::CloseAllBrowsers(bool force_close) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&SimpleHandler::CloseAllBrowsers, this, force_close)); + return; + } + + if (browser_list_.empty()) + return; + + BrowserList::const_iterator it = browser_list_.begin(); + for (; it != browser_list_.end(); ++it) + (*it)->GetHost()->CloseBrowser(force_close); +} diff --git a/tests/cefsimple/simple_handler.h b/tests/cefsimple/simple_handler.h new file mode 100644 index 000000000..1f272ff1f --- /dev/null +++ b/tests/cefsimple/simple_handler.h @@ -0,0 +1,66 @@ +// 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_CEFSIMPLE_SIMPLE_HANDLER_H_ +#define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_ + +#include "include/cef_client.h" + +#include + +class SimpleHandler : public CefClient, + public CefDisplayHandler, + public CefLifeSpanHandler, + public CefLoadHandler { + public: + SimpleHandler(); + ~SimpleHandler(); + + // Provide access to the single global instance of this object. + static SimpleHandler* GetInstance(); + + // CefClient methods: + virtual CefRefPtr GetDisplayHandler() OVERRIDE { + return this; + } + virtual CefRefPtr GetLifeSpanHandler() OVERRIDE { + return this; + } + virtual CefRefPtr GetLoadHandler() OVERRIDE { + return this; + } + + // CefDisplayHandler methods: + virtual void OnTitleChange(CefRefPtr browser, + const CefString& title) OVERRIDE; + + // CefLifeSpanHandler methods: + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; + virtual bool DoClose(CefRefPtr browser) OVERRIDE; + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; + + // CefLoadHandler methods: + virtual void OnLoadError(CefRefPtr browser, + CefRefPtr frame, + ErrorCode errorCode, + const CefString& errorText, + const CefString& failedUrl) OVERRIDE; + + // Request that all existing browser windows close. + void CloseAllBrowsers(bool force_close); + + bool IsClosing() const { return is_closing_; } + + private: + // List of existing browser windows. Only accessed on the CEF UI thread. + typedef std::list > BrowserList; + BrowserList browser_list_; + + bool is_closing_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(SimpleHandler); +}; + +#endif // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_ diff --git a/tests/cefsimple/simple_handler_linux.cpp b/tests/cefsimple/simple_handler_linux.cpp new file mode 100644 index 000000000..a1e04e15e --- /dev/null +++ b/tests/cefsimple/simple_handler_linux.cpp @@ -0,0 +1,54 @@ +// 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 "cefsimple/simple_handler.h" + +#include +#include +#include + +#include "include/cef_browser.h" +#include "include/wrapper/cef_helpers.h" + +void SimpleHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + std::string titleStr(title); + + // Retrieve the X11 display shared with Chromium. + ::Display* display = cef_get_xdisplay(); + DCHECK(display); + + // Retrieve the X11 window handle for the browser. + ::Window window = browser->GetHost()->GetWindowHandle(); + DCHECK_NE(window, kNullWindowHandle); + + // Retrieve the atoms required by the below XChangeProperty call. + const char* kAtoms[] = { + "_NET_WM_NAME", + "UTF8_STRING" + }; + Atom atoms[2]; + int result = XInternAtoms(display, const_cast(kAtoms), 2, false, + atoms); + if (!result) + NOTREACHED(); + + // Set the window title. + XChangeProperty(display, + window, + atoms[0], + atoms[1], + 8, + PropModeReplace, + reinterpret_cast(titleStr.c_str()), + titleStr.size()); + + // TODO(erg): This is technically wrong. So XStoreName and friends expect + // this in Host Portable Character Encoding instead of UTF-8, which I believe + // is Compound Text. This shouldn't matter 90% of the time since this is the + // fallback to the UTF8 property above. + XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str()); +} + diff --git a/tests/cefsimple/simple_handler_mac.mm b/tests/cefsimple/simple_handler_mac.mm new file mode 100644 index 000000000..696959a5c --- /dev/null +++ b/tests/cefsimple/simple_handler_mac.mm @@ -0,0 +1,21 @@ +// 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 "cefsimple/simple_handler.h" + +#import + +#include "include/cef_browser.h" +#include "include/wrapper/cef_helpers.h" + +void SimpleHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + + NSView* view = (NSView*)browser->GetHost()->GetWindowHandle(); + NSWindow* window = [view window]; + std::string titleStr(title); + NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; + [window setTitle:str]; +} diff --git a/tests/cefsimple/simple_handler_win.cpp b/tests/cefsimple/simple_handler_win.cpp new file mode 100644 index 000000000..32fc1c008 --- /dev/null +++ b/tests/cefsimple/simple_handler_win.cpp @@ -0,0 +1,19 @@ +// 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 "cefsimple/simple_handler.h" + +#include +#include + +#include "include/cef_browser.h" +#include "include/wrapper/cef_helpers.h" + +void SimpleHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + + CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle(); + SetWindowText(hwnd, std::wstring(title).c_str()); +} diff --git a/tests/unittests/browser_info_map_unittest.cc b/tests/unittests/browser_info_map_unittest.cc new file mode 100644 index 000000000..bcb8b9655 --- /dev/null +++ b/tests/unittests/browser_info_map_unittest.cc @@ -0,0 +1,722 @@ +// 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 + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "libcef_dll/wrapper/cef_browser_info_map.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +struct MyObject { + MyObject(int val = 0) : member(val) {} + int member; +}; + +int g_destruct_ct = 0; + +struct MyObjectTraits { + static void Destruct(MyObject info) { + g_destruct_ct++; + } +}; + +typedef CefBrowserInfoMap MyObjectMap; + +class MyVisitor : public MyObjectMap::Visitor { + public: + MyVisitor(bool remove = false, + int remove_browser_id = 0, + InfoIdType remove_info_id = 0) + : remove_(remove), + remove_browser_id_(remove_browser_id), + remove_info_id_(remove_info_id) {} + + virtual bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { + Info info_rec; + info_rec.browser_id = browser_id; + info_rec.info_id = info_id; + info_rec.info = info; + info_list_.push_back(info_rec); + + // Based on test configuration remove no objects, all objects, or only the + // specified object. + *remove = remove_ || (browser_id == remove_browser_id_ && + info_id == remove_info_id_); + return true; + } + + // Returns true if the specified info was passed to OnNextInfo. Removes the + // record if found. + bool Exists(int browser_id, + InfoIdType info_id, + InfoObjectType info) { + InfoList::iterator it = info_list_.begin(); + for (; it != info_list_.end(); ++it) { + const Info& found_info = *it; + if (browser_id == found_info.browser_id && + info_id == found_info.info_id && + info.member == found_info.info.member) { + info_list_.erase(it); + return true; + } + } + return false; + } + + size_t info_size() const { return info_list_.size(); } + + private: + bool remove_; + int remove_browser_id_; + InfoIdType remove_info_id_; + + struct Info { + int browser_id; + InfoIdType info_id; + InfoObjectType info; + }; + + // Track calls to OnNextInfo. + typedef std::list InfoList; + InfoList info_list_; +}; + +} // namespace + +TEST(BrowserInfoMapTest, AddSingleBrowser) { + MyObjectMap map; + const int kBrowserId = 1; + + g_destruct_ct = 0; + + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId)); + + MyObject obj1(1); + map.Add(kBrowserId, 1, obj1); + EXPECT_EQ(1U, map.size()); + EXPECT_EQ(1U, map.size(kBrowserId)); + + MyObject obj2(2); + map.Add(kBrowserId, 2, obj2); + EXPECT_EQ(2U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId)); + + MyObject obj3(3); + map.Add(kBrowserId, 3, obj3); + EXPECT_EQ(3U, map.size()); + EXPECT_EQ(3U, map.size(kBrowserId)); + + EXPECT_EQ(0, g_destruct_ct); + + map.clear(kBrowserId); + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId)); + + EXPECT_EQ(3, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, AddMultipleBrowsers) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId1)); + EXPECT_EQ(0U, map.size(kBrowserId2)); + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + EXPECT_EQ(1U, map.size()); + EXPECT_EQ(1U, map.size(kBrowserId1)); + EXPECT_EQ(0U, map.size(kBrowserId2)); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + EXPECT_EQ(2U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(0U, map.size(kBrowserId2)); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + EXPECT_EQ(3U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(1U, map.size(kBrowserId2)); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + EXPECT_EQ(0, g_destruct_ct); + + map.clear(kBrowserId1); + EXPECT_EQ(2U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + EXPECT_EQ(2, g_destruct_ct); + + map.clear(kBrowserId2); + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId1)); + EXPECT_EQ(0U, map.size(kBrowserId2)); + + EXPECT_EQ(4, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindSingleBrowser) { + MyObjectMap map; + const int kBrowserId = 1; + + g_destruct_ct = 0; + + // obj1 not added yet. + MyObject nf1 = map.Find(kBrowserId, 1, NULL); + EXPECT_EQ(0, nf1.member); + + MyObject obj1(1); + map.Add(kBrowserId, 1, obj1); + + // obj1 should exist. + MyObject f1 = map.Find(kBrowserId, 1, NULL); + EXPECT_EQ(obj1.member, f1.member); + + // obj2 not added yet. + MyObject nf2 = map.Find(kBrowserId, 2, NULL); + EXPECT_EQ(0, nf2.member); + + MyObject obj2(2); + map.Add(kBrowserId, 2, obj2); + + // obj2 should exist. + MyObject f2 = map.Find(kBrowserId, 2, NULL); + EXPECT_EQ(obj2.member, f2.member); + + // find obj1 again. + MyObject f1b = map.Find(kBrowserId, 1, NULL); + EXPECT_EQ(obj1.member, f1b.member); + + // find obj2 again. + MyObject f2b = map.Find(kBrowserId, 2, NULL); + EXPECT_EQ(obj2.member, f2b.member); + + // doesn't exist. + MyObject nf3 = map.Find(kBrowserId, 3, NULL); + EXPECT_EQ(0, nf3.member); + MyObject nf4 = map.Find(10, 1, NULL); + EXPECT_EQ(0, nf4.member); + MyObject nf5 = map.Find(10, 3, NULL); + EXPECT_EQ(0, nf5.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + EXPECT_EQ(2, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindMultipleBrowsers) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + // obj1 not added yet. + MyObject nf1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(0, nf1.member); + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + // obj1 should exist. + MyObject f1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(obj1.member, f1.member); + + // obj2 not added yet. + MyObject nf2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(0, nf2.member); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + // obj2 should exist. + MyObject f2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(obj2.member, f2.member); + + // obj3 not added yet. + MyObject nf3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(0, nf3.member); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + // obj3 should exist. + MyObject f3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(obj3.member, f3.member); + + // obj4 not added yet. + MyObject nf4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(0, nf4.member); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + // obj4 should exist. + MyObject f4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(obj4.member, f4.member); + + // obj1-3 should exist. + MyObject f1b = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(obj1.member, f1b.member); + MyObject f2b = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(obj2.member, f2b.member); + MyObject f3b = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(obj3.member, f3b.member); + + // wrong browser + MyObject nf5 = map.Find(kBrowserId1, 4, NULL); + EXPECT_EQ(0, nf5.member); + MyObject nf6 = map.Find(kBrowserId2, 1, NULL); + EXPECT_EQ(0, nf6.member); + + // deosn't exist + MyObject nf7 = map.Find(kBrowserId2, 5, NULL); + EXPECT_EQ(0, nf7.member); + MyObject nf8 = map.Find(8, 1, NULL); + EXPECT_EQ(0, nf8.member); + MyObject nf9 = map.Find(8, 10, NULL); + EXPECT_EQ(0, nf9.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + EXPECT_EQ(4, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, Find) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should only visit the single object + MyVisitor visitor; + map.Find(kBrowserId2, 4, &visitor); + EXPECT_EQ(1U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + EXPECT_EQ(4, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAndRemove) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should only visit and remove the single object. + MyVisitor visitor(true); + map.Find(kBrowserId1, 2, &visitor); + EXPECT_EQ(1U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 2, obj2)); + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(3U, map.size()); + EXPECT_EQ(1U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // visited object shouldn't exist + MyObject nf2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(0, nf2.member); + + // other objects should exist + MyObject nf1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(obj1.member, nf1.member); + MyObject nf3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(obj3.member, nf3.member); + MyObject nf4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(obj4.member, nf4.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + // should destruct the remaining 3 objects + EXPECT_EQ(3, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAll) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should visit all objects + MyVisitor visitor; + map.FindAll(&visitor); + EXPECT_EQ(4U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 1, obj1)); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 2, obj2)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 3, obj3)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + EXPECT_EQ(4, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAllByBrowser) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should only visit browser2 objects + MyVisitor visitor; + map.FindAll(kBrowserId2, &visitor); + EXPECT_EQ(2U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 3, obj3)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + EXPECT_EQ(4, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAllAndRemoveAll) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should visit all objects + MyVisitor visitor(true); + map.FindAll(&visitor); + EXPECT_EQ(4U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 1, obj1)); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 2, obj2)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 3, obj3)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId1)); + EXPECT_EQ(0U, map.size(kBrowserId2)); + + EXPECT_EQ(0, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAllAndRemoveOne) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should visit all objects and remove one + MyVisitor visitor(false, kBrowserId2, 3); + map.FindAll(&visitor); + EXPECT_EQ(4U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 1, obj1)); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 2, obj2)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 3, obj3)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(3U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(1U, map.size(kBrowserId2)); + + // removed object shouldn't exist + MyObject nf3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(0, nf3.member); + + // other objects should exist + MyObject f1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(obj1.member, f1.member); + MyObject f2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(obj2.member, f2.member); + MyObject f4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(obj4.member, f4.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + // should destruct the remaining 3 objects + EXPECT_EQ(3, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAllAndRemoveAllByBrowser) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should only visit browser1 objects + MyVisitor visitor(true); + map.FindAll(kBrowserId1, &visitor); + EXPECT_EQ(2U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 1, obj1)); + EXPECT_TRUE(visitor.Exists(kBrowserId1, 2, obj2)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(2U, map.size()); + EXPECT_EQ(0U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // browser1 objects shouldn't exist + MyObject nf1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(0, nf1.member); + MyObject nf2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(0, nf2.member); + + // browser 2 objects should exist + MyObject f3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(obj3.member, f3.member); + MyObject f4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(obj4.member, f4.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + // should destruct the remaining 2 objects + EXPECT_EQ(2, g_destruct_ct); +} + +TEST(BrowserInfoMapTest, FindAllAndRemoveOneByBrowser) { + MyObjectMap map; + const int kBrowserId1 = 1; + const int kBrowserId2 = 2; + + g_destruct_ct = 0; + + MyObject obj1(1); + map.Add(kBrowserId1, 1, obj1); + + MyObject obj2(2); + map.Add(kBrowserId1, 2, obj2); + + MyObject obj3(3); + map.Add(kBrowserId2, 3, obj3); + + MyObject obj4(4); + map.Add(kBrowserId2, 4, obj4); + + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(2U, map.size(kBrowserId2)); + + // should visit browser2 objects and remove one + MyVisitor visitor(false, kBrowserId2, 4); + map.FindAll(kBrowserId2, &visitor); + EXPECT_EQ(2U, visitor.info_size()); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 3, obj3)); + EXPECT_TRUE(visitor.Exists(kBrowserId2, 4, obj4)); + // should be no unexpected visits + EXPECT_EQ(0U, visitor.info_size()); + + EXPECT_EQ(3U, map.size()); + EXPECT_EQ(2U, map.size(kBrowserId1)); + EXPECT_EQ(1U, map.size(kBrowserId2)); + + // removed object shouldn't exist + MyObject nf4 = map.Find(kBrowserId2, 4, NULL); + EXPECT_EQ(0, nf4.member); + + // other objects should exist + MyObject f1 = map.Find(kBrowserId1, 1, NULL); + EXPECT_EQ(obj1.member, f1.member); + MyObject f2 = map.Find(kBrowserId1, 2, NULL); + EXPECT_EQ(obj2.member, f2.member); + MyObject f3 = map.Find(kBrowserId2, 3, NULL); + EXPECT_EQ(obj3.member, f3.member); + + EXPECT_EQ(0, g_destruct_ct); + map.clear(); + // should destruct the remaining 3 objects + EXPECT_EQ(3, g_destruct_ct); +} + + +namespace { + +class MyHeapObject { + public: + MyHeapObject(int* destroy_ct) : destroy_ct_(destroy_ct) {} + ~MyHeapObject() { + (*destroy_ct_)++; + } + + private: + int* destroy_ct_; +}; + +} // namespace + +TEST(BrowserInfoMapTest, DefaultTraits) { + CefBrowserInfoMap map; + + int destroy_ct = 0; + map.Add(1, 1, new MyHeapObject(&destroy_ct)); + map.Add(1, 2, new MyHeapObject(&destroy_ct)); + map.Add(2, 1, new MyHeapObject(&destroy_ct)); + map.Add(2, 2, new MyHeapObject(&destroy_ct)); + map.Add(3, 1, new MyHeapObject(&destroy_ct)); + map.Add(3, 2, new MyHeapObject(&destroy_ct)); + + EXPECT_EQ(6U, map.size()); + + map.clear(1); + EXPECT_EQ(4U, map.size()); + EXPECT_EQ(2, destroy_ct); + + map.clear(); + EXPECT_EQ(0U, map.size()); + EXPECT_EQ(6, destroy_ct); +} diff --git a/tests/unittests/chromium_includes.h b/tests/unittests/chromium_includes.h new file mode 100644 index 000000000..0611738a9 --- /dev/null +++ b/tests/unittests/chromium_includes.h @@ -0,0 +1,14 @@ +// 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_UNITTESTS_CHROMIUM_INCLUDES_H_ +#define CEF_TESTS_UNITTESTS_CHROMIUM_INCLUDES_H_ +#pragma once + +// Include some Chromium headers first to avoid type conflicts with CEF headers. +#include "base/bind.h" +#include "base/strings/string16.h" +#include "base/synchronization/lock.h" + +#endif // CEF_TESTS_UNITTESTS_CHROMIUM_INCLUDES_H_ diff --git a/tests/unittests/client_app_delegates.cc b/tests/unittests/client_app_delegates.cc new file mode 100644 index 000000000..311cf1b65 --- /dev/null +++ b/tests/unittests/client_app_delegates.cc @@ -0,0 +1,91 @@ +// 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 "tests/cefclient/client_app.h" + +// static +void ClientApp::CreateBrowserDelegates(BrowserDelegateSet& delegates) { + // Bring in the V8 tests. + extern void CreateV8BrowserTests(BrowserDelegateSet& delegates); + CreateV8BrowserTests(delegates); + + // Bring in the Navigation tests. + extern void CreateNavigationBrowserTests(BrowserDelegateSet& delegates); + CreateNavigationBrowserTests(delegates); + + // Bring in the RequestHandler tests. + extern void CreateRequestHandlerBrowserTests(BrowserDelegateSet& delegates); + CreateRequestHandlerBrowserTests(delegates); +} + +// static +void ClientApp::CreateRenderDelegates(RenderDelegateSet& delegates) { + // Bring in the routing test handler delegate. + extern void CreateRoutingTestHandlerDelegate( + ClientApp::RenderDelegateSet& delegates); + CreateRoutingTestHandlerDelegate(delegates); + + // Bring in the message router tests. + extern void CreateMessageRouterRendererTests( + ClientApp::RenderDelegateSet& delegates); + CreateMessageRouterRendererTests(delegates); + + // Bring in the process message tests. + extern void CreateProcessMessageRendererTests( + ClientApp::RenderDelegateSet& delegates); + CreateProcessMessageRendererTests(delegates); + + // Bring in the V8 tests. + extern void CreateV8RendererTests(RenderDelegateSet& delegates); + CreateV8RendererTests(delegates); + + // Bring in the DOM tests. + extern void CreateDOMRendererTests(RenderDelegateSet& delegates); + CreateDOMRendererTests(delegates); + + // Bring in the URLRequest tests. + extern void CreateURLRequestRendererTests(RenderDelegateSet& delegates); + CreateURLRequestRendererTests(delegates); + + // Bring in the Navigation tests. + extern void CreateNavigationRendererTests(RenderDelegateSet& delegates); + CreateNavigationRendererTests(delegates); + + // Bring in the Request tests. + extern void CreateRequestRendererTests(RenderDelegateSet& delegates); + CreateRequestRendererTests(delegates); + + // Bring in the RequestHandler tests. + extern void CreateRequestHandlerRendererTests(RenderDelegateSet& delegates); + CreateRequestHandlerRendererTests(delegates); +} + +// static +void ClientApp::RegisterCustomSchemes( + CefRefPtr registrar, + std::vector& cookiable_schemes) { + // Bring in the scheme handler tests. + extern void RegisterSchemeHandlerCustomSchemes( + CefRefPtr registrar, + std::vector& cookiable_schemes); + RegisterSchemeHandlerCustomSchemes(registrar, cookiable_schemes); + + // Bring in the cookie tests. + extern void RegisterCookieCustomSchemes( + CefRefPtr registrar, + std::vector& cookiable_schemes); + RegisterCookieCustomSchemes(registrar, cookiable_schemes); + + // Bring in the URLRequest tests. + extern void RegisterURLRequestCustomSchemes( + CefRefPtr registrar, + std::vector& cookiable_schemes); + RegisterURLRequestCustomSchemes(registrar, cookiable_schemes); +} + +// static +CefRefPtr ClientApp::CreatePrintHandler() { + return NULL; +} + diff --git a/tests/unittests/command_line_unittest.cc b/tests/unittests/command_line_unittest.cc new file mode 100644 index 000000000..da303beb4 --- /dev/null +++ b/tests/unittests/command_line_unittest.cc @@ -0,0 +1,121 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_command_line.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +void VerifyCommandLine(CefRefPtr command_line) { + std::string program = command_line->GetProgram(); + EXPECT_EQ("test.exe", program); + + EXPECT_TRUE(command_line->HasSwitches()); + + EXPECT_TRUE(command_line->HasSwitch("switch1")); + std::string switch1 = command_line->GetSwitchValue("switch1"); + EXPECT_EQ("", switch1); + EXPECT_TRUE(command_line->HasSwitch("switch2")); + std::string switch2 = command_line->GetSwitchValue("switch2"); + EXPECT_EQ("val2", switch2); + EXPECT_TRUE(command_line->HasSwitch("switch3")); + std::string switch3 = command_line->GetSwitchValue("switch3"); + EXPECT_EQ("val3", switch3); + EXPECT_TRUE(command_line->HasSwitch("switch4")); + std::string switch4 = command_line->GetSwitchValue("switch4"); + EXPECT_EQ("val 4", switch4); + EXPECT_FALSE(command_line->HasSwitch("switchnoexist")); + + CefCommandLine::SwitchMap switches; + command_line->GetSwitches(switches); + EXPECT_EQ((size_t)4, switches.size()); + + bool has1 = false, has2 = false, has3 = false, has4 = false; + + CefCommandLine::SwitchMap::const_iterator it = switches.begin(); + for (; it != switches.end(); ++it) { + std::string name = it->first; + std::string val = it->second; + + if (name == "switch1") { + has1 = true; + EXPECT_EQ("", val); + } else if (name == "switch2") { + has2 = true; + EXPECT_EQ("val2", val); + } else if (name == "switch3") { + has3 = true; + EXPECT_EQ("val3", val); + } else if (name == "switch4") { + has4 = true; + EXPECT_EQ("val 4", val); + } + } + + EXPECT_TRUE(has1); + EXPECT_TRUE(has2); + EXPECT_TRUE(has3); + EXPECT_TRUE(has4); + + EXPECT_TRUE(command_line->HasArguments()); + + CefCommandLine::ArgumentList args; + command_line->GetArguments(args); + EXPECT_EQ((size_t)2, args.size()); + std::string arg0 = args[0]; + EXPECT_EQ("arg1", arg0); + std::string arg1 = args[1]; + EXPECT_EQ("arg 2", arg1); + + command_line->Reset(); + EXPECT_FALSE(command_line->HasSwitches()); + EXPECT_FALSE(command_line->HasArguments()); + std::string cur_program = command_line->GetProgram(); + EXPECT_EQ(program, cur_program); +} + +} // namespace + +// Test creating a command line from argc/argv or string. +TEST(CommandLineTest, Init) { + CefRefPtr command_line = CefCommandLine::CreateCommandLine(); + EXPECT_TRUE(command_line.get() != NULL); + +#if defined(OS_WIN) + command_line->InitFromString("test.exe --switch1 -switch2=val2 /switch3=val3 " + "-switch4=\"val 4\" arg1 \"arg 2\""); +#else + const char* args[] = { + "test.exe", + "--switch1", + "-switch2=val2", + "-switch3=val3", + "-switch4=val 4", + "arg1", + "arg 2" + }; + command_line->InitFromArgv(sizeof(args) / sizeof(char*), args); +#endif + + VerifyCommandLine(command_line); +} + +// Test creating a command line using set and append methods. +TEST(CommandLineTest, Manual) { + CefRefPtr command_line = CefCommandLine::CreateCommandLine(); + EXPECT_TRUE(command_line.get() != NULL); + + command_line->SetProgram("test.exe"); + command_line->AppendSwitch("switch1"); + command_line->AppendSwitchWithValue("switch2", "val2"); + command_line->AppendSwitchWithValue("switch3", "val3"); + command_line->AppendSwitchWithValue("switch4", "val 4"); + command_line->AppendArgument("arg1"); + command_line->AppendArgument("arg 2"); + + VerifyCommandLine(command_line); +} diff --git a/tests/unittests/cookie_unittest.cc b/tests/unittests/cookie_unittest.cc new file mode 100644 index 000000000..15d148862 --- /dev/null +++ b/tests/unittests/cookie_unittest.cc @@ -0,0 +1,1123 @@ +// 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 + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/files/scoped_temp_dir.h" +#include "base/synchronization/waitable_event.h" + +#include "include/base/cef_bind.h" +#include "include/base/cef_logging.h" +#include "include/base/cef_ref_counted.h" +#include "include/cef_cookie.h" +#include "include/cef_scheme.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_suite.h" + +namespace { + +const char* kTestUrl = "http://www.test.com/path/to/cookietest/foo.html"; +const char* kTestDomain = "www.test.com"; +const char* kTestPath = "/path/to/cookietest"; + +typedef std::vector CookieVector; + +void IOT_Set(CefRefPtr manager, + const CefString& url, CookieVector* cookies, + base::WaitableEvent* event) { + CookieVector::const_iterator it = cookies->begin(); + for (; it != cookies->end(); ++it) + EXPECT_TRUE(manager->SetCookie(url, *it)); + event->Signal(); +} + +void IOT_Delete(CefRefPtr manager, + const CefString& url, const CefString& cookie_name, + base::WaitableEvent* event) { + EXPECT_TRUE(manager->DeleteCookies(url, cookie_name)); + event->Signal(); +} + +class TestVisitor : public CefCookieVisitor { + public: + TestVisitor(CookieVector* cookies, bool deleteCookies, + base::WaitableEvent* event) + : cookies_(cookies), + delete_cookies_(deleteCookies), + event_(event) { + } + virtual ~TestVisitor() { + event_->Signal(); + } + + virtual bool Visit(const CefCookie& cookie, int count, int total, + bool& deleteCookie) { + cookies_->push_back(cookie); + if (delete_cookies_) + deleteCookie = true; + return true; + } + + CookieVector* cookies_; + bool delete_cookies_; + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestVisitor); +}; + +// Set the cookies. +void SetCookies(CefRefPtr manager, + const CefString& url, CookieVector& cookies, + base::WaitableEvent& event) { + CefPostTask(TID_IO, base::Bind(IOT_Set, manager, url, &cookies, &event)); + event.Wait(); +} + +// Delete the cookie. +void DeleteCookies(CefRefPtr manager, + const CefString& url, const CefString& cookie_name, + base::WaitableEvent& event) { + CefPostTask(TID_IO, + base::Bind(IOT_Delete, manager, url, cookie_name, &event)); + event.Wait(); +} + +// Create a test cookie. If |withDomain| is true a domain cookie will be +// created, otherwise a host cookie will be created. +void CreateCookie(CefRefPtr manager, + CefCookie& cookie, bool withDomain, + bool sessionCookie, + base::WaitableEvent& event) { + CefString(&cookie.name).FromASCII("my_cookie"); + CefString(&cookie.value).FromASCII("My Value"); + if (withDomain) + CefString(&cookie.domain).FromASCII(kTestDomain); + CefString(&cookie.path).FromASCII(kTestPath); + if (!sessionCookie) { + cookie.has_expires = true; + cookie.expires.year = 2200; + cookie.expires.month = 4; + cookie.expires.day_of_week = 5; + cookie.expires.day_of_month = 11; + } + + CookieVector cookies; + cookies.push_back(cookie); + + SetCookies(manager, kTestUrl, cookies, event); +} + +// Retrieve the test cookie. If |withDomain| is true check that the cookie +// is a domain cookie, otherwise a host cookie. if |deleteCookies| is true +// the cookie will be deleted when it's retrieved. +void GetCookie(CefRefPtr manager, + const CefCookie& cookie, bool withDomain, + base::WaitableEvent& event, bool deleteCookies) { + CookieVector cookies; + + // Get the cookie and delete it. + EXPECT_TRUE(manager->VisitUrlCookies(kTestUrl, false, + new TestVisitor(&cookies, deleteCookies, &event))); + event.Wait(); + + EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + + const CefCookie& cookie_read = cookies[0]; + EXPECT_EQ(CefString(&cookie_read.name), "my_cookie"); + EXPECT_EQ(CefString(&cookie_read.value), "My Value"); + if (withDomain) + EXPECT_EQ(CefString(&cookie_read.domain), ".www.test.com"); + else + EXPECT_EQ(CefString(&cookie_read.domain), kTestDomain); + EXPECT_EQ(CefString(&cookie_read.path), kTestPath); + EXPECT_EQ(cookie.has_expires, cookie_read.has_expires); + EXPECT_EQ(cookie.expires.year, cookie_read.expires.year); + EXPECT_EQ(cookie.expires.month, cookie_read.expires.month); + EXPECT_EQ(cookie.expires.day_of_week, cookie_read.expires.day_of_week); + EXPECT_EQ(cookie.expires.day_of_month, cookie_read.expires.day_of_month); + EXPECT_EQ(cookie.expires.hour, cookie_read.expires.hour); + EXPECT_EQ(cookie.expires.minute, cookie_read.expires.minute); + EXPECT_EQ(cookie.expires.second, cookie_read.expires.second); + EXPECT_EQ(cookie.expires.millisecond, cookie_read.expires.millisecond); +} + +// Visit URL cookies. +void VisitUrlCookies(CefRefPtr manager, + const CefString& url, + bool includeHttpOnly, + CookieVector& cookies, + bool deleteCookies, + base::WaitableEvent& event) { + EXPECT_TRUE(manager->VisitUrlCookies(url, includeHttpOnly, + new TestVisitor(&cookies, deleteCookies, &event))); + event.Wait(); +} + +// Visit all cookies. +void VisitAllCookies(CefRefPtr manager, + CookieVector& cookies, + bool deleteCookies, + base::WaitableEvent& event) { + EXPECT_TRUE(manager->VisitAllCookies( + new TestVisitor(&cookies, deleteCookies, &event))); + event.Wait(); +} + +// Verify that no cookies exist. If |withUrl| is true it will only check for +// cookies matching the URL. +void VerifyNoCookies(CefRefPtr manager, + base::WaitableEvent& event, bool withUrl) { + CookieVector cookies; + + // Verify that the cookie has been deleted. + if (withUrl) { + EXPECT_TRUE(manager->VisitUrlCookies(kTestUrl, false, + new TestVisitor(&cookies, false, &event))); + } else { + EXPECT_TRUE(manager->VisitAllCookies( + new TestVisitor(&cookies, false, &event))); + } + event.Wait(); + + EXPECT_EQ((CookieVector::size_type)0, cookies.size()); +} + +// Delete all system cookies. +void DeleteAllCookies(CefRefPtr manager, + base::WaitableEvent& event) { + CefPostTask(TID_IO, + base::Bind(IOT_Delete, manager, CefString(), CefString(), &event)); + event.Wait(); +} + +void TestDomainCookie(CefRefPtr manager) { + base::WaitableEvent event(false, false); + CefCookie cookie; + + // Create a domain cookie. + CreateCookie(manager, cookie, true, false, event); + + // Retrieve, verify and delete the domain cookie. + GetCookie(manager, cookie, true, event, true); + + // Verify that the cookie was deleted. + VerifyNoCookies(manager, event, true); +} + +void TestHostCookie(CefRefPtr manager) { + base::WaitableEvent event(false, false); + CefCookie cookie; + + // Create a host cookie. + CreateCookie(manager, cookie, false, false, event); + + // Retrieve, verify and delete the host cookie. + GetCookie(manager, cookie, false, event, true); + + // Verify that the cookie was deleted. + VerifyNoCookies(manager, event, true); +} + +void TestMultipleCookies(CefRefPtr manager) { + base::WaitableEvent event(false, false); + std::stringstream ss; + int i; + + CookieVector cookies; + + const int kNumCookies = 4; + + // Create the cookies. + for (i = 0; i < kNumCookies; i++) { + CefCookie cookie; + + ss << "my_cookie" << i; + CefString(&cookie.name).FromASCII(ss.str().c_str()); + ss.str(""); + ss << "My Value " << i; + CefString(&cookie.value).FromASCII(ss.str().c_str()); + ss.str(""); + + cookies.push_back(cookie); + } + + // Set the cookies. + SetCookies(manager, kTestUrl, cookies, event); + cookies.clear(); + + // Get the cookies without deleting them. + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)kNumCookies, cookies.size()); + + CookieVector::const_iterator it = cookies.begin(); + for (i = 0; it != cookies.end(); ++it, ++i) { + const CefCookie& cookie = *it; + + ss << "my_cookie" << i; + EXPECT_EQ(CefString(&cookie.name), ss.str()); + ss.str(""); + ss << "My Value " << i; + EXPECT_EQ(CefString(&cookie.value), ss.str()); + ss.str(""); + } + + cookies.clear(); + + // Delete the 2nd cookie. + DeleteCookies(manager, kTestUrl, CefString("my_cookie1"), event); + + // Verify that the cookie has been deleted. + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)3, cookies.size()); + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie0"); + EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2"); + EXPECT_EQ(CefString(&cookies[2].name), "my_cookie3"); + + cookies.clear(); + + // Delete the rest of the cookies. + DeleteCookies(manager, kTestUrl, CefString(), event); + + // Verify that the cookies have been deleted. + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + + // Create the cookies. + for (i = 0; i < kNumCookies; i++) { + CefCookie cookie; + + ss << "my_cookie" << i; + CefString(&cookie.name).FromASCII(ss.str().c_str()); + ss.str(""); + ss << "My Value " << i; + CefString(&cookie.value).FromASCII(ss.str().c_str()); + ss.str(""); + + cookies.push_back(cookie); + } + + // Delete all of the cookies using the visitor. + VisitUrlCookies(manager, kTestUrl, false, cookies, true, event); + + cookies.clear(); + + // Verify that the cookies have been deleted. + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)0, cookies.size()); +} + +void TestAllCookies(CefRefPtr manager) { + base::WaitableEvent event(false, false); + CookieVector cookies; + + // Delete all system cookies just in case something is left over from a + // different test. + DeleteCookies(manager, CefString(), CefString(), event); + + // Verify that all system cookies have been deleted. + VisitAllCookies(manager, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + + // Create cookies with 2 separate hosts. + CefCookie cookie1; + const char* kUrl1 = "http://www.foo.com"; + CefString(&cookie1.name).FromASCII("my_cookie1"); + CefString(&cookie1.value).FromASCII("My Value 1"); + + cookies.push_back(cookie1); + SetCookies(manager, kUrl1, cookies, event); + cookies.clear(); + + CefCookie cookie2; + const char* kUrl2 = "http://www.bar.com"; + CefString(&cookie2.name).FromASCII("my_cookie2"); + CefString(&cookie2.value).FromASCII("My Value 2"); + + cookies.push_back(cookie2); + SetCookies(manager, kUrl2, cookies, event); + cookies.clear(); + + // Verify that all system cookies can be retrieved. + VisitAllCookies(manager, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)2, cookies.size()); + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); + EXPECT_EQ(CefString(&cookies[0].value), "My Value 1"); + EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com"); + EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2"); + EXPECT_EQ(CefString(&cookies[1].value), "My Value 2"); + EXPECT_EQ(CefString(&cookies[1].domain), "www.bar.com"); + cookies.clear(); + + // Verify that the cookies can be retrieved separately. + VisitUrlCookies(manager, kUrl1, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); + EXPECT_EQ(CefString(&cookies[0].value), "My Value 1"); + EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com"); + cookies.clear(); + + VisitUrlCookies(manager, kUrl2, false, cookies, false, event); + + EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie2"); + EXPECT_EQ(CefString(&cookies[0].value), "My Value 2"); + EXPECT_EQ(CefString(&cookies[0].domain), "www.bar.com"); + cookies.clear(); + + // Delete all of the system cookies. + DeleteAllCookies(manager, event); + + // Verify that all system cookies have been deleted. + VerifyNoCookies(manager, event, false); +} + +void TestChangeDirectory(CefRefPtr manager, + const CefString& original_dir) { + base::WaitableEvent event(false, false); + CefCookie cookie; + + base::ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + // Delete all of the system cookies. + DeleteAllCookies(manager, event); + + // Set the new temporary directory as the storage location. + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); + + // Verify that no cookies exist. + VerifyNoCookies(manager, event, true); + + // Create a domain cookie. + CreateCookie(manager, cookie, true, false, event); + + // Retrieve and verify the domain cookie. + GetCookie(manager, cookie, true, event, false); + + // Restore the original storage location. + EXPECT_TRUE(manager->SetStoragePath(original_dir, false)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); + + // Verify that no cookies exist. + VerifyNoCookies(manager, event, true); + + // Set the new temporary directory as the storage location. + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); + + // Retrieve and verify the domain cookie that was set previously. + GetCookie(manager, cookie, true, event, false); + + // Restore the original storage location. + EXPECT_TRUE(manager->SetStoragePath(original_dir, false)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); +} + +} // namespace + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString(), false); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieOnDisk) { + base::ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString(), false); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieOnDisk) { + base::ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString(), false); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesOnDisk) { + base::ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +TEST(CookieTest, AllCookiesGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, AllCookiesInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString(), false); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, AllCookiesOnDisk) { + base::ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, ChangeDirectoryGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + std::string cache_path; + CefTestSuite::GetCachePath(cache_path); + + TestChangeDirectory(manager, cache_path); +} + +TEST(CookieTest, ChangeDirectoryCreated) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString(), false); + EXPECT_TRUE(manager.get()); + + TestChangeDirectory(manager, CefString()); +} + + +namespace { + +class TestCompletionCallback : public CefCompletionCallback { + public: + explicit TestCompletionCallback(base::WaitableEvent* event) + : event_(event) {} + + virtual void OnComplete() OVERRIDE { + event_->Signal(); + } + + private: + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestCompletionCallback); +}; + +} // namespace + +TEST(CookieTest, SessionCookieNoPersist) { + base::ScopedTempDir temp_dir; + base::WaitableEvent event(false, false); + CefCookie cookie; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + EXPECT_TRUE(manager.get()); + + // Create a session cookie. + CreateCookie(manager, cookie, true, true, event); + + // Retrieve and verify the cookie. + GetCookie(manager, cookie, true, event, false); + + // Flush the cookie store to disk. + manager->FlushStore(new TestCompletionCallback(&event)); + event.Wait(); + + // Create a new manager to read the same cookie store. + manager = + CefCookieManager::CreateManager(temp_dir.path().value(), false); + + // Verify that the cookie doesn't exist. + VerifyNoCookies(manager, event, true); +} + +TEST(CookieTest, SessionCookieWillPersist) { + base::ScopedTempDir temp_dir; + base::WaitableEvent event(false, false); + CefCookie cookie; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value(), true); + EXPECT_TRUE(manager.get()); + + // Create a session cookie. + CreateCookie(manager, cookie, true, true, event); + + // Retrieve and verify the cookie. + GetCookie(manager, cookie, true, event, false); + + // Flush the cookie store to disk. + manager->FlushStore(new TestCompletionCallback(&event)); + event.Wait(); + + // Create a new manager to read the same cookie store. + manager = + CefCookieManager::CreateManager(temp_dir.path().value(), true); + + // Verify that the cookie exists. + GetCookie(manager, cookie, true, event, false); +} + + +namespace { + +const char* kCookieJSUrl1 = "http://tests/cookie1.html"; +const char* kCookieJSUrl2 = "http://tests/cookie2.html"; + +class CookieTestJSHandler : public TestHandler { + public: + class RequestContextHandler : public CefRequestContextHandler { + public: + explicit RequestContextHandler(CookieTestJSHandler* handler) + : handler_(handler) {} + + virtual CefRefPtr GetCookieManager() OVERRIDE { + EXPECT_TRUE(handler_); + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + + if (url_ == kCookieJSUrl1) { + // Return the first cookie manager. + handler_->got_cookie_manager1_.yes(); + return handler_->manager1_; + } else { + // Return the second cookie manager. + handler_->got_cookie_manager2_.yes(); + return handler_->manager2_; + } + } + + void SetURL(const std::string& url) { + url_ = url; + } + + void Detach() { + handler_ = NULL; + } + + private: + std::string url_; + CookieTestJSHandler* handler_; + + IMPLEMENT_REFCOUNTING(RequestContextHandler); + }; + + CookieTestJSHandler() {} + + virtual void RunTest() OVERRIDE { + // Create =new in-memory managers. + manager1_ = CefCookieManager::CreateManager(CefString(), false); + manager2_ = CefCookieManager::CreateManager(CefString(), false); + + std::string page = + "" + "" + "COOKIE TEST1"; + AddResource(kCookieJSUrl1, page, "text/html"); + + page = + "" + "" + "COOKIE TEST2"; + AddResource(kCookieJSUrl2, page, "text/html"); + + context_handler_ = new RequestContextHandler(this); + context_handler_->SetURL(kCookieJSUrl1); + + // Create the browser + CreateBrowser(kCookieJSUrl1, + CefRequestContext::CreateContext(context_handler_.get())); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url == kCookieJSUrl1) { + got_load_end1_.yes(); + VerifyCookie(manager1_, url, "name1", "value1", got_cookie1_); + + // Go to the next URL + context_handler_->SetURL(kCookieJSUrl2); + frame->LoadURL(kCookieJSUrl2); + } else { + got_load_end2_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie2_); + + DestroyTest(); + } + } + + virtual void DestroyTest() OVERRIDE { + context_handler_->Detach(); + context_handler_ = NULL; + + TestHandler::DestroyTest(); + } + + // Verify that the cookie was set successfully. + void VerifyCookie(CefRefPtr manager, + const std::string& url, + const std::string& name, + const std::string& value, + TrackCallback& callback) { + base::WaitableEvent event(false, false); + CookieVector cookies; + + // Get the cookie. + VisitUrlCookies(manager, url, false, cookies, false, event); + + if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + CefString(&cookies[0].value) == value) { + callback.yes(); + } + } + + CefRefPtr context_handler_; + + CefRefPtr manager1_; + CefRefPtr manager2_; + + TrackCallback got_cookie_manager1_; + TrackCallback got_cookie_manager2_; + TrackCallback got_load_end1_; + TrackCallback got_load_end2_; + TrackCallback got_cookie1_; + TrackCallback got_cookie2_; +}; + +} // namespace + +// Verify use of multiple cookie managers vis JS. +TEST(CookieTest, GetCookieManagerJS) { + CefRefPtr handler = new CookieTestJSHandler(); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_cookie_manager1_); + EXPECT_TRUE(handler->got_cookie_manager2_); + EXPECT_TRUE(handler->got_load_end1_); + EXPECT_TRUE(handler->got_load_end2_); + EXPECT_TRUE(handler->got_cookie1_); + EXPECT_TRUE(handler->got_cookie2_); +} + + +namespace { + +class CookieTestSchemeHandler : public TestHandler { + public: + class SchemeHandler : public CefResourceHandler { + public: + explicit SchemeHandler(CookieTestSchemeHandler* handler) + : handler_(handler), + offset_(0) {} + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) + OVERRIDE { + std::string url = request->GetURL(); + if (url == handler_->url1_) { + content_ = "COOKIE TEST1"; + cookie_ = "name1=value1"; + handler_->got_process_request1_.yes(); + } else if (url == handler_->url2_) { + content_ = "COOKIE TEST2"; + cookie_ = "name2=value2"; + handler_->got_process_request2_.yes(); + } else if (url == handler_->url3_) { + content_ = "COOKIE TEST3"; + handler_->got_process_request3_.yes(); + + // Verify that the cookie was passed in. + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + CefRequest::HeaderMap::iterator it = headerMap.find("Cookie"); + if (it != headerMap.end() && it->second == "name2=value2") + handler_->got_process_request_cookie_.yes(); + + } + callback->Continue(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = content_.size(); + + response->SetStatus(200); + response->SetMimeType("text/html"); + + if (!cookie_.empty()) { + CefResponse::HeaderMap headerMap; + response->GetHeaderMap(headerMap); + headerMap.insert(std::make_pair("Set-Cookie", cookie_)); + response->SetHeaderMap(headerMap); + } + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) + OVERRIDE { + bool has_data = false; + bytes_read = 0; + + size_t size = content_.size(); + if (offset_ < size) { + int transfer_size = + std::min(bytes_to_read, static_cast(size - offset_)); + memcpy(data_out, content_.c_str() + offset_, transfer_size); + offset_ += transfer_size; + + bytes_read = transfer_size; + has_data = true; + } + + return has_data; + } + + virtual void Cancel() OVERRIDE { + } + + private: + CookieTestSchemeHandler* handler_; + std::string content_; + size_t offset_; + std::string cookie_; + + IMPLEMENT_REFCOUNTING(SchemeHandler); + }; + + class SchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + explicit SchemeHandlerFactory(CookieTestSchemeHandler* handler) + : handler_(handler) {} + + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) OVERRIDE { + std::string url = request->GetURL(); + if (url == handler_->url3_) { + // Verify that the cookie was not passed in. + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + CefRequest::HeaderMap::iterator it = headerMap.find("Cookie"); + if (it != headerMap.end() && it->second == "name2=value2") + handler_->got_create_cookie_.yes(); + } + + return new SchemeHandler(handler_); + } + + private: + CookieTestSchemeHandler* handler_; + + IMPLEMENT_REFCOUNTING(SchemeHandlerFactory); + }; + + class RequestContextHandler : public CefRequestContextHandler { + public: + explicit RequestContextHandler(CookieTestSchemeHandler* handler) + : handler_(handler) {} + + virtual CefRefPtr GetCookieManager() OVERRIDE { + EXPECT_TRUE(handler_); + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + + if (url_ == handler_->url1_) { + // Return the first cookie manager. + handler_->got_cookie_manager1_.yes(); + return handler_->manager1_; + } else { + // Return the second cookie manager. + handler_->got_cookie_manager2_.yes(); + return handler_->manager2_; + } + } + + void SetURL(const std::string& url) { + url_ = url; + } + + void Detach() { + handler_ = NULL; + } + + private: + std::string url_; + CookieTestSchemeHandler* handler_; + + IMPLEMENT_REFCOUNTING(RequestContextHandler); + }; + + CookieTestSchemeHandler(const std::string& scheme) : scheme_(scheme) { + url1_ = scheme + "://cookie-tests/cookie1.html"; + url2_ = scheme + "://cookie-tests/cookie2.html"; + url3_ = scheme + "://cookie-tests/cookie3.html"; + } + + virtual void RunTest() OVERRIDE { + // Create new in-memory managers. + manager1_ = CefCookieManager::CreateManager(CefString(), false); + manager2_ = CefCookieManager::CreateManager(CefString(), false); + + if (scheme_ != "http") { + std::vector schemes; + schemes.push_back("http"); + schemes.push_back("https"); + schemes.push_back(scheme_); + + manager1_->SetSupportedSchemes(schemes); + manager2_->SetSupportedSchemes(schemes); + } + + // Register the scheme handler. + CefRegisterSchemeHandlerFactory(scheme_, "cookie-tests", + new SchemeHandlerFactory(this)); + + context_handler_ = new RequestContextHandler(this); + context_handler_->SetURL(url1_); + + // Create the browser + CreateBrowser(url1_, + CefRequestContext::CreateContext(context_handler_.get())); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url == url1_) { + got_load_end1_.yes(); + VerifyCookie(manager1_, url, "name1", "value1", got_cookie1_); + + // Go to the next URL + context_handler_->SetURL(url2_); + frame->LoadURL(url2_); + } else if (url == url2_) { + got_load_end2_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie2_); + + // Go to the next URL + context_handler_->SetURL(url3_); + frame->LoadURL(url3_); + } else { + got_load_end3_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie3_); + + // Unregister the scheme handler. + CefRegisterSchemeHandlerFactory(scheme_, "cookie-tests", NULL); + + DestroyTest(); + } + } + + virtual void DestroyTest() OVERRIDE { + context_handler_->Detach(); + context_handler_ = NULL; + + TestHandler::DestroyTest(); + } + + // Verify that the cookie was set successfully. + void VerifyCookie(CefRefPtr manager, + const std::string& url, + const std::string& name, + const std::string& value, + TrackCallback& callback) { + base::WaitableEvent event(false, false); + CookieVector cookies; + + // Get the cookie. + VisitUrlCookies(manager, url, false, cookies, false, event); + + if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + CefString(&cookies[0].value) == value) { + callback.yes(); + } + } + + std::string scheme_; + std::string url1_; + std::string url2_; + std::string url3_; + + CefRefPtr context_handler_; + + CefRefPtr manager1_; + CefRefPtr manager2_; + + TrackCallback got_process_request1_; + TrackCallback got_process_request2_; + TrackCallback got_process_request3_; + TrackCallback got_create_cookie_; + TrackCallback got_process_request_cookie_; + TrackCallback got_cookie_manager1_; + TrackCallback got_cookie_manager2_; + TrackCallback got_load_end1_; + TrackCallback got_load_end2_; + TrackCallback got_load_end3_; + TrackCallback got_cookie1_; + TrackCallback got_cookie2_; + TrackCallback got_cookie3_; +}; + +} // namespace + +// Verify use of multiple cookie managers via HTTP. +TEST(CookieTest, GetCookieManagerHttp) { + CefRefPtr handler = + new CookieTestSchemeHandler("http"); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_process_request1_); + EXPECT_TRUE(handler->got_process_request2_); + EXPECT_TRUE(handler->got_process_request3_); + EXPECT_FALSE(handler->got_create_cookie_); + EXPECT_TRUE(handler->got_process_request_cookie_); + EXPECT_TRUE(handler->got_cookie_manager1_); + EXPECT_TRUE(handler->got_cookie_manager2_); + EXPECT_TRUE(handler->got_load_end1_); + EXPECT_TRUE(handler->got_load_end2_); + EXPECT_TRUE(handler->got_load_end3_); + EXPECT_TRUE(handler->got_cookie1_); + EXPECT_TRUE(handler->got_cookie2_); + EXPECT_TRUE(handler->got_cookie3_); +} + +// Verify use of multiple cookie managers via a custom scheme. +TEST(CookieTest, GetCookieManagerCustom) { + CefRefPtr handler = + new CookieTestSchemeHandler("ccustom"); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_process_request1_); + EXPECT_TRUE(handler->got_process_request2_); + EXPECT_TRUE(handler->got_process_request3_); + EXPECT_FALSE(handler->got_create_cookie_); + EXPECT_TRUE(handler->got_process_request_cookie_); + EXPECT_TRUE(handler->got_cookie_manager1_); + EXPECT_TRUE(handler->got_cookie_manager2_); + EXPECT_TRUE(handler->got_load_end1_); + EXPECT_TRUE(handler->got_load_end2_); + EXPECT_TRUE(handler->got_load_end3_); + EXPECT_TRUE(handler->got_cookie1_); + EXPECT_TRUE(handler->got_cookie2_); + EXPECT_TRUE(handler->got_cookie3_); +} + +// Entry point for registering custom schemes. +// Called from client_app_delegates.cc. +void RegisterCookieCustomSchemes( + CefRefPtr registrar, + std::vector& cookiable_schemes) { + // Used by GetCookieManagerCustom test. + registrar->AddCustomScheme("ccustom", true, false, false); +} diff --git a/tests/unittests/dialog_unittest.cc b/tests/unittests/dialog_unittest.cc new file mode 100644 index 000000000..4a1c982f7 --- /dev/null +++ b/tests/unittests/dialog_unittest.cc @@ -0,0 +1,270 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/base/cef_bind.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_util.h" + +namespace { + +const char* kTestUrl = "http://tests/DialogTestHandler"; + +class DialogTestHandler : public TestHandler { + public: + struct TestConfig { + explicit TestConfig(FileDialogMode dialog_mode) + : mode(dialog_mode), + title("Test Title"), + default_file_name("Test File Name"), + callback_async(false), + callback_cancel(false) { + accept_types.push_back("text/*"); + accept_types.push_back(".js"); + accept_types.push_back(".css"); + } + + FileDialogMode mode; + CefString title; + CefString default_file_name; + std::vector accept_types; + + bool callback_async; // True if the callback should execute asynchronously. + bool callback_cancel; // True if the callback should cancel. + std::vector callback_paths; // Resulting paths if not cancelled. + }; + + class Callback : public CefRunFileDialogCallback { + public: + explicit Callback(DialogTestHandler* handler) + : handler_(handler) { + } + + virtual void OnFileDialogDismissed( + CefRefPtr browser_host, + const std::vector& file_paths) OVERRIDE { + handler_->got_onfiledialogdismissed_.yes(); + + std::string url = browser_host->GetBrowser()->GetMainFrame()->GetURL(); + EXPECT_STREQ(kTestUrl, url.c_str()); + + if (handler_->config_.callback_cancel) + EXPECT_TRUE(file_paths.empty()); + else + TestStringVectorEqual(handler_->config_.callback_paths, file_paths); + + handler_->DestroyTest(); + handler_ = NULL; + } + + private: + DialogTestHandler* handler_; + + IMPLEMENT_REFCOUNTING(Callback); + }; + + explicit DialogTestHandler(const TestConfig& config) + : config_(config) { + } + + virtual void RunTest() OVERRIDE { + AddResource(kTestUrl, "TEST", "text/html"); + + // Create the browser + CreateBrowser(kTestUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + browser->GetHost()->RunFileDialog(config_.mode, + config_.title, + config_.default_file_name, + config_.accept_types, + new Callback(this)); + } + + void ExecuteCallback(CefRefPtr callback) { + if (config_.callback_cancel) + callback->Cancel(); + else + callback->Continue(config_.callback_paths); + } + + // CefDialogHandler + virtual bool OnFileDialog( + CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_name, + const std::vector& accept_types, + CefRefPtr callback) OVERRIDE { + got_onfiledialog_.yes(); + + std::string url = browser->GetMainFrame()->GetURL(); + EXPECT_STREQ(kTestUrl, url.c_str()); + + EXPECT_EQ(config_.mode, mode); + EXPECT_STREQ(config_.title.ToString().c_str(), title.ToString().c_str()); + EXPECT_STREQ(config_.default_file_name.ToString().c_str(), + default_file_name.ToString().c_str()); + TestStringVectorEqual(config_.accept_types, accept_types); + + if (config_.callback_async) { + CefPostTask(TID_UI, + base::Bind(&DialogTestHandler::ExecuteCallback, this, callback)); + } else { + ExecuteCallback(callback); + } + + return true; + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_onfiledialog_); + EXPECT_TRUE(got_onfiledialogdismissed_); + + TestHandler::DestroyTest(); + } + + TestConfig config_; + + TrackCallback got_onfiledialog_; + TrackCallback got_onfiledialogdismissed_; +}; + +} // namespace + +// Test with all parameters empty. +TEST(DialogTest, FileEmptyParams) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN); + config.title.clear(); + config.default_file_name.clear(); + config.accept_types.clear(); + config.callback_async = false; + config.callback_cancel = false; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpen) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN); + config.callback_async = false; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenAsync) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN); + config.callback_async = true; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenAsyncCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenMultiple) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE); + config.callback_async = false; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + config.callback_paths.push_back("/path/to/file2.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenMultipleCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenMultipleAsync) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE); + config.callback_async = true; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + config.callback_paths.push_back("/path/to/file2.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileOpenMultipleAsyncCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_OPEN_MULTIPLE); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileSave) { + DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE); + config.callback_async = false; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileSaveCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileSaveAsync) { + DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE); + config.callback_async = true; + config.callback_cancel = false; + config.callback_paths.push_back("/path/to/file1.txt"); + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} + +TEST(DialogTest, FileSaveAsyncCancel) { + DialogTestHandler::TestConfig config(FILE_DIALOG_SAVE); + config.callback_async = false; + config.callback_cancel = true; + + CefRefPtr handler = new DialogTestHandler(config); + handler->ExecuteTest(); +} diff --git a/tests/unittests/display_unittest.cc b/tests/unittests/display_unittest.cc new file mode 100644 index 000000000..ffd17ab9c --- /dev/null +++ b/tests/unittests/display_unittest.cc @@ -0,0 +1,112 @@ +// 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 + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" + +namespace { + +// How it works: +// 1. Load kTitleUrl1 (title should be kTitleStr1) +// 2. Load kTitleUrl2 (title should be kTitleStr2) +// 3. History back to kTitleUrl1 (title should be kTitleStr1) +// 4. History forward to kTitleUrl2 (title should be kTitleStr2) +// 5. Set title via JavaScript (title should be kTitleStr3) + +const char kTitleUrl1[] = "http://tests-title/nav1.html"; +const char kTitleUrl2[] = "http://tests-title/nav2.html"; +const char kTitleStr1[] = "Title 1"; +const char kTitleStr2[] = "Title 2"; +const char kTitleStr3[] = "Title 3"; + +// Browser side. +class TitleTestHandler : public TestHandler { + public: + TitleTestHandler() + : step_(0) {} + + virtual void RunTest() OVERRIDE { + // Add the resources that we will navigate to/from. + AddResource(kTitleUrl1, + "" + std::string(kTitleStr1) + + "Nav1", "text/html"); + AddResource(kTitleUrl2, + "" + std::string(kTitleStr2) + + "Nav2" + + "" + + "", "text/html"); + + // Create the browser. + CreateBrowser(kTitleUrl1); + } + + virtual void OnTitleChange(CefRefPtr browser, + const CefString& title) OVERRIDE { + std::string title_str = title; + if (step_ == 0 || step_ == 2) { + EXPECT_STREQ(kTitleStr1, title_str.c_str()); + } else if (step_ == 1 || step_ == 3) { + EXPECT_STREQ(kTitleStr2, title_str.c_str()); + } else if (step_ == 4) { + // Ignore the unexpected notification of the page URL. + // Related bug: http://crbug.com/331351 + if (title_str == &kTitleUrl2[7]) + return; + + EXPECT_STREQ(kTitleStr3, title_str.c_str()); + } + + got_title_[step_].yes(); + + if (step_ == 4) + DestroyTest(); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + switch (step_++) { + case 0: + frame->LoadURL(kTitleUrl2); + break; + case 1: + browser->GoBack(); + break; + case 2: + browser->GoForward(); + break; + case 3: + frame->ExecuteJavaScript("setTitle()", kTitleUrl2, 0); + break; + default: + EXPECT_TRUE(false); // Not reached. + } + } + + private: + virtual void DestroyTest() OVERRIDE { + for (int i = 0; i < 5; ++i) + EXPECT_TRUE(got_title_[i]) << "step " << i; + + TestHandler::DestroyTest(); + } + + int step_; + + TrackCallback got_title_[5]; +}; + +} // namespace + +// Test title notifications. +TEST(DisplayTest, Title) { + CefRefPtr handler = new TitleTestHandler(); + handler->ExecuteTest(); +} diff --git a/tests/unittests/dom_unittest.cc b/tests/unittests/dom_unittest.cc new file mode 100644 index 000000000..8a76547c3 --- /dev/null +++ b/tests/unittests/dom_unittest.cc @@ -0,0 +1,335 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_dom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/cefclient/client_app.h" +#include "tests/unittests/test_handler.h" + +namespace { + +const char* kTestUrl = "http://tests/DOMTest.Test"; +const char* kTestMessage = "DOMTest.Message"; + +enum DOMTestType { + DOM_TEST_STRUCTURE, + DOM_TEST_MODIFY, +}; + +class TestDOMVisitor : public CefDOMVisitor { + public: + explicit TestDOMVisitor(CefRefPtr browser, DOMTestType test_type) + : browser_(browser), + test_type_(test_type) { + } + + void TestHeadNodeStructure(CefRefPtr headNode) { + EXPECT_TRUE(headNode.get()); + EXPECT_TRUE(headNode->IsElement()); + EXPECT_FALSE(headNode->IsText()); + EXPECT_EQ(headNode->GetName(), "HEAD"); + EXPECT_EQ(headNode->GetElementTagName(), "HEAD"); + + EXPECT_TRUE(headNode->HasChildren()); + EXPECT_FALSE(headNode->HasElementAttributes()); + + CefRefPtr titleNode = headNode->GetFirstChild(); + EXPECT_TRUE(titleNode.get()); + EXPECT_TRUE(titleNode->IsElement()); + EXPECT_FALSE(titleNode->IsText()); + EXPECT_EQ(titleNode->GetName(), "TITLE"); + EXPECT_EQ(titleNode->GetElementTagName(), "TITLE"); + EXPECT_TRUE(titleNode->GetParent()->IsSame(headNode)); + + EXPECT_FALSE(titleNode->GetNextSibling().get()); + EXPECT_FALSE(titleNode->GetPreviousSibling().get()); + EXPECT_TRUE(titleNode->HasChildren()); + EXPECT_FALSE(titleNode->HasElementAttributes()); + + CefRefPtr textNode = titleNode->GetFirstChild(); + EXPECT_TRUE(textNode.get()); + EXPECT_FALSE(textNode->IsElement()); + EXPECT_TRUE(textNode->IsText()); + EXPECT_EQ(textNode->GetValue(), "The Title"); + EXPECT_TRUE(textNode->GetParent()->IsSame(titleNode)); + + EXPECT_FALSE(textNode->GetNextSibling().get()); + EXPECT_FALSE(textNode->GetPreviousSibling().get()); + EXPECT_FALSE(textNode->HasChildren()); + } + + void TestBodyNodeStructure(CefRefPtr bodyNode) { + EXPECT_TRUE(bodyNode.get()); + EXPECT_TRUE(bodyNode->IsElement()); + EXPECT_FALSE(bodyNode->IsText()); + EXPECT_EQ(bodyNode->GetName(), "BODY"); + EXPECT_EQ(bodyNode->GetElementTagName(), "BODY"); + + EXPECT_TRUE(bodyNode->HasChildren()); + EXPECT_FALSE(bodyNode->HasElementAttributes()); + + CefRefPtr h1Node = bodyNode->GetFirstChild(); + EXPECT_TRUE(h1Node.get()); + EXPECT_TRUE(h1Node->IsElement()); + EXPECT_FALSE(h1Node->IsText()); + EXPECT_EQ(h1Node->GetName(), "H1"); + EXPECT_EQ(h1Node->GetElementTagName(), "H1"); + + EXPECT_FALSE(h1Node->GetNextSibling().get()); + EXPECT_FALSE(h1Node->GetPreviousSibling().get()); + EXPECT_TRUE(h1Node->HasChildren()); + EXPECT_FALSE(h1Node->HasElementAttributes()); + + CefRefPtr textNode = h1Node->GetFirstChild(); + EXPECT_TRUE(textNode.get()); + EXPECT_FALSE(textNode->IsElement()); + EXPECT_TRUE(textNode->IsText()); + EXPECT_EQ(textNode->GetValue(), "Hello From"); + + EXPECT_FALSE(textNode->GetPreviousSibling().get()); + EXPECT_FALSE(textNode->HasChildren()); + + CefRefPtr brNode = textNode->GetNextSibling(); + EXPECT_TRUE(brNode.get()); + EXPECT_TRUE(brNode->IsElement()); + EXPECT_FALSE(brNode->IsText()); + EXPECT_EQ(brNode->GetName(), "BR"); + EXPECT_EQ(brNode->GetElementTagName(), "BR"); + + EXPECT_FALSE(brNode->HasChildren()); + + EXPECT_TRUE(brNode->HasElementAttributes()); + EXPECT_TRUE(brNode->HasElementAttribute("class")); + EXPECT_EQ(brNode->GetElementAttribute("class"), "some_class"); + EXPECT_TRUE(brNode->HasElementAttribute("id")); + EXPECT_EQ(brNode->GetElementAttribute("id"), "some_id"); + EXPECT_FALSE(brNode->HasElementAttribute("no_existing")); + + CefDOMNode::AttributeMap map; + brNode->GetElementAttributes(map); + ASSERT_EQ(map.size(), (size_t)2); + EXPECT_EQ(map["class"], "some_class"); + EXPECT_EQ(map["id"], "some_id"); + + // Can also retrieve by ID. + brNode = bodyNode->GetDocument()->GetElementById("some_id"); + EXPECT_TRUE(brNode.get()); + EXPECT_TRUE(brNode->IsElement()); + EXPECT_FALSE(brNode->IsText()); + EXPECT_EQ(brNode->GetName(), "BR"); + EXPECT_EQ(brNode->GetElementTagName(), "BR"); + + textNode = brNode->GetNextSibling(); + EXPECT_TRUE(textNode.get()); + EXPECT_FALSE(textNode->IsElement()); + EXPECT_TRUE(textNode->IsText()); + EXPECT_EQ(textNode->GetValue(), "Main Frame"); + + EXPECT_FALSE(textNode->GetNextSibling().get()); + EXPECT_FALSE(textNode->HasChildren()); + } + + // Test document structure by iterating through the DOM tree. + void TestStructure(CefRefPtr document) { + EXPECT_EQ(document->GetTitle(), "The Title"); + EXPECT_EQ(document->GetBaseURL(), kTestUrl); + EXPECT_EQ(document->GetCompleteURL("foo.html"), "http://tests/foo.html"); + + // Navigate the complete document structure. + CefRefPtr docNode = document->GetDocument(); + EXPECT_TRUE(docNode.get()); + EXPECT_FALSE(docNode->IsElement()); + EXPECT_FALSE(docNode->IsText()); + + CefRefPtr htmlNode = docNode->GetFirstChild(); + EXPECT_TRUE(htmlNode.get()); + EXPECT_TRUE(htmlNode->IsElement()); + EXPECT_FALSE(htmlNode->IsText()); + EXPECT_EQ(htmlNode->GetName(), "HTML"); + EXPECT_EQ(htmlNode->GetElementTagName(), "HTML"); + + EXPECT_TRUE(htmlNode->HasChildren()); + EXPECT_FALSE(htmlNode->HasElementAttributes()); + + CefRefPtr headNode = htmlNode->GetFirstChild(); + TestHeadNodeStructure(headNode); + + CefRefPtr bodyNode = headNode->GetNextSibling(); + TestBodyNodeStructure(bodyNode); + + // Retrieve the head node directly. + headNode = document->GetHead(); + TestHeadNodeStructure(headNode); + + // Retrieve the body node directly. + bodyNode = document->GetBody(); + TestBodyNodeStructure(bodyNode); + } + + // Test document modification by changing the H1 tag. + void TestModify(CefRefPtr document) { + CefRefPtr bodyNode = document->GetBody(); + CefRefPtr h1Node = bodyNode->GetFirstChild(); + + ASSERT_EQ(h1Node->GetAsMarkup(), + "

Hello From
" + "Main Frame

"); + + CefRefPtr textNode = h1Node->GetFirstChild(); + ASSERT_EQ(textNode->GetValue(), "Hello From"); + ASSERT_TRUE(textNode->SetValue("A Different Message From")); + ASSERT_EQ(textNode->GetValue(), "A Different Message From"); + + CefRefPtr brNode = textNode->GetNextSibling(); + EXPECT_EQ(brNode->GetElementAttribute("class"), "some_class"); + EXPECT_TRUE(brNode->SetElementAttribute("class", "a_different_class")); + EXPECT_EQ(brNode->GetElementAttribute("class"), "a_different_class"); + + ASSERT_EQ(h1Node->GetAsMarkup(), + "

A Different Message From
Main Frame

"); + + ASSERT_FALSE(h1Node->SetValue("Something Different")); + } + + virtual void Visit(CefRefPtr document) OVERRIDE { + if (test_type_ == DOM_TEST_STRUCTURE) + TestStructure(document); + else if (test_type_ == DOM_TEST_MODIFY) + TestModify(document); + + DestroyTest(); + } + + protected: + // Return from the test. + void DestroyTest() { + // Check if the test has failed. + bool result = !TestFailed(); + + // Return the result to the browser process. + CefRefPtr return_msg = + CefProcessMessage::Create(kTestMessage); + EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result)); + EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg)); + } + + CefRefPtr browser_; + DOMTestType test_type_; + + IMPLEMENT_REFCOUNTING(TestDOMVisitor); +}; + +// Used in the render process. +class DOMRendererTest : public ClientApp::RenderDelegate { + public: + DOMRendererTest() { + } + + virtual bool OnProcessMessageReceived( + CefRefPtr app, + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + if (message->GetName() == kTestMessage) { + EXPECT_EQ(message->GetArgumentList()->GetSize(), (size_t)1); + int test_type = message->GetArgumentList()->GetInt(0); + + browser->GetMainFrame()->VisitDOM( + new TestDOMVisitor(browser, static_cast(test_type))); + return true; + } + return false; + } + + private: + IMPLEMENT_REFCOUNTING(DOMRendererTest); +}; + +// Used in the browser process. +class TestDOMHandler : public TestHandler { + public: + explicit TestDOMHandler(DOMTestType test) + : test_type_(test) { + } + + virtual void RunTest() OVERRIDE { + std::stringstream mainHtml; + mainHtml << + "" + "The Title" + "" + "

Hello From
" + "Main Frame

" + "" + ""; + + AddResource(kTestUrl, mainHtml.str(), "text/html"); + CreateBrowser(kTestUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + if (frame->IsMain()) { + // Start the test in the render process. + CefRefPtr message( + CefProcessMessage::Create(kTestMessage)); + message->GetArgumentList()->SetInt(0, test_type_); + EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, message)); + } + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + EXPECT_STREQ(message->GetName().ToString().c_str(), kTestMessage); + + got_message_.yes(); + + if (message->GetArgumentList()->GetBool(0)) + got_success_.yes(); + + // Test is complete. + DestroyTest(); + + return true; + } + + DOMTestType test_type_; + TrackCallback got_message_; + TrackCallback got_success_; +}; + +} // namespace + +// Test DOM structure reading. +TEST(DOMTest, Read) { + CefRefPtr handler = + new TestDOMHandler(DOM_TEST_STRUCTURE); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_message_); + EXPECT_TRUE(handler->got_success_); +} + +// Test DOM modifications. +TEST(DOMTest, Modify) { + CefRefPtr handler = + new TestDOMHandler(DOM_TEST_MODIFY); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_message_); + EXPECT_TRUE(handler->got_success_); +} + +// Entry point for creating DOM renderer test objects. +// Called from client_app_delegates.cc. +void CreateDOMRendererTests(ClientApp::RenderDelegateSet& delegates) { + delegates.insert(new DOMRendererTest); +} diff --git a/tests/unittests/download_unittest.cc b/tests/unittests/download_unittest.cc new file mode 100644 index 000000000..771b50d6a --- /dev/null +++ b/tests/unittests/download_unittest.cc @@ -0,0 +1,266 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/file_util.h" +#include "base/files/scoped_temp_dir.h" + +#include "include/cef_scheme.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" + +namespace { + +const char kTestDomain[] = "test-download"; +const char kTestEntryUrl[] = "http://test-download/test.html"; +const char kTestDownloadUrl[] = "http://test-download/download.txt"; +const char kTestFileName[] = "download_test.txt"; +const char kTestContentDisposition[] = + "attachment; filename=\"download_test.txt\""; +const char kTestMimeType[] = "text/plain"; +const char kTestContent[] = "Download test text"; + +class DownloadSchemeHandler : public CefResourceHandler { + public: + explicit DownloadSchemeHandler(TrackCallback* got_download_request) + : got_download_request_(got_download_request), + offset_(0) {} + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) + OVERRIDE { + std::string url = request->GetURL(); + if (url == kTestEntryUrl) { + content_ = "Download Test"; + mime_type_ = "text/html"; + } else if (url == kTestDownloadUrl) { + got_download_request_->yes(); + content_ = kTestContent; + mime_type_ = kTestMimeType; + content_disposition_ = kTestContentDisposition; + } else { + EXPECT_TRUE(false); // Not reached. + return false; + } + + callback->Continue(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = content_.size(); + + response->SetStatus(200); + response->SetMimeType(mime_type_); + + if (!content_disposition_.empty()) { + CefResponse::HeaderMap headerMap; + response->GetHeaderMap(headerMap); + headerMap.insert( + std::make_pair("Content-Disposition", content_disposition_)); + response->SetHeaderMap(headerMap); + } + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) + OVERRIDE { + bool has_data = false; + bytes_read = 0; + + size_t size = content_.size(); + if (offset_ < size) { + int transfer_size = + std::min(bytes_to_read, static_cast(size - offset_)); + memcpy(data_out, content_.c_str() + offset_, transfer_size); + offset_ += transfer_size; + + bytes_read = transfer_size; + has_data = true; + } + + return has_data; + } + + virtual void Cancel() OVERRIDE { + } + + private: + TrackCallback* got_download_request_; + std::string content_; + std::string mime_type_; + std::string content_disposition_; + size_t offset_; + + IMPLEMENT_REFCOUNTING(DownloadSchemeHandler); +}; + +class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + explicit DownloadSchemeHandlerFactory(TrackCallback* got_download_request) + : got_download_request_(got_download_request) {} + + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) OVERRIDE { + return new DownloadSchemeHandler(got_download_request_); + } + + private: + TrackCallback* got_download_request_; + + IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory); +}; + +class DownloadTestHandler : public TestHandler { + public: + DownloadTestHandler() {} + + virtual void RunTest() OVERRIDE { + CefRegisterSchemeHandlerFactory("http", kTestDomain, + new DownloadSchemeHandlerFactory(&got_download_request_)); + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); + test_path_ = temp_dir_.path().AppendASCII(kTestFileName); + + // Create the browser + CreateBrowser(kTestEntryUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + EXPECT_STREQ(kTestEntryUrl, frame->GetURL().ToString().c_str()); + + // Begin the download. + browser->GetHost()->StartDownload(kTestDownloadUrl); + } + + virtual void OnBeforeDownload( + CefRefPtr browser, + CefRefPtr download_item, + const CefString& suggested_name, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_UI)); + EXPECT_FALSE(got_on_before_download_); + + got_on_before_download_.yes(); + + EXPECT_TRUE(browser->IsSame(GetBrowser())); + EXPECT_STREQ(kTestFileName, suggested_name.ToString().c_str()); + EXPECT_TRUE(download_item.get()); + EXPECT_TRUE(callback.get()); + + download_id_ = download_item->GetId(); + EXPECT_LT(0U, download_id_); + + EXPECT_TRUE(download_item->IsValid()); + EXPECT_TRUE(download_item->IsInProgress()); + EXPECT_FALSE(download_item->IsComplete()); + EXPECT_FALSE(download_item->IsCanceled()); + EXPECT_EQ(static_cast(sizeof(kTestContent)-1), + download_item->GetTotalBytes()); + EXPECT_EQ(0UL, download_item->GetFullPath().length()); + EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str()); + EXPECT_EQ(0UL, download_item->GetSuggestedFileName().length()); + EXPECT_STREQ(kTestContentDisposition, + download_item->GetContentDisposition().ToString().c_str()); + EXPECT_STREQ(kTestMimeType, download_item->GetMimeType().ToString().c_str()); + + callback->Continue(test_path_.value(), false); + } + + virtual void OnDownloadUpdated( + CefRefPtr browser, + CefRefPtr download_item, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_UI)); + + got_on_download_updated_.yes(); + + EXPECT_TRUE(browser->IsSame(GetBrowser())); + EXPECT_TRUE(download_item.get()); + EXPECT_TRUE(callback.get()); + + if (got_on_before_download_) + EXPECT_EQ(download_id_, download_item->GetId()); + + EXPECT_LE(0LL, download_item->GetCurrentSpeed()); + EXPECT_LE(0, download_item->GetPercentComplete()); + + EXPECT_TRUE(download_item->IsValid()); + EXPECT_FALSE(download_item->IsCanceled()); + EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str()); + EXPECT_STREQ(kTestContentDisposition, + download_item->GetContentDisposition().ToString().c_str()); + EXPECT_STREQ(kTestMimeType, + download_item->GetMimeType().ToString().c_str()); + + std::string full_path = download_item->GetFullPath(); + if (!full_path.empty()) { + got_full_path_.yes(); + EXPECT_STREQ(CefString(test_path_.value()).ToString().c_str(), + full_path.c_str()); + } + + if (download_item->IsComplete()) { + EXPECT_FALSE(download_item->IsInProgress()); + EXPECT_EQ(100, download_item->GetPercentComplete()); + EXPECT_EQ(static_cast(sizeof(kTestContent)-1), + download_item->GetReceivedBytes()); + EXPECT_EQ(static_cast(sizeof(kTestContent)-1), + download_item->GetTotalBytes()); + + DestroyTest(); + } else { + EXPECT_TRUE(download_item->IsInProgress()); + EXPECT_LE(0LL, download_item->GetReceivedBytes()); + } + } + + virtual void DestroyTest() OVERRIDE { + CefRegisterSchemeHandlerFactory("http", kTestDomain, NULL); + + EXPECT_TRUE(got_download_request_); + EXPECT_TRUE(got_on_before_download_); + EXPECT_TRUE(got_on_download_updated_); + EXPECT_TRUE(got_full_path_); + + // Verify the file contents. + std::string contents; + EXPECT_TRUE(base::ReadFileToString(test_path_, &contents)); + EXPECT_STREQ(kTestContent, contents.c_str()); + + EXPECT_TRUE(temp_dir_.Delete()); + + TestHandler::DestroyTest(); + } + + private: + base::ScopedTempDir temp_dir_; + base::FilePath test_path_; + uint32 download_id_; + + TrackCallback got_download_request_; + TrackCallback got_on_before_download_; + TrackCallback got_on_download_updated_; + TrackCallback got_full_path_; +}; + +} // namespace + +// Verify that downloads work. +TEST(DownloadTest, Download) { + CefRefPtr handler = new DownloadTestHandler(); + handler->ExecuteTest(); +} diff --git a/tests/unittests/geolocation_unittest.cc b/tests/unittests/geolocation_unittest.cc new file mode 100644 index 000000000..59fedee08 --- /dev/null +++ b/tests/unittests/geolocation_unittest.cc @@ -0,0 +1,210 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/synchronization/waitable_event.h" + +#include "include/base/cef_bind.h" +#include "include/cef_geolocation.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_util.h" + +namespace { + +const char* kTestOrigin = "http://tests/"; +const char* kTestUrl = "http://tests/GeolocationTestHandler"; +const char* kTestAllowUrl = "http://tests/GeolocationTestHandler.Allow"; +const char* kTestDenyUrl = "http://tests/GeolocationTestHandler.Deny"; +const char* kTestCancelUrl = "http://tests/GeolocationTestHandler.Cancel"; + +enum TestMode { + TEST_ALLOW, + TEST_DENY, + TEST_CANCEL, +}; + +class GeolocationTestHandler : public TestHandler { + public: + GeolocationTestHandler(const TestMode& mode, bool async) + : mode_(mode), + async_(async), + request_id_(-1) { + } + + virtual void RunTest() OVERRIDE { + std::string html = + "TEST START"; + AddResource(kTestUrl, html, "text/html"); + + std::string end_html = "TEST END"; + AddResource(kTestAllowUrl, end_html, "text/html"); + AddResource(kTestDenyUrl, end_html, "text/html"); + AddResource(kTestCancelUrl, end_html, "text/html"); + + // Create the browser + CreateBrowser(kTestUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url != kTestUrl) { + if (url == kTestAllowUrl) + got_allow_.yes(); + else if (url == kTestDenyUrl) + got_deny_.yes(); + else if (url == kTestCancelUrl) + got_cancel_.yes(); + + DestroyTest(); + } + } + + void ExecuteCallback(CefRefPtr callback) { + if (mode_ == TEST_ALLOW) + callback->Continue(true); + else if (mode_ == TEST_DENY) + callback->Continue(false); + } + + virtual bool OnRequestGeolocationPermission( + CefRefPtr browser, + const CefString& requesting_url, + int request_id, + CefRefPtr callback) OVERRIDE { + got_requestgeolocationpermission_.yes(); + + EXPECT_TRUE(CefCurrentlyOn(TID_UI)); + + EXPECT_STREQ(kTestOrigin, requesting_url.ToString().c_str()); + request_id_ = request_id; + + if (!async_) { + ExecuteCallback(callback); + } else { + CefPostTask(TID_UI, + base::Bind(&GeolocationTestHandler::ExecuteCallback, this, callback)); + } + + return true; + } + + virtual void OnCancelGeolocationPermission( + CefRefPtr browser, + const CefString& requesting_url, + int request_id) OVERRIDE { + got_cancelgeolocationpermission_.yes(); + + EXPECT_TRUE(CefCurrentlyOn(TID_UI)); + + EXPECT_STREQ(kTestOrigin, requesting_url.ToString().c_str()); + EXPECT_EQ(request_id, request_id_); + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_requestgeolocationpermission_); + if (mode_ == TEST_CANCEL) + EXPECT_TRUE(got_cancelgeolocationpermission_); + else + EXPECT_FALSE(got_cancelgeolocationpermission_); + + TestHandler::DestroyTest(); + } + + TestMode mode_; + bool async_; + + int request_id_; + + TrackCallback got_requestgeolocationpermission_; + TrackCallback got_cancelgeolocationpermission_; + TrackCallback got_allow_; + TrackCallback got_cancel_; + TrackCallback got_deny_; +}; + +} // namespace + +TEST(GeolocationTest, HandlerAllow) { + CefRefPtr handler = + new GeolocationTestHandler(TEST_ALLOW, false); + handler->ExecuteTest(); + EXPECT_TRUE(handler->got_allow_); +} + +TEST(GeolocationTest, HandlerAllowAsync) { + CefRefPtr handler = + new GeolocationTestHandler(TEST_ALLOW, true); + handler->ExecuteTest(); + EXPECT_TRUE(handler->got_allow_); +} + +TEST(GeolocationTest, HandlerDeny) { + CefRefPtr handler = + new GeolocationTestHandler(TEST_DENY, false); + handler->ExecuteTest(); + EXPECT_TRUE(handler->got_deny_); +} + +TEST(GeolocationTest, HandlerDenyAsync) { + CefRefPtr handler = + new GeolocationTestHandler(TEST_DENY, true); + handler->ExecuteTest(); + EXPECT_TRUE(handler->got_deny_); +} + +TEST(GeolocationTest, HandlerCancel) { + CefRefPtr handler = + new GeolocationTestHandler(TEST_CANCEL, false); + handler->ExecuteTest(); + EXPECT_TRUE(handler->got_cancel_); +} + + +namespace { + +class TestGetGeolocationCallback : public CefGetGeolocationCallback { + public: + explicit TestGetGeolocationCallback(base::WaitableEvent* event) + : event_(event) { + } + + virtual void OnLocationUpdate(const CefGeoposition& position) OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_UI)); + EXPECT_EQ(position.error_code, GEOPOSITON_ERROR_NONE); + EXPECT_NE(position.latitude, 0.0); + EXPECT_NE(position.longitude, 0.0); + EXPECT_NE(position.accuracy, 0.0); + EXPECT_NE(position.timestamp.year, 0); + event_->Signal(); + } + +private: + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestGetGeolocationCallback); +}; + +} // namespace + +TEST(GeolocationTest, GetGeolocation) { + base::WaitableEvent event(false, false); + CefGetGeolocation(new TestGetGeolocationCallback(&event)); + event.Wait(); +} diff --git a/tests/unittests/jsdialog_unittest.cc b/tests/unittests/jsdialog_unittest.cc new file mode 100644 index 000000000..b0a0389e7 --- /dev/null +++ b/tests/unittests/jsdialog_unittest.cc @@ -0,0 +1,417 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/base/cef_bind.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" + +namespace { + +const char* kStartUrl = "http://tests/JSDialogTestHandler.Start"; +const char* kEndUrl = "http://tests/JSDialogTestHandler.End?r="; + +class JSDialogTestHandler : public TestHandler { + public: + enum TestType { + TYPE_ALERT, + TYPE_CONFIRM, + TYPE_PROMPT, + TYPE_ONBEFOREUNLOAD, + }; + enum TestMode { + MODE_SUPPRESS, + MODE_RUN_IMMEDIATE, + MODE_RUN_DELAYED, + }; + + JSDialogTestHandler(TestType type, + TestMode mode, + bool success, + const std::string& user_input, + const std::string& result) + : type_(type), + mode_(mode), + success_(success), + user_input_(user_input), + result_(result) { + } + + virtual void RunTest() OVERRIDE { + std::string content = "START"; + + AddResource(kStartUrl, content, "text/html"); + AddResource(kEndUrl, "END", "text/html"); + + // Create the browser + CreateBrowser(kStartUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + if (!frame->IsMain()) + return; + + std::string url = frame->GetURL(); + if (url.find(kEndUrl) == 0) { + got_onloadend_.yes(); + + std::string result = url.substr(strlen(kEndUrl)); + EXPECT_STREQ(result_.c_str(), result.c_str()); + + DestroyTest(); + } else if (type_ == TYPE_ONBEFOREUNLOAD) { + // Trigger the onunload handler. + frame->LoadURL(kEndUrl); + } + } + + virtual void Continue(CefRefPtr callback) { + callback->Continue(success_, user_input_); + } + + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + const CefString& accept_lang, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) OVERRIDE { + got_onjsdialog_.yes(); + + EXPECT_STREQ("http://tests/", origin_url.ToString().c_str()); + EXPECT_TRUE(accept_lang.empty()); + + if (type_ == TYPE_ALERT) { + EXPECT_EQ(JSDIALOGTYPE_ALERT, dialog_type); + EXPECT_STREQ("My alert message", message_text.ToString().c_str()); + EXPECT_TRUE(default_prompt_text.empty()); + } else if (type_ == TYPE_CONFIRM) { + EXPECT_EQ(JSDIALOGTYPE_CONFIRM, dialog_type); + EXPECT_STREQ("My confirm message", message_text.ToString().c_str()); + EXPECT_TRUE(default_prompt_text.empty()); + } else if (type_ == TYPE_PROMPT) { + EXPECT_EQ(JSDIALOGTYPE_PROMPT, dialog_type); + EXPECT_STREQ("My prompt message", message_text.ToString().c_str()); + EXPECT_STREQ("my default", default_prompt_text.ToString().c_str()); + } + + EXPECT_FALSE(suppress_message); + + if (mode_ == MODE_SUPPRESS) { + // Suppress the dialog. + suppress_message = true; + return false; + } else if (mode_ == MODE_RUN_IMMEDIATE) { + // Continue immediately. + callback->Continue(success_, user_input_); + } else if (mode_ == MODE_RUN_DELAYED) { + // Continue asynchronously. + CefPostTask(TID_UI, + base::Bind(&JSDialogTestHandler::Continue, this, callback)); + } + + return true; + } + + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) + OVERRIDE { + got_onbeforeunloaddialog_.yes(); + + if (type_ == TYPE_ONBEFOREUNLOAD) { + EXPECT_STREQ("My unload message", message_text.ToString().c_str()); + EXPECT_FALSE(is_reload); + } + + if (mode_ == MODE_RUN_IMMEDIATE) { + // Continue immediately. + callback->Continue(success_, user_input_); + } else if (mode_ == MODE_RUN_DELAYED) { + // Continue asynchronously. + CefPostTask(TID_UI, + base::Bind(&JSDialogTestHandler::Continue, this, callback)); + } + + return true; + } + + virtual void OnResetDialogState(CefRefPtr browser) OVERRIDE { + got_onresetdialogstate_.yes(); + } + + TestType type_; + TestMode mode_; + bool success_; + std::string user_input_; + std::string result_; + + TrackCallback got_onjsdialog_; + TrackCallback got_onbeforeunloaddialog_; + TrackCallback got_onresetdialogstate_; + TrackCallback got_onloadend_; +}; + +} // namespace + +// Alert dialog with suppression. +TEST(JSDialogTest, AlertSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Alert dialog with immediate callback. +TEST(JSDialogTest, AlertRunImmediate) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Alert dialog with delayed callback. +TEST(JSDialogTest, AlertRunDelayed) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog with suppression. +TEST(JSDialogTest, ConfirmSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run immediately return OK. +TEST(JSDialogTest, ConfirmRunImmediateOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + "ok"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run immediately return Cancel. +TEST(JSDialogTest, ConfirmRunImmediateCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + false, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run delayed return OK. +TEST(JSDialogTest, ConfirmRunDelayedOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + "ok"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run delayed return Cancel. +TEST(JSDialogTest, ConfirmRunDelayedCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_DELAYED, + false, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog with suppression. +TEST(JSDialogTest, PromptSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run immediately return OK. +TEST(JSDialogTest, PromptRunImmediateOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "some_value", // user_input + "some_value"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run immediately return Cancel. +TEST(JSDialogTest, PromptRunImmediateCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + false, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run delayed return OK. +TEST(JSDialogTest, PromptRunDelayedOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "some_value", // user_input + "some_value"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run delayed return Cancel. +TEST(JSDialogTest, PromptRunDelayedCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_DELAYED, + false, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// OnBeforeUnload dialog with immediate callback. +TEST(JSDialogTest, OnBeforeUnloadRunImmediate) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_FALSE(handler->got_onjsdialog_); + EXPECT_TRUE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// OnBeforeUnload dialog with delayed callback. +TEST(JSDialogTest, OnBeforeUnloadRunDelayed) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_FALSE(handler->got_onjsdialog_); + EXPECT_TRUE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} diff --git a/tests/unittests/life_span_unittest.cc b/tests/unittests/life_span_unittest.cc new file mode 100644 index 000000000..0f79b074f --- /dev/null +++ b/tests/unittests/life_span_unittest.cc @@ -0,0 +1,310 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/base/cef_bind.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/routing_test_handler.h" + +namespace { + +const char kLifeSpanUrl[] = "http://tests-life-span/test.html"; +const char kUnloadDialogText[] = "Are you sure?"; +const char kUnloadMsg[] = "LifeSpanTestHandler.Unload"; + +// Browser side. +class LifeSpanTestHandler : public RoutingTestHandler { + public: + struct Settings { + Settings() + : force_close(false), + add_onunload_handler(false), + allow_do_close(true), + accept_before_unload_dialog(true) {} + + bool force_close; + bool add_onunload_handler; + bool allow_do_close; + bool accept_before_unload_dialog; + }; + + explicit LifeSpanTestHandler(const Settings& settings) + : settings_(settings), + executing_delay_close_(false) {} + + virtual void RunTest() OVERRIDE { + // Add the resources that we will navigate to/from. + std::string page = "Page"; + AddResource(kLifeSpanUrl, page, "text/html"); + + // Create the browser. + CreateBrowser(kLifeSpanUrl); + } + + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE { + got_after_created_.yes(); + RoutingTestHandler::OnAfterCreated(browser); + } + + virtual bool DoClose(CefRefPtr browser) OVERRIDE { + if (executing_delay_close_) + return false; + + EXPECT_TRUE(browser->IsSame(GetBrowser())); + + got_do_close_.yes(); + + if (!settings_.allow_do_close) { + // The close will be canceled. + ScheduleDelayClose(); + } + + return !settings_.allow_do_close; + } + + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE { + if (!executing_delay_close_) { + got_before_close_.yes(); + EXPECT_TRUE(browser->IsSame(GetBrowser())); + } + + RoutingTestHandler::OnBeforeClose(browser); + } + + virtual bool OnBeforeUnloadDialog( + CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) OVERRIDE { + if (executing_delay_close_) { + callback->Continue(true, CefString()); + return true; + } + + EXPECT_TRUE(browser->IsSame(GetBrowser())); + EXPECT_STREQ(kUnloadDialogText, message_text.ToString().c_str()); + EXPECT_FALSE(is_reload); + EXPECT_TRUE(callback.get()); + + if (!settings_.accept_before_unload_dialog) { + // The close will be canceled. + ScheduleDelayClose(); + } + + got_before_unload_dialog_.yes(); + callback->Continue(settings_.accept_before_unload_dialog, CefString()); + return true; + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + got_load_end_.yes(); + EXPECT_TRUE(browser->IsSame(GetBrowser())); + + // Attempt to close the browser. + browser->GetHost()->CloseBrowser(settings_.force_close); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + if (request.ToString() == kUnloadMsg) { + if (!executing_delay_close_) + got_unload_message_.yes(); + } + callback->Success(""); + return true; + } + + TrackCallback got_after_created_; + TrackCallback got_do_close_; + TrackCallback got_before_close_; + TrackCallback got_before_unload_dialog_; + TrackCallback got_unload_message_; + TrackCallback got_load_end_; + TrackCallback got_delay_close_; + + private: + // Wait a bit to make sure no additional events are received and then close + // the window. + void ScheduleDelayClose() { + CefPostDelayedTask(TID_UI, + base::Bind(&LifeSpanTestHandler::DelayClose, this), 100); + } + + void DelayClose() { + got_delay_close_.yes(); + executing_delay_close_ = true; + DestroyTest(); + } + + Settings settings_; + + // Forces the window to close (bypasses test conditions). + bool executing_delay_close_; +}; + +} // namespace + +TEST(LifeSpanTest, DoCloseAllow) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_TRUE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_FALSE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseAllowForce) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = true; + settings.force_close = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_TRUE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_FALSE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseDisallow) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = false; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_FALSE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_TRUE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseDisallowForce) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = false; + settings.force_close = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_FALSE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_TRUE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseDisallowWithOnUnloadAllow) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = false; + settings.add_onunload_handler = true; + settings.accept_before_unload_dialog = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_FALSE(handler->got_before_close_); + EXPECT_TRUE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_TRUE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseAllowWithOnUnloadForce) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = true; + settings.add_onunload_handler = true; + settings.force_close = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_TRUE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_FALSE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, DoCloseDisallowWithOnUnloadForce) { + LifeSpanTestHandler::Settings settings; + settings.allow_do_close = false; + settings.add_onunload_handler = true; + settings.force_close = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_FALSE(handler->got_before_close_); + EXPECT_FALSE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_TRUE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, OnUnloadAllow) { + LifeSpanTestHandler::Settings settings; + settings.add_onunload_handler = true; + settings.accept_before_unload_dialog = true; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_TRUE(handler->got_do_close_); + EXPECT_TRUE(handler->got_before_close_); + EXPECT_TRUE(handler->got_before_unload_dialog_); + EXPECT_TRUE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_FALSE(handler->got_delay_close_); +} + +TEST(LifeSpanTest, OnUnloadDisallow) { + LifeSpanTestHandler::Settings settings; + settings.add_onunload_handler = true; + settings.accept_before_unload_dialog = false; + CefRefPtr handler = new LifeSpanTestHandler(settings); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_after_created_); + EXPECT_FALSE(handler->got_do_close_); + EXPECT_FALSE(handler->got_before_close_); + EXPECT_TRUE(handler->got_before_unload_dialog_); + EXPECT_FALSE(handler->got_unload_message_); + EXPECT_TRUE(handler->got_load_end_); + EXPECT_TRUE(handler->got_delay_close_); +} diff --git a/tests/unittests/mac/English.lproj/InfoPlist.strings b/tests/unittests/mac/English.lproj/InfoPlist.strings new file mode 100644 index 000000000..fe2abe11b --- /dev/null +++ b/tests/unittests/mac/English.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "© Chromium Embedded Framework Authors, 2010"; diff --git a/tests/unittests/mac/English.lproj/MainMenu.xib b/tests/unittests/mac/English.lproj/MainMenu.xib new file mode 100644 index 000000000..e4f7c1fc3 --- /dev/null +++ b/tests/unittests/mac/English.lproj/MainMenu.xib @@ -0,0 +1,2880 @@ + + + + 1050 + 10F569 + 820 + 1038.29 + 461.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 820 + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + cefclient + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + TestShell + + YES + + + About cefclient + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide cefclient + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit cefclient + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + File + + YES + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + Open Recent + + YES + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save + s + 1048576 + 2147483647 + + + + + + Save As… + S + 1179648 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + Edit + + YES + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + Find + + YES + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + Spelling and Grammar + + YES + + + Show Spelling… + : + 1048576 + 2147483647 + + + + + + Check Spelling + ; + 1048576 + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + Substitutions + + YES + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + Speech + + YES + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 1048576 + 2147483647 + + + submenuAction: + + Format + + YES + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Show Colors + C + 1179648 + 2147483647 + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + View + + YES + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + Window + + YES + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + cefclient Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + YES + + + + + YES + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + showHelp: + + + + 360 + + + + orderFrontColorPanel: + + + + 361 + + + + saveDocument: + + + + 362 + + + + saveDocumentAs: + + + + 363 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + + + + + + MainMenu + + + 19 + + + YES + + + + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 217 + + + YES + + + + + + 83 + + + YES + + + + + + 81 + + + YES + + + + + + + + + + + + + + + + 75 + + + 3 + + + 80 + + + 8 + + + 78 + + + 6 + + + 72 + + + + + 82 + + + 9 + + + 124 + + + YES + + + + + + 77 + + + 5 + + + 73 + + + 1 + + + 79 + + + 7 + + + 112 + + + 10 + + + 74 + + + 2 + + + 125 + + + YES + + + + + + 126 + + + + + 205 + + + YES + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + YES + + + + + + 216 + + + YES + + + + + + 200 + + + YES + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + YES + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + YES + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + YES + + + + + + 296 + + + YES + + + + + + + 297 + + + + + 298 + + + + + 299 + + + YES + + + + + + 300 + + + YES + + + + + + + 344 + + + + + 345 + + + + + 211 + + + YES + + + + + + 212 + + + YES + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + YES + + + + + + 349 + + + YES + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 389 + + + + + + + YES + + YES + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 112.IBPluginDependency + 112.ImportedFromIB2 + 124.IBPluginDependency + 124.ImportedFromIB2 + 125.IBPluginDependency + 125.ImportedFromIB2 + 125.editorWindowContentRectSynchronizationRect + 126.IBPluginDependency + 126.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 19.IBPluginDependency + 19.ImportedFromIB2 + 195.IBPluginDependency + 195.ImportedFromIB2 + 196.IBPluginDependency + 196.ImportedFromIB2 + 197.IBPluginDependency + 197.ImportedFromIB2 + 198.IBPluginDependency + 198.ImportedFromIB2 + 199.IBPluginDependency + 199.ImportedFromIB2 + 200.IBEditorWindowLastContentRect + 200.IBPluginDependency + 200.ImportedFromIB2 + 200.editorWindowContentRectSynchronizationRect + 201.IBPluginDependency + 201.ImportedFromIB2 + 202.IBPluginDependency + 202.ImportedFromIB2 + 203.IBPluginDependency + 203.ImportedFromIB2 + 204.IBPluginDependency + 204.ImportedFromIB2 + 205.IBEditorWindowLastContentRect + 205.IBPluginDependency + 205.ImportedFromIB2 + 205.editorWindowContentRectSynchronizationRect + 206.IBPluginDependency + 206.ImportedFromIB2 + 207.IBPluginDependency + 207.ImportedFromIB2 + 208.IBPluginDependency + 208.ImportedFromIB2 + 209.IBPluginDependency + 209.ImportedFromIB2 + 210.IBPluginDependency + 210.ImportedFromIB2 + 211.IBPluginDependency + 211.ImportedFromIB2 + 212.IBEditorWindowLastContentRect + 212.IBPluginDependency + 212.ImportedFromIB2 + 212.editorWindowContentRectSynchronizationRect + 213.IBPluginDependency + 213.ImportedFromIB2 + 214.IBPluginDependency + 214.ImportedFromIB2 + 215.IBPluginDependency + 215.ImportedFromIB2 + 216.IBPluginDependency + 216.ImportedFromIB2 + 217.IBPluginDependency + 217.ImportedFromIB2 + 218.IBPluginDependency + 218.ImportedFromIB2 + 219.IBPluginDependency + 219.ImportedFromIB2 + 220.IBEditorWindowLastContentRect + 220.IBPluginDependency + 220.ImportedFromIB2 + 220.editorWindowContentRectSynchronizationRect + 221.IBPluginDependency + 221.ImportedFromIB2 + 23.IBPluginDependency + 23.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 239.IBPluginDependency + 239.ImportedFromIB2 + 24.IBEditorWindowLastContentRect + 24.IBPluginDependency + 24.ImportedFromIB2 + 24.editorWindowContentRectSynchronizationRect + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 295.IBPluginDependency + 296.IBEditorWindowLastContentRect + 296.IBPluginDependency + 296.editorWindowContentRectSynchronizationRect + 297.IBPluginDependency + 298.IBPluginDependency + 299.IBPluginDependency + 300.IBEditorWindowLastContentRect + 300.IBPluginDependency + 300.editorWindowContentRectSynchronizationRect + 344.IBPluginDependency + 345.IBPluginDependency + 346.IBPluginDependency + 346.ImportedFromIB2 + 348.IBPluginDependency + 348.ImportedFromIB2 + 349.IBEditorWindowLastContentRect + 349.IBPluginDependency + 349.ImportedFromIB2 + 349.editorWindowContentRectSynchronizationRect + 350.IBPluginDependency + 350.ImportedFromIB2 + 351.IBPluginDependency + 351.ImportedFromIB2 + 354.IBPluginDependency + 354.ImportedFromIB2 + 389.IBPluginDependency + 5.IBPluginDependency + 5.ImportedFromIB2 + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + 72.IBPluginDependency + 72.ImportedFromIB2 + 73.IBPluginDependency + 73.ImportedFromIB2 + 74.IBPluginDependency + 74.ImportedFromIB2 + 75.IBPluginDependency + 75.ImportedFromIB2 + 77.IBPluginDependency + 77.ImportedFromIB2 + 78.IBPluginDependency + 78.ImportedFromIB2 + 79.IBPluginDependency + 79.ImportedFromIB2 + 80.IBPluginDependency + 80.ImportedFromIB2 + 81.IBEditorWindowLastContentRect + 81.IBPluginDependency + 81.ImportedFromIB2 + 81.editorWindowContentRectSynchronizationRect + 82.IBPluginDependency + 82.ImportedFromIB2 + 83.IBPluginDependency + 83.ImportedFromIB2 + 92.IBPluginDependency + 92.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{906, 713}, {164, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{375, 955}, {171, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{522, 812}, {146, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 6}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {272, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {275, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{675, 493}, {240, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{144, 735}, {243, 243}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {164, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {167, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {238, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {241, 103}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{835, 663}, {194, 73}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{304, 905}, {197, 73}} + {{541, 736}, {426, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{6, 836}, {430, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{785, 693}, {231, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{254, 935}, {234, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{719, 693}, {173, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + {{188, 935}, {176, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{915, 473}, {212, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{608, 612}, {215, 63}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{553, 553}, {193, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{18, 653}, {200, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{633, 533}, {196, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{102, 775}, {199, 203}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + + YES + + + + + YES + + + YES + + + + 439 + + + + YES + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSController + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSController.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSDocumentController + NSObject + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + id + id + id + id + + + + YES + + YES + clearRecentDocuments: + newDocument: + openDocument: + saveAllDocuments: + + + YES + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAlert.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAnimation.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBox.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSComboBoxCell.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDatePickerCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSImage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSRuleEditor.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSound.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechRecognizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSpeechSynthesizer.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSplitView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTabView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextStorage.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenField.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTokenFieldCell.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbar.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSMetadata.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSSpellServer.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + Print.framework/Headers/PDEPluginInterface.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CAAnimation.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CALayer.h + + + + NSObject + + IBFrameworkSource + QuartzCore.framework/Headers/CIImageProvider.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + + + NSText + NSView + + + + NSUserDefaultsController + NSController + + IBFrameworkSource + AppKit.framework/Headers/NSUserDefaultsController.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + + + NSWindow + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../../../../cef.xcodeproj + 3 + + YES + + YES + NSMenuCheckmark + NSMenuMixedState + + + YES + {9, 8} + {7, 2} + + + + diff --git a/tests/unittests/mac/Info.plist b/tests/unittests/mac/Info.plist new file mode 100644 index 000000000..3d5f27c20 --- /dev/null +++ b/tests/unittests/mac/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + unittests.icns + CFBundleIdentifier + org.cef.unittests + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/tests/unittests/mac/unittests.icns b/tests/unittests/mac/unittests.icns new file mode 100644 index 0000000000000000000000000000000000000000..f36742de2572421b1eaa5569f64ab34e450ddb67 GIT binary patch literal 55080 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%0Ac$%Pvh#VA!uK`rp4)7 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 OV{TRe000a^@Bjd~o7PtV literal 0 HcmV?d00001 diff --git a/tests/unittests/message_router_unittest.cc b/tests/unittests/message_router_unittest.cc new file mode 100644 index 000000000..032f6f540 --- /dev/null +++ b/tests/unittests/message_router_unittest.cc @@ -0,0 +1,2815 @@ +// 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 +#include +#include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/strings/stringprintf.h" + +#include "include/base/cef_bind.h" +#include "include/base/cef_weak_ptr.h" +#include "include/cef_v8.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/routing_test_handler.h" +#include "tests/cefclient/client_app.h" + +// Comment out this define to disable the unit test timeout. +#define TIMEOUT_ENABLED 1 + +namespace { + +const char kTestDomainRoot[] = "http://tests-mr"; +const char kTestDomain1[] = "http://tests-mr1.com/"; +const char kTestDomain2[] = "http://tests-mr2.com/"; +const char kTestDomain3[] = "http://tests-mr3.com/"; + +const char kDoneMessageName[] = "mrtNotifyMsg"; + +const char kJSNotifyFunc[] = "mrtNotify"; +const char kJSAssertTotalCountFunc[] = "mrtAssertTotalCount"; +const char kJSAssertBrowserCountFunc[] = "mrtAssertBrowserCount"; +const char kJSAssertContextCountFunc[] = "mrtAssertContextCount"; + +void SetRouterConfig(CefMessageRouterConfig& config) { + config.js_query_function = "mrtQuery"; + config.js_cancel_function = "mrtQueryCancel"; +} + +// Handle the renderer side of the routing implementation. +class MRRenderDelegate : public ClientApp::RenderDelegate { + public: + class V8HandlerImpl : public CefV8Handler { + public: + explicit V8HandlerImpl(CefRefPtr delegate) + : delegate_(delegate) { + } + + virtual bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE { + const std::string& message_name = name; + if (message_name == kJSNotifyFunc) { + EXPECT_EQ(1U, arguments.size()); + EXPECT_TRUE(arguments[0]->IsString()); + + const CefString& msg = arguments[0]->GetStringValue(); + CefRefPtr context = CefV8Context::GetCurrentContext(); + CefRefPtr browser = context->GetBrowser(); + CefRefPtr frame = context->GetFrame(); + const int64 frame_id = frame->GetIdentifier(); + + CefRefPtr message = + CefProcessMessage::Create(kDoneMessageName); + CefRefPtr args = message->GetArgumentList(); + args->SetInt(0, CefInt64GetLow(frame_id)); + args->SetInt(1, CefInt64GetHigh(frame_id)); + args->SetString(2, msg); + EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, message)); + return true; + } else { + EXPECT_EQ(1U, arguments.size()); + EXPECT_TRUE(arguments[0]->IsInt()); + + const int expected_count = arguments[0]->GetIntValue(); + int actual_count = -1; + + CefRefPtr context = CefV8Context::GetCurrentContext(); + CefRefPtr browser = context->GetBrowser(); + + if (name == kJSAssertTotalCountFunc) { + actual_count = + delegate_->message_router_->GetPendingCount(NULL, NULL); + } else if (name == kJSAssertBrowserCountFunc) { + actual_count = + delegate_->message_router_->GetPendingCount(browser, NULL); + } else if (name == kJSAssertContextCountFunc) { + actual_count = + delegate_->message_router_->GetPendingCount(browser, context); + } + + if (expected_count != actual_count) { + const std::string& exceptionStr = + base::StringPrintf("%s failed; expected %d, got %d", + message_name.c_str(), expected_count, + actual_count); + exception = exceptionStr; + } + } + + return true; + } + + private: + CefRefPtr delegate_; + + IMPLEMENT_REFCOUNTING(V8HandlerImpl); + }; + + MRRenderDelegate() {} + + virtual void OnWebKitInitialized(CefRefPtr app) OVERRIDE { + // Create the renderer-side router for query handling. + CefMessageRouterConfig config; + SetRouterConfig(config); + message_router_ = CefMessageRouterRendererSide::Create(config); + } + + virtual void OnContextCreated(CefRefPtr app, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + const std::string& url = frame->GetURL(); + if (url.find(kTestDomainRoot) != 0) + return; + + message_router_->OnContextCreated(browser, frame, context); + + // Register function handlers with the 'window' object. + CefRefPtr window = context->GetGlobal(); + + CefRefPtr handler = new V8HandlerImpl(this); + CefV8Value::PropertyAttribute attributes = + static_cast( + V8_PROPERTY_ATTRIBUTE_READONLY | + V8_PROPERTY_ATTRIBUTE_DONTENUM | + V8_PROPERTY_ATTRIBUTE_DONTDELETE); + + CefRefPtr notify_func = + CefV8Value::CreateFunction(kJSNotifyFunc, handler.get()); + window->SetValue(kJSNotifyFunc, notify_func, attributes); + + CefRefPtr total_count_func = + CefV8Value::CreateFunction(kJSAssertTotalCountFunc, handler.get()); + window->SetValue(kJSAssertTotalCountFunc, total_count_func, attributes); + + CefRefPtr browser_count_func = + CefV8Value::CreateFunction(kJSAssertBrowserCountFunc, handler.get()); + window->SetValue(kJSAssertBrowserCountFunc, browser_count_func, attributes); + + CefRefPtr context_count_func = + CefV8Value::CreateFunction(kJSAssertContextCountFunc, handler.get()); + window->SetValue(kJSAssertContextCountFunc, context_count_func, attributes); + } + + virtual void OnContextReleased(CefRefPtr app, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + const std::string& url = frame->GetURL(); + if (url.find(kTestDomainRoot) != 0) + return; + + message_router_->OnContextReleased(browser, frame, context); + } + + virtual bool OnProcessMessageReceived( + CefRefPtr app, + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + const std::string& url = browser->GetMainFrame()->GetURL(); + if (url.find(kTestDomainRoot) != 0) + return false; + + return message_router_->OnProcessMessageReceived( + browser, source_process, message); + } + + private: + CefRefPtr message_router_; + + IMPLEMENT_REFCOUNTING(MRRenderDelegate); +}; + +} // namespace + +// Entry point for creating the test delegate. +// Called from client_app_delegates.cc. +void CreateMessageRouterRendererTests( + ClientApp::RenderDelegateSet& delegates) { + delegates.insert(new MRRenderDelegate); +} + + +namespace { + +class MRTestHandler : public TestHandler { + public: + MRTestHandler() { + } + + virtual void RunTest() OVERRIDE { + RunMRTest(); + +#if defined(TIMEOUT_ENABLED) + // Time out the test after a reasonable period of time. + CefPostDelayedTask(TID_UI, + base::Bind(&MRTestHandler::DestroyTest, this), + 4000); +#endif + } + + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE { + if (!message_router_) { + // Create the browser-side router for query handling. + CefMessageRouterConfig config; + SetRouterConfig(config); + message_router_ = CefMessageRouterBrowserSide::Create(config); + AddHandlers(message_router_); + } + TestHandler::OnAfterCreated(browser); + } + + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE{ + message_router_->OnBeforeClose(browser); + TestHandler::OnBeforeClose(browser); + } + + virtual void OnRenderProcessTerminated( + CefRefPtr browser, + TerminationStatus status) OVERRIDE{ + message_router_->OnRenderProcessTerminated(browser); + } + + // Only call this method if the navigation isn't canceled. + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) OVERRIDE{ + message_router_->OnBeforeBrowse(browser, frame); + return false; + } + + // Returns true if the router handled the navigation. + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE{ + const std::string& message_name = message->GetName(); + if (message_name == kDoneMessageName) { + CefRefPtr args = message->GetArgumentList(); + EXPECT_EQ(3U, args->GetSize()); + EXPECT_EQ(VTYPE_INT, args->GetType(0)); + EXPECT_EQ(VTYPE_INT, args->GetType(1)); + EXPECT_EQ(VTYPE_STRING, args->GetType(2)); + + const int64 frame_id = CefInt64Set(args->GetInt(0), args->GetInt(1)); + CefRefPtr frame = browser->GetFrame(frame_id); + EXPECT_TRUE(frame); + + OnNotify(browser, frame, args->GetString(2)); + return true; + } + + return message_router_->OnProcessMessageReceived( + browser, source_process, message); + } + + CefRefPtr GetRouter() const { + return message_router_; + }; + + protected: + virtual void RunMRTest() =0; + + virtual void AddHandlers( + CefRefPtr message_router) =0; + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) =0; + + bool AssertQueryCount(CefRefPtr browser, + CefMessageRouterBrowserSide::Handler* handler, + int expected_count) { + int actual_count = message_router_->GetPendingCount(browser, handler); + EXPECT_EQ(expected_count, actual_count); + return (expected_count == actual_count); + } + + void AssertMainBrowser(CefRefPtr browser) { + EXPECT_TRUE(browser.get()); + EXPECT_EQ(GetBrowserId(), browser->GetIdentifier()); + } + + private: + CefRefPtr message_router_; +}; + + +// Implementation of MRTestHandler that loads a single page. +class SingleLoadTestHandler : + public MRTestHandler, + public CefMessageRouterBrowserSide::Handler { + public: + SingleLoadTestHandler() + : main_url_(std::string(kTestDomain1) + "main.html") {} + + const std::string& GetMainURL() { return main_url_; } + + protected: + virtual void RunMRTest() OVERRIDE { + AddOtherResources(); + AddResource(main_url_, GetMainHTML(), "text/html"); + + CreateBrowser(main_url_, NULL); + } + + virtual void AddHandlers( + CefRefPtr message_router) OVERRIDE { + message_router->AddHandler(this, false); + } + + virtual void AddOtherResources() { + } + + virtual std::string GetMainHTML() =0; + + void AssertMainFrame(CefRefPtr frame) { + EXPECT_TRUE(frame.get()); + EXPECT_TRUE(frame->IsMain()); + EXPECT_STREQ(main_url_.c_str(), frame->GetURL().ToString().c_str()); + } + + private: + const std::string main_url_; +}; + +// Used to verify that the test harness (bound functions) behave correctly. +class HarnessTestHandler : public SingleLoadTestHandler { + public: + HarnessTestHandler(bool test_success) + : test_success_(test_success) {} + + virtual std::string GetMainHTML() OVERRIDE { + std::string html; + if (test_success_) { + // All assertions should pass. + html = + ""; + } else { + // All assertions should fail. + html = + ""; + } + return html; + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + got_done_.yes(); + EXPECT_STREQ("true", message.c_str()); + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_done_); + TestHandler::DestroyTest(); + } + + private: + const bool test_success_; + TrackCallback got_done_; +}; + +} // namespace + +// Verify that the test harness works with successful assertions. +TEST(MessageRouterTest, HarnessSuccess) { + CefRefPtr handler = new HarnessTestHandler(true); + handler->ExecuteTest(); +} + +// Verify that the test harness works with failed assertions. +TEST(MessageRouterTest, HarnessFailure) { + CefRefPtr handler = new HarnessTestHandler(false); + handler->ExecuteTest(); +} + + +namespace { + +const char kSingleQueryRequest[] = "request_context"; +const char kSingleQueryResponse[] = "success_response"; +const int kSingleQueryErrorCode = 5; +const char kSingleQueryErrorMessage[] = "error_message"; + +// Test a single query in a single page load. +class SingleQueryTestHandler : public SingleLoadTestHandler { + public: + enum TestType { + SUCCESS, + FAILURE, + CANCEL, + }; + + SingleQueryTestHandler(TestType type, bool sync_callback) + : test_type_(type), + sync_callback_(sync_callback), + query_id_(0) {} + + virtual std::string GetMainHTML() OVERRIDE { + std::string html; + + const std::string& errorCodeStr = + base::StringPrintf("%d", kSingleQueryErrorCode); + + html = ""; + return html; + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + // OnNotify only be called once. + EXPECT_FALSE(got_notify_); + got_notify_.yes(); + + if (test_type_ == SUCCESS) { + EXPECT_STREQ("success", message.c_str()); + } else if (test_type_ == FAILURE) { + EXPECT_STREQ("failure", message.c_str()); + } else if (test_type_ == CANCEL) { + EXPECT_STREQ("cancel", message.c_str()); + } + + DestroyTestIfDone(); + } + + void ExecuteCallback() { + EXPECT_TRUE(callback_.get()); + if (test_type_ == SUCCESS) { + callback_->Success(kSingleQueryResponse); + } else if (test_type_ == FAILURE) { + callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage); + } else { + EXPECT_TRUE(false); // Not reached. + } + callback_ = NULL; + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_NE(0, query_id); + EXPECT_FALSE(persistent); + EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); + + got_on_query_.yes(); + + query_id_ = query_id; + callback_ = callback; + + if (test_type_ == SUCCESS || test_type_ == FAILURE) { + if (sync_callback_) { + ExecuteCallback(); + } else { + CefPostTask(TID_UI, + base::Bind(&SingleQueryTestHandler::ExecuteCallback, this)); + } + } + + return true; + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_EQ(test_type_, CANCEL); + EXPECT_EQ(query_id_, query_id); + EXPECT_TRUE(got_on_query_); + EXPECT_TRUE(callback_.get()); + + got_on_query_canceled_.yes(); + callback_ = NULL; + + DestroyTestIfDone(); + } + + void DestroyTestIfDone() { + bool destroy_test = false; + if (test_type_ == CANCEL) + destroy_test = got_notify_ && got_on_query_canceled_; + else + destroy_test = got_notify_; + if (destroy_test) + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_notify_); + EXPECT_TRUE(got_on_query_); + EXPECT_FALSE(callback_.get()); + + if (test_type_ == CANCEL) + EXPECT_TRUE(got_on_query_canceled_); + else + EXPECT_FALSE(got_on_query_canceled_); + + TestHandler::DestroyTest(); + } + + private: + const TestType test_type_; + const bool sync_callback_; + + int64 query_id_; + CefRefPtr callback_; + + TrackCallback got_on_query_; + TrackCallback got_on_query_canceled_; + TrackCallback got_notify_; +}; + +} // namespace + +// Test that a single query with successful result delivered synchronously. +TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) { + CefRefPtr handler = + new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true); + handler->ExecuteTest(); +} + +// Test that a single query with successful result delivered asynchronously. +TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) { + CefRefPtr handler = + new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false); + handler->ExecuteTest(); +} + +// Test that a single query with failure result delivered synchronously. +TEST(MessageRouterTest, SingleQueryFailureSyncCallback) { + CefRefPtr handler = + new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true); + handler->ExecuteTest(); +} + +// Test that a single query with failure result delivered asynchronously. +TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) { + CefRefPtr handler = + new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false); + handler->ExecuteTest(); +} + +// Test that a single query with cancellation. +TEST(MessageRouterTest, SingleQueryCancel) { + CefRefPtr handler = + new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true); + handler->ExecuteTest(); +} + + +namespace { + +const int kSinglePersistentQueryResponseCount = 10; + +// Test a single persistent query in a single page load. +class SinglePersistentQueryTestHandler : public SingleLoadTestHandler { + public: + enum TestType { + SUCCESS, + FAILURE, + }; + + SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback) + : test_type_(test_type), + sync_callback_(sync_callback), + query_id_(0) {} + + virtual std::string GetMainHTML() OVERRIDE { + std::string html; + + const std::string& responseCountStr = + base::StringPrintf("%d", kSinglePersistentQueryResponseCount); + const std::string& errorCodeStr = + base::StringPrintf("%d", kSingleQueryErrorCode); + + html = ""; + return html; + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + if (test_type_ == SUCCESS) + EXPECT_STREQ("success", message.c_str()); + else if (test_type_ == FAILURE) + EXPECT_STREQ("failure", message.c_str()); + + got_notify_.yes(); + + DestroyTestIfDone(); + } + + void ExecuteCallback() { + EXPECT_TRUE(callback_.get()); + if (test_type_ == SUCCESS) { + callback_->Success(kSingleQueryResponse); + } else { + callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage); + callback_ = NULL; + } + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_NE(0, query_id); + EXPECT_TRUE(persistent); + EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); + + got_on_query_.yes(); + + query_id_ = query_id; + callback_ = callback; + + int repeat = + (test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1); + + for (int i = 0; i < repeat; ++i) { + if (sync_callback_) { + ExecuteCallback(); + } else { + CefPostTask(TID_UI, + base::Bind(&SinglePersistentQueryTestHandler::ExecuteCallback, + this)); + } + } + + return true; + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_EQ(query_id_, query_id); + EXPECT_TRUE(got_on_query_); + EXPECT_TRUE(callback_.get()); + + got_on_query_canceled_.yes(); + callback_ = NULL; + + DestroyTestIfDone(); + } + + void DestroyTestIfDone() { + bool destroy_test = false; + if (test_type_ == SUCCESS) { + if (got_on_query_ && got_on_query_canceled_ && got_notify_) + destroy_test = true; + } else if (got_on_query_ && got_notify_) { + destroy_test = true; + } + + if (destroy_test) + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_notify_); + EXPECT_TRUE(got_on_query_); + EXPECT_FALSE(callback_.get()); + + if (test_type_ == SUCCESS) + EXPECT_TRUE(got_on_query_canceled_); + else + EXPECT_FALSE(got_on_query_canceled_); + + TestHandler::DestroyTest(); + } + + private: + const TestType test_type_; + const bool sync_callback_; + + int64 query_id_; + CefRefPtr callback_; + + TrackCallback got_on_query_; + TrackCallback got_on_query_canceled_; + TrackCallback got_notify_; +}; + +} // namespace + +// Test that a single query with successful result delivered synchronously. +TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) { + CefRefPtr handler = + new SinglePersistentQueryTestHandler( + SinglePersistentQueryTestHandler::SUCCESS, true); + handler->ExecuteTest(); +} + +// Test that a single query with successful result delivered asynchronously. +TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) { + CefRefPtr handler = + new SinglePersistentQueryTestHandler( + SinglePersistentQueryTestHandler::SUCCESS, false); + handler->ExecuteTest(); +} + +// Test that a single query with failure result delivered synchronously. +TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) { + CefRefPtr handler = + new SinglePersistentQueryTestHandler( + SinglePersistentQueryTestHandler::FAILURE, true); + handler->ExecuteTest(); +} + +// Test that a single query with failure result delivered asynchronously. +TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) { + CefRefPtr handler = + new SinglePersistentQueryTestHandler( + SinglePersistentQueryTestHandler::FAILURE, false); + handler->ExecuteTest(); +} + + +namespace { + +// Test a single unhandled query in a single page load. +class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler { + public: + SingleUnhandledQueryTestHandler() {} + + virtual std::string GetMainHTML() OVERRIDE { + std::string html; + + html = ""; + return html; + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_STREQ("failure", message.c_str()); + + got_notify_.yes(); + + DestroyTest(); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + EXPECT_NE(0, query_id); + EXPECT_FALSE(persistent); + EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); + + got_on_query_.yes(); + + return false; + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + EXPECT_FALSE(true); // Not reached. + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_on_query_); + EXPECT_TRUE(got_notify_); + + TestHandler::DestroyTest(); + } + + private: + TrackCallback got_on_query_; + TrackCallback got_notify_; +}; + +} // namespace + +// Test that a single unhandled query results in a call to onFailure. +TEST(MessageRouterTest, SingleUnhandledQuery) { + CefRefPtr handler = + new SingleUnhandledQueryTestHandler(); + handler->ExecuteTest(); +} + + +namespace { + +const char kMultiQueryRequestId[] = "request_id"; +const char kMultiQueryRepeatCt[] = "repeat_ct"; +const char kMultiQueryRequest[] = "request"; +const char kMultiQueryResponse[] = "response"; +const char kMultiQuerySuccess[] = "success"; +const char kMultiQueryError[] = "error"; +const char kMultiQueryErrorMessage[] = "errormsg"; +const int kMultiQueryPersistentResponseCount = 5; + +// Generates HTML and verifies results for multiple simultanious queries. +class MultiQueryManager : public CefMessageRouterBrowserSide::Handler { + public: + enum TestType { + // Initiates a non-persistent query with a successful response. + // OnQuery and OnNotify will be called. + SUCCESS, + + // Initiates a non-persistent query with a failure response. + // OnQuery and OnNotify will be called. + FAILURE, + + // Initiates a persistent query with multiple successful responses. + // OnQuery, OnNotify and OnQueryCanceled will be called. + PERSISTENT_SUCCESS, + + // Initiates a persistent query with multiple successful responses and one + // failure response. + // OnQuery and OnNotify will be called. + PERSISTENT_FAILURE, + + // Initiates a non-persistent query that will be canceled via JavaScript. + // No JavaScript callbacks will be executed. + // OnQuery and OnQueryCanceled will be called. + CANCEL, + + // Initiates a non-persistent query that will not be manually canceled. + // No JavaScript callbacks will be executed. + // OnQuery and OnQueryCanceled will be called. + AUTOCANCEL, + + // Initiates a persistent query with multiple successful responses that will + // not be manually canceled. + // OnQuery, OnNotify and OnQueryCanceled will be called. + PERSISTENT_AUTOCANCEL, + }; + + class Observer { + public: + // Called when all manual queries are complete. + virtual void OnManualQueriesCompleted(MultiQueryManager* manager) {} + + // Called when all queries are complete. + virtual void OnAllQueriesCompleted(MultiQueryManager* manager) {} + protected: + virtual ~Observer() {} + }; + + MultiQueryManager(const std::string& label, + bool synchronous, + int id_offset = 0) + : label_(label), + synchronous_(synchronous), + id_offset_(id_offset), + finalized_(false), + running_(false), + manual_total_(0), + received_count_(0), + manual_complete_count_(0), + auto_complete_count_(0), + will_cancel_by_removing_handler_(false), + weak_ptr_factory_(this) { + } + + virtual ~MultiQueryManager() {} + + void AddObserver(Observer* observer) { + EXPECT_FALSE(running_); + observer_set_.insert(observer); + } + + void RemoveObserver(Observer* observer) { + EXPECT_FALSE(running_); + EXPECT_TRUE(observer_set_.erase(observer)); + } + + // Can be called from any thread, but should always be called from the same + // thread. + void AddTestQuery(TestType type) { + EXPECT_FALSE(finalized_); + test_query_vector_.push_back(TestQuery(type)); + if (!IsAuto(type)) + manual_total_++; + } + + // Must be called after AddTestQuery and before the manager is used. + void Finalize() { + EXPECT_FALSE(finalized_); + finalized_ = true; + } + + // Call after all manual queries have completed if you intend to cancel auto + // queries by removing the handler. + void WillCancelByRemovingHandler() { + EXPECT_TRUE(IsManualComplete()); + will_cancel_by_removing_handler_ = true; + } + + std::string GetHTML(bool assert_total, bool assert_browser) const { + EXPECT_TRUE(finalized_); + EXPECT_FALSE(running_); + + std::string html; + + html = "" + label_ + ""; + + return html; + } + + void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) { + EXPECT_TRUE(finalized_); + EXPECT_UI_THREAD(); + + if (!running_) + running_ = true; + + EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); + + std::string value; + int index = 0; + EXPECT_TRUE(SplitIDString(message, &value, &index)); + + TestQuery& query = test_query_vector_[index]; + + // Verify that browser and frame are the same. + EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << index; + EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << index; + + // Verify a successful/expected result. + if (will_cancel_by_removing_handler_) { + // Auto queries receive an onFailure callback which will notify with error + // when the handler is removed. + EXPECT_STREQ(kMultiQueryError, value.c_str()) << index; + EXPECT_TRUE(IsAuto(query.type)) << index; + EXPECT_TRUE(query.got_query) << index; + if (query.type == PERSISTENT_AUTOCANCEL) + EXPECT_TRUE(query.got_success) << index; + else + EXPECT_FALSE(query.got_success) << index; + + query.got_error.yes(); + + // There's a race between OnQueryCanceled and OnNotification. Only call + // OnQueryCompleted a single time. + if (query.got_query_canceled) + OnQueryCompleted(query.type); + } else { + EXPECT_STREQ(kMultiQuerySuccess, value.c_str()) << index; + EXPECT_TRUE(WillNotify(query.type)) << index; + EXPECT_TRUE(query.got_query) << index; + EXPECT_FALSE(query.got_query_canceled) << index; + EXPECT_FALSE(query.got_success) << index; + + query.got_success.yes(); + + // PERSISTENT_AUTOCANCEL doesn't call OnReceiveCompleted from OnQuery. + if (query.type == PERSISTENT_AUTOCANCEL) + OnReceiveCompleted(query.type); + + // Call OnQueryCompleted for types that don't get OnQueryCanceled. + if (!WillCancel(query.type)) + OnQueryCompleted(query.type); + } + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(finalized_); + EXPECT_UI_THREAD(); + + if (!running_) + running_ = true; + + EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); + EXPECT_NE(0, query_id); + + std::string value; + int index = 0; + EXPECT_TRUE(SplitIDString(request, &value, &index)); + + TestQuery& query = test_query_vector_[index]; + + if (IsPersistent(query.type)) + EXPECT_TRUE(persistent); + else + EXPECT_FALSE(persistent); + + // Verify expected request. + EXPECT_STREQ(kMultiQueryRequest, value.c_str()) << index; + + // Verify that call order is correct. + EXPECT_FALSE(query.got_query) << index; + EXPECT_FALSE(query.got_query_canceled) << index; + EXPECT_FALSE(query.got_success) << index; + EXPECT_FALSE(query.got_error) << index; + + query.got_query.yes(); + + query.browser_id = browser->GetIdentifier(); + query.frame_id = frame->GetIdentifier(); + + if (query.type == SUCCESS) { + // Send the single success response. + callback->Success(GetIDString(kMultiQueryResponse, index)); + } else if (IsPersistent(query.type)) { + // Send the required number of successful responses. + const std::string& response = GetIDString(kMultiQueryResponse, index); + for (int i = 0; i < kMultiQueryPersistentResponseCount; ++i) + callback->Success(response); + } + + if (WillFail(query.type)) { + // Send the single failure response. + callback->Failure(index, GetIDString(kMultiQueryErrorMessage, index)); + } + + if (WillCancel(query.type)) { + // Hold onto the callback until the query is canceled. + query.query_id = query_id; + query.callback = callback; + } + + // PERSISTENT_AUTOCANCEL will call OnReceiveCompleted once the success + // notification is received. + if (query.type != PERSISTENT_AUTOCANCEL) + OnReceiveCompleted(query.type); + + return true; + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + EXPECT_TRUE(finalized_); + EXPECT_UI_THREAD(); + + if (!running_) + running_ = true; + + EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); + EXPECT_NE(0, query_id); + + bool found = false; + for (size_t i = 0; i < test_query_vector_.size(); ++i) { + TestQuery& query = test_query_vector_[i]; + if (query.query_id == query_id) { + // Verify that browser and frame are the same. + EXPECT_EQ(query.browser_id, browser->GetIdentifier()) << i; + EXPECT_EQ(query.frame_id, frame->GetIdentifier()) << i; + + // Verify a successful/expected result. + EXPECT_TRUE(WillCancel(query.type)) << i; + EXPECT_TRUE(query.callback) << i; + + // Release the callback. + query.callback = NULL; + + // Verify that call order is correct. + EXPECT_TRUE(query.got_query) << i; + + if (query.type == CANCEL || query.type == AUTOCANCEL) { + // No JavaScript onSuccess callback executes. + EXPECT_FALSE(query.got_success) << i; + } else { + // JavaScript onSuccess does execute before cancellation. + EXPECT_TRUE(query.got_success) << i; + } + + query.got_query_canceled.yes(); + + if (will_cancel_by_removing_handler_) { + // There's a race between OnQueryCanceled and OnNotification. Only + // call OnQueryCompleted a single time. + if (query.got_error) + OnQueryCompleted(query.type); + } else { + EXPECT_FALSE(query.got_error) << i; + + // Cancellation is always completion. + OnQueryCompleted(query.type); + } + + found = true; + break; + } + } + EXPECT_TRUE(found); + } + + // Asserts that all queries have completed. + void AssertAllComplete() const { + EXPECT_TRUE(finalized_); + EXPECT_FALSE(running_); + EXPECT_UI_THREAD(); + + for (size_t i = 0; i < test_query_vector_.size(); ++i) { + const TestQuery& query = test_query_vector_[i]; + EXPECT_TRUE(query.got_query) << i; + + if (WillCancel(query.type)) + EXPECT_TRUE(query.got_query_canceled) << i; + else + EXPECT_FALSE(query.got_query_canceled) << i; + + if (WillNotify(query.type)) + EXPECT_TRUE(query.got_success) << i; + else + EXPECT_FALSE(query.got_success) << i; + + if (IsAuto(query.type) && will_cancel_by_removing_handler_) + EXPECT_TRUE(query.got_error); + else + EXPECT_FALSE(query.got_error); + + EXPECT_FALSE(query.callback) << i; + } + } + + // Returns true if all manual queries have completed. + bool IsManualComplete() const { + EXPECT_TRUE(finalized_); + EXPECT_UI_THREAD(); + + return (manual_complete_count_ == manual_total_); + } + + // Returns true if all queries have completed. + bool IsAllComplete() const { + EXPECT_TRUE(finalized_); + EXPECT_UI_THREAD(); + + return (manual_complete_count_ + auto_complete_count_ == + static_cast(test_query_vector_.size())); + } + + bool HasAutoQueries() const { + return (manual_total_ != static_cast(test_query_vector_.size())); + } + + private: + struct TestQuery { + explicit TestQuery(TestType test_type) + : type(test_type), + browser_id(0), + frame_id(0), + query_id(0) {} + + TestType type; + + // Set in OnQuery and verified in OnNotify or OnQueryCanceled. + int browser_id; + int64 frame_id; + + // Used when a query is canceled. + int64 query_id; + CefRefPtr callback; + + TrackCallback got_query; + TrackCallback got_query_canceled; + TrackCallback got_success; + TrackCallback got_error; + }; + + class NotifyTask : public CefTask { + public: + NotifyTask(base::WeakPtr weak_ptr, + bool notify_all) + : weak_ptr_(weak_ptr), + notify_all_(notify_all) {} + + virtual void Execute() OVERRIDE { + if (weak_ptr_) { + if (notify_all_) + weak_ptr_->NotifyAllQueriesCompleted(); + else + weak_ptr_->NotifyManualQueriesCompleted(); + } + } + + private: + base::WeakPtr weak_ptr_; + const bool notify_all_; + + IMPLEMENT_REFCOUNTING(NotifyTask); + }; + + static bool IsAuto(TestType type) { + return (type == AUTOCANCEL || + type == PERSISTENT_AUTOCANCEL); + } + + static bool IsPersistent(TestType type) { + return (type == PERSISTENT_SUCCESS || + type == PERSISTENT_FAILURE || + type == PERSISTENT_AUTOCANCEL); + } + + static bool WillFail(TestType type) { + return (type == FAILURE || + type == PERSISTENT_FAILURE); + } + + static bool WillCancel(TestType type) { + return (type == PERSISTENT_SUCCESS || + type == CANCEL || + type == AUTOCANCEL || + type == PERSISTENT_AUTOCANCEL); + } + + static bool WillNotify(TestType type) { + return (type == SUCCESS || + type == PERSISTENT_SUCCESS || + type == FAILURE || + type == PERSISTENT_FAILURE || + type == PERSISTENT_AUTOCANCEL); + } + + void OnReceiveCompleted(TestType type) { + const int total_count = static_cast(test_query_vector_.size()); + if (++received_count_ == total_count && manual_total_ == 0) { + // There aren't any manual queries so notify here. + CefPostTask(TID_UI, + new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false)); + } + } + + void OnQueryCompleted(TestType type) { + const int total_count = static_cast(test_query_vector_.size()); + EXPECT_LT(manual_complete_count_ + auto_complete_count_, total_count); + EXPECT_LE(manual_complete_count_, manual_total_); + + const bool is_auto = IsAuto(type); + if (is_auto) + auto_complete_count_++; + else if (++manual_complete_count_ == manual_total_) { + CefPostTask(TID_UI, + new NotifyTask(weak_ptr_factory_.GetWeakPtr(), false)); + } + + if (auto_complete_count_ + manual_complete_count_ == total_count) { + running_ = false; + CefPostTask(TID_UI, + new NotifyTask(weak_ptr_factory_.GetWeakPtr(), true)); + } + } + + void NotifyManualQueriesCompleted() { + if (observer_set_.empty()) + return; + + // Use a copy of the set in case an Observer is removed while we're + // iterating. + ObserverSet observer_set = observer_set_; + + ObserverSet::const_iterator it = observer_set.begin(); + for (; it != observer_set.end(); ++it) { + (*it)->OnManualQueriesCompleted(this); + } + } + + void NotifyAllQueriesCompleted() { + if (observer_set_.empty()) + return; + + // Use a copy of the set in case an Observer is removed while we're + // iterating. + ObserverSet observer_set = observer_set_; + + ObserverSet::const_iterator it = observer_set.begin(); + for (; it != observer_set.end(); ++it) { + (*it)->OnAllQueriesCompleted(this); + } + } + + std::string GetQueryHTML(const int index, const TestQuery& query) const { + const std::string& request_id_var = + GetIDString(kMultiQueryRequestId, index); + const std::string& repeat_ct_var = GetIDString(kMultiQueryRepeatCt, index); + const std::string& request_val = + GetIDString(std::string(kMultiQueryRequest) + ":", index); + const std::string& success_val = + GetIDString(std::string(kMultiQuerySuccess) + ":", index); + const std::string& error_val = + GetIDString(std::string(kMultiQueryError) + ":", index); + + std::string html; + + const bool persistent = IsPersistent(query.type); + + if (persistent) + html += "var " + repeat_ct_var + " = 0;\n"; + + html += "var " + request_id_var + " = window.mrtQuery({\n" + " request: '" + request_val + "',\n" + " persistent: " + (persistent ? "true" : "false") + ",\n"; + + if (query.type == SUCCESS) { + const std::string& response_val = + GetIDString(kMultiQueryResponse, index); + + html += " onSuccess: function(response) {\n" + " if (response == '" + response_val + "')\n" + " window.mrtNotify('" + success_val + "');\n" + " else\n" + " window.mrtNotify('" + error_val + "');\n" + " },\n" + " onFailure: function(error_code, error_message) {\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n"; + } else if (query.type == FAILURE) { + const std::string& error_code_val = GetIntString(index); + const std::string& error_message_val = + GetIDString(kMultiQueryErrorMessage, index); + + html += " onSuccess: function(response) {\n" + " window.mrtNotify('" + error_val + "');\n" + " },\n" + " onFailure: function(error_code, error_message) {\n" + " if (error_code == " + error_code_val + + " && error_message == '" + error_message_val + "')\n" + " window.mrtNotify('" + success_val + "');\n" + " else\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n"; + } else if (query.type == PERSISTENT_SUCCESS || + query.type == PERSISTENT_AUTOCANCEL) { + const std::string& response_val = + GetIDString(kMultiQueryResponse, index); + const std::string& repeat_ct = + GetIntString(kMultiQueryPersistentResponseCount); + + html += " onSuccess: function(response) {\n" + " if (response == '" + response_val + "') {\n" + // Should get repeat_ct number of successful responses. + " if (++" + repeat_ct_var + " == " + repeat_ct + ") {\n" + " window.mrtNotify('" + success_val + "');\n"; + + if (query.type == PERSISTENT_SUCCESS) { + // Manually cancel the request. + html += " window.mrtQueryCancel(" + request_id_var + ");\n"; + } + + html += " }\n" + " } else {\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n" + " },\n" + " onFailure: function(error_code, error_message) {\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n"; + } else if (query.type == PERSISTENT_FAILURE) { + const std::string& error_code_val = GetIntString(index); + const std::string& error_message_val = + GetIDString(kMultiQueryErrorMessage, index); + const std::string& repeat_ct = + GetIntString(kMultiQueryPersistentResponseCount); + + html += " onSuccess: function(response) {\n" + // Should get some successful responses before failure. + " if (++" + repeat_ct_var + " > " + repeat_ct + ") {\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n" + " },\n" + " onFailure: function(error_code, error_message) {\n" + " if (error_code == " + error_code_val + + " && error_message == '" + error_message_val + "'" + " && " + repeat_ct_var + " == " + repeat_ct + ")\n" + " window.mrtNotify('" + success_val + "');\n" + " else\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n"; + } else if (query.type == CANCEL || query.type == AUTOCANCEL) { + html += " onSuccess: function(response) {\n" + " window.mrtNotify('" + error_val + "');\n" + " },\n" + " onFailure: function(error_code, error_message) {\n" + " window.mrtNotify('" + error_val + "');\n" + " }\n"; + } + + html += "});\n"; + + return html; + } + + std::string GetCancelHTML(const int index, const TestQuery& query) const { + const std::string& request_id_var = GetIDString(kMultiQueryRequestId, index); + return "window.mrtQueryCancel(" + request_id_var + ");\n"; + } + + std::string GetIDString(const std::string& prefix, int index) const { + EXPECT_TRUE(!prefix.empty()); + return base::StringPrintf("%s%d", prefix.c_str(), GetIDFromIndex(index)); + } + + bool SplitIDString(const std::string& str, + std::string* value, int* index) const { + size_t pos = str.find(':'); + if (pos != std::string::npos) { + *value = str.substr(0, pos); + *index = GetIndexFromID(atoi(str.substr(pos+1).c_str())); + return (*index >= 0 && + *index < static_cast(test_query_vector_.size())); + } + + return false; + } + + std::string GetIntString(int val) const { + return base::StringPrintf("%d", val); + } + + int GetIDFromIndex(int index) const { return id_offset_ + index; } + int GetIndexFromID(int id) const { return id - id_offset_; } + + const std::string label_; + const bool synchronous_; + const int id_offset_; + + typedef std::vector TestQueryVector; + TestQueryVector test_query_vector_; + + typedef std::set ObserverSet; + ObserverSet observer_set_; + + // Set to true after all queries have been added. + bool finalized_; + // Set to true while queries are pending. + bool running_; + + // Total number of queries that will manually complete. + int manual_total_; + + // Number of queries that have been received. + int received_count_; + + // Number of queries that have completed successfully. + int manual_complete_count_; + int auto_complete_count_; + + // If true any pending queries will receive an onFailure callback in addition + // to be canceled. + bool will_cancel_by_removing_handler_; + + // Should always be the last member. + base::WeakPtrFactory weak_ptr_factory_; +}; + +void MakeTestQueries(MultiQueryManager* manager, bool some, + int many_count = 200) { + if (some) { + // Test some queries of arbitrary types. + // Use a hard-coded list so the behavior is deterministic across test runs. + MultiQueryManager::TestType types[] = { + MultiQueryManager::PERSISTENT_AUTOCANCEL, + MultiQueryManager::SUCCESS, + MultiQueryManager::AUTOCANCEL, + MultiQueryManager::PERSISTENT_FAILURE, + MultiQueryManager::CANCEL, + MultiQueryManager::FAILURE, + MultiQueryManager::AUTOCANCEL, + MultiQueryManager::SUCCESS, + MultiQueryManager::PERSISTENT_SUCCESS, + MultiQueryManager::SUCCESS, + MultiQueryManager::PERSISTENT_AUTOCANCEL, + MultiQueryManager::CANCEL, + MultiQueryManager::PERSISTENT_SUCCESS, + MultiQueryManager::FAILURE, + }; + for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { + manager->AddTestQuery(types[i]); + } + } else { + // Test every type of query. + for (int i = 0; i < many_count; ++i) { + MultiQueryManager::TestType type; + switch (i % 7) { + case 0: + type = MultiQueryManager::SUCCESS; + break; + case 1: + type = MultiQueryManager::FAILURE; + break; + case 2: + type = MultiQueryManager::PERSISTENT_SUCCESS; + break; + case 3: + type = MultiQueryManager::PERSISTENT_FAILURE; + break; + case 4: + type = MultiQueryManager::CANCEL; + break; + case 5: + type = MultiQueryManager::AUTOCANCEL; + break; + case 6: + type = MultiQueryManager::PERSISTENT_AUTOCANCEL; + break; + } + manager->AddTestQuery(type); + } + } + manager->Finalize(); +} + +// Test multiple queries in a single page load with a single frame. +class MultiQuerySingleFrameTestHandler : + public SingleLoadTestHandler, + public MultiQueryManager::Observer { + public: + enum CancelType { + CANCEL_BY_NAVIGATION, + CANCEL_BY_REMOVING_HANDLER, + CANCEL_BY_CLOSING_BROWSER, + }; + + MultiQuerySingleFrameTestHandler( + bool synchronous, + CancelType cancel_type = CANCEL_BY_NAVIGATION) + : manager_(std::string(), synchronous), + cancel_type_(cancel_type) { + manager_.AddObserver(this); + } + + virtual std::string GetMainHTML() OVERRIDE { + return manager_.GetHTML(true, true); + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + manager_.OnNotify(browser, frame, message); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + return manager_.OnQuery(browser, frame, query_id, request, persistent, + callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + manager_.OnQueryCanceled(browser, frame, query_id); + } + + virtual void OnManualQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + EXPECT_EQ(manager, &manager_); + if (manager_.HasAutoQueries()) { + if (cancel_type_ == CANCEL_BY_NAVIGATION) { + // Navigate somewhere else to terminate the auto queries. + GetBrowser()->GetMainFrame()->LoadURL( + std::string(kTestDomain1) + "cancel.html"); + } else if (cancel_type_ == CANCEL_BY_REMOVING_HANDLER) { + // Change the expected behavior in the manager. + manager_.WillCancelByRemovingHandler(); + GetRouter()->RemoveHandler(this); + // All queries should be immediately canceled. + AssertQueryCount(NULL, NULL, 0); + } else if (cancel_type_ == CANCEL_BY_CLOSING_BROWSER) { + // Change the expected behavior in the handler. + SetSignalCompletionWhenAllBrowsersClose(false); + GetBrowser()->GetHost()->CloseBrowser(false); + } + } + } + + virtual void OnAllQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + EXPECT_EQ(manager, &manager_); + + // All queries should be canceled. + AssertQueryCount(NULL, NULL, 0); + + DestroyTest(); + + if (!SignalCompletionWhenAllBrowsersClose()) { + // Complete asynchronously so the call stack has a chance to unwind. + CefPostTask(TID_UI, + base::Bind(&MultiQuerySingleFrameTestHandler::TestComplete, this)); + } + } + + virtual void DestroyTest() OVERRIDE { + manager_.AssertAllComplete(); + TestHandler::DestroyTest(); + } + + MultiQueryManager* GetManager() { return &manager_; } + + private: + MultiQueryManager manager_; + const CancelType cancel_type_; +}; + +} // namespace + +#define MULTI_QUERY_SINGLE_FRAME_TYPE_TEST(name, type, synchronous) \ + TEST(MessageRouterTest, name) { \ + CefRefPtr handler = \ + new MultiQuerySingleFrameTestHandler(synchronous); \ + MultiQueryManager* manager = handler->GetManager(); \ + manager->AddTestQuery(MultiQueryManager::type); \ + manager->Finalize(); \ + handler->ExecuteTest(); \ + } + +// Test the query types individually. +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameSyncSuccess, SUCCESS, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameAsyncSuccess, SUCCESS, false); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameSyncFailure, FAILURE, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameAsyncFailure, FAILURE, false); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameSyncPersistentSuccess, PERSISTENT_SUCCESS, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameAsyncPersistentSuccess, PERSISTENT_SUCCESS, false); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameSyncPersistentFailure, PERSISTENT_FAILURE, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameAsyncPersistentFailure, PERSISTENT_FAILURE, false); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameCancel, CANCEL, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFrameAutoCancel, AUTOCANCEL, true); +MULTI_QUERY_SINGLE_FRAME_TYPE_TEST( + MultiQuerySingleFramePersistentAutoCancel, PERSISTENT_AUTOCANCEL, true); + +// Test that one frame can run some queries successfully in a synchronous +// manner. +TEST(MessageRouterTest, MultiQuerySingleFrameSyncSome) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(true); + MakeTestQueries(handler->GetManager(), true); + handler->ExecuteTest(); +} + +// Test that one frame can run some queries successfully in an asynchronous +// manner. +TEST(MessageRouterTest, MultiQuerySingleFrameAsyncSome) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(false); + MakeTestQueries(handler->GetManager(), true); + handler->ExecuteTest(); +} + +// Test that one frame can run many queries successfully in a synchronous +// manner. +TEST(MessageRouterTest, MultiQuerySingleFrameSyncMany) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(true); + MakeTestQueries(handler->GetManager(), false); + handler->ExecuteTest(); +} + +// Test that one frame can run many queries successfully in an asynchronous +// manner. +TEST(MessageRouterTest, MultiQuerySingleFrameAsyncMany) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(false); + MakeTestQueries(handler->GetManager(), false); + handler->ExecuteTest(); +} + +// Test that pending queries can be canceled by removing the handler. +TEST(MessageRouterTest, MultiQuerySingleFrameCancelByRemovingHandler) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(false, + MultiQuerySingleFrameTestHandler::CANCEL_BY_REMOVING_HANDLER); + MakeTestQueries(handler->GetManager(), false); + handler->ExecuteTest(); +} + +// Test that pending queries can be canceled by closing the browser. +TEST(MessageRouterTest, MultiQuerySingleFrameCancelByClosingBrowser) { + CefRefPtr handler = + new MultiQuerySingleFrameTestHandler(false, + MultiQuerySingleFrameTestHandler::CANCEL_BY_CLOSING_BROWSER); + MakeTestQueries(handler->GetManager(), false); + handler->ExecuteTest(); +} + + +namespace { + +// Test multiple handlers. +class MultiQueryMultiHandlerTestHandler : + public SingleLoadTestHandler, + public MultiQueryManager::Observer { + public: + class Handler : public CefMessageRouterBrowserSide::Handler { + public: + Handler(MultiQueryMultiHandlerTestHandler* test_handler, + int index) + : test_handler_(test_handler), + index_(index), + query_id_(0) { + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + // Each handler only handles a single request. + const std::string& handled_request = + base::StringPrintf("%s:%d", kMultiQueryRequest, index_); + if (request != handled_request) + return false; + + // Verify that handlers are called in the correct order. + if (index_ == 0) { + EXPECT_FALSE(test_handler_->got_query0_); + EXPECT_FALSE(test_handler_->got_query1_); + EXPECT_FALSE(test_handler_->got_query2_); + + test_handler_->got_query0_.yes(); + } else if (index_ == 1) { + EXPECT_TRUE(test_handler_->got_query0_); + EXPECT_FALSE(test_handler_->got_query1_); + EXPECT_FALSE(test_handler_->got_query2_); + + test_handler_->got_query1_.yes(); + } else if (index_ == 2) { + EXPECT_TRUE(test_handler_->got_query0_); + EXPECT_TRUE(test_handler_->got_query1_); + EXPECT_FALSE(test_handler_->got_query2_); + + test_handler_->got_query2_.yes(); + } + + query_id_ = query_id; + return test_handler_->OnQuery(browser, frame, query_id, request, + persistent, callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + // Verify that the correct handler is called for cancellation. + EXPECT_EQ(query_id_, query_id); + + if (index_ == 0) { + EXPECT_FALSE(test_handler_->got_query_canceled0_); + test_handler_->got_query_canceled0_.yes(); + } else if (index_ == 1) { + EXPECT_FALSE(test_handler_->got_query_canceled1_); + test_handler_->got_query_canceled1_.yes(); + } else if (index_ == 2) { + EXPECT_FALSE(test_handler_->got_query_canceled2_); + test_handler_->got_query_canceled2_.yes(); + } + + test_handler_->OnQueryCanceled(browser, frame, query_id); + } + + private: + MultiQueryMultiHandlerTestHandler* test_handler_; + const int index_; + int query_id_; + }; + + MultiQueryMultiHandlerTestHandler(bool synchronous, + bool cancel_by_removing_handler) + : manager_(std::string(), synchronous, 0), + handler0_(this, 0), + handler1_(this, 1), + handler2_(this, 2), + cancel_by_removing_handler_(cancel_by_removing_handler) { + manager_.AddObserver(this); + + // Each handler will handle one of the queries. + manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL); + manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL); + manager_.AddTestQuery(MultiQueryManager::PERSISTENT_AUTOCANCEL); + manager_.Finalize(); + } + + virtual std::string GetMainHTML() OVERRIDE { + return manager_.GetHTML(true, true); + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + manager_.OnNotify(browser, frame, message); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + return manager_.OnQuery(browser, frame, query_id, request, persistent, + callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + AssertMainBrowser(browser); + AssertMainFrame(frame); + + manager_.OnQueryCanceled(browser, frame, query_id); + } + + virtual void OnManualQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + EXPECT_EQ(manager, &manager_); + + EXPECT_TRUE(got_query0_); + EXPECT_TRUE(got_query1_); + EXPECT_TRUE(got_query2_); + EXPECT_FALSE(got_query_canceled0_); + EXPECT_FALSE(got_query_canceled1_); + EXPECT_FALSE(got_query_canceled2_); + + EXPECT_TRUE(manager_.HasAutoQueries()); + + CefMessageRouterBrowserSide* router = GetRouter(); + + // Remove one handler to cancel a query. + + if (cancel_by_removing_handler_) { + manager_.WillCancelByRemovingHandler(); + + // Each query should be canceled as the handler is removed. + EXPECT_TRUE(router->RemoveHandler(&handler1_)); + EXPECT_FALSE(got_query_canceled0_); + EXPECT_TRUE(got_query_canceled1_); + EXPECT_FALSE(got_query_canceled2_); + + EXPECT_TRUE(router->RemoveHandler(&handler2_)); + EXPECT_FALSE(got_query_canceled0_); + EXPECT_TRUE(got_query_canceled2_); + + EXPECT_TRUE(router->RemoveHandler(&handler0_)); + EXPECT_TRUE(got_query_canceled0_); + } else { + GetBrowser()->GetMainFrame()->LoadURL( + std::string(kTestDomain1) + "cancel.html"); + } + } + + virtual void OnAllQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + EXPECT_EQ(manager, &manager_); + + // All queries should be canceled. + AssertQueryCount(NULL, NULL, 0); + + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + EXPECT_TRUE(got_query0_); + EXPECT_TRUE(got_query1_); + EXPECT_TRUE(got_query2_); + EXPECT_TRUE(got_query_canceled0_); + EXPECT_TRUE(got_query_canceled1_); + EXPECT_TRUE(got_query_canceled2_); + + manager_.AssertAllComplete(); + TestHandler::DestroyTest(); + } + + protected: + virtual void AddHandlers( + CefRefPtr message_router) OVERRIDE { + // OnQuery call order will verify that the first/last ordering works as + // expected. + EXPECT_TRUE(message_router->AddHandler(&handler1_, true)); + EXPECT_TRUE(message_router->AddHandler(&handler0_, true)); + EXPECT_TRUE(message_router->AddHandler(&handler2_, false)); + + // Can't add the same handler multiple times. + EXPECT_FALSE(message_router->AddHandler(&handler1_, true)); + } + + private: + MultiQueryManager manager_; + Handler handler0_; + Handler handler1_; + Handler handler2_; + + const bool cancel_by_removing_handler_; + + TrackCallback got_query0_; + TrackCallback got_query1_; + TrackCallback got_query2_; + + TrackCallback got_query_canceled0_; + TrackCallback got_query_canceled1_; + TrackCallback got_query_canceled2_; +}; + +} // namespace + +// Test that multiple handlers behave correctly. +TEST(MessageRouterTest, MultiQueryMultiHandler) { + CefRefPtr handler = + new MultiQueryMultiHandlerTestHandler(false, false); + handler->ExecuteTest(); +} + +// Test that multiple handlers behave correctly. Cancel by removing the +// handlers. +TEST(MessageRouterTest, MultiQueryMultiHandlerCancelByRemovingHandler) { + CefRefPtr handler = + new MultiQueryMultiHandlerTestHandler(false, true); + handler->ExecuteTest(); +} + + +namespace { + +// Map of managers on a per-URL basis. +class MultiQueryManagerMap : + public CefMessageRouterBrowserSide::Handler, + public MultiQueryManager::Observer { + public: + class Observer { + public: + // Called when all manual queries are complete. + virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) {} + + // Called when all queries are complete. + virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) {} + protected: + virtual ~Observer() {} + }; + + MultiQueryManagerMap() + : finalized_(false), + running_(false), + manual_complete_count_(0), + total_complete_count_(0) { + } + + virtual ~MultiQueryManagerMap() { + RemoveAllManagers(); + } + + void AddObserver(Observer* observer) { + EXPECT_FALSE(running_); + observer_set_.insert(observer); + } + + void RemoveObserver(Observer* observer) { + EXPECT_FALSE(running_); + EXPECT_TRUE(observer_set_.erase(observer)); + } + + MultiQueryManager* CreateManager(const std::string& url, bool synchronous) { + EXPECT_FALSE(finalized_); + + // The sub-frame resource should not already exist. + URLManagerMap::const_iterator it = manager_map_.find(url); + EXPECT_EQ(it, manager_map_.end()); + + MultiQueryManager* manager = + new MultiQueryManager(url, synchronous, + static_cast(manager_map_.size()) * 1000); + manager->AddObserver(this); + manager_map_.insert(std::make_pair(url, manager)); + + return manager; + } + + void Finalize() { + EXPECT_FALSE(finalized_); + finalized_ = true; + } + + std::string GetMainHTML() const { + EXPECT_TRUE(finalized_); + EXPECT_FALSE(running_); + + std::string html = "\n"; + + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) { + const std::string& name = GetNameForURL(it->first); + html += "\n"; + } + + html += ""; + return html; + } + + void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) { + EXPECT_TRUE(finalized_); + if (!running_) + running_ = true; + + MultiQueryManager* manager = GetManager(browser, frame); + manager->OnNotify(browser, frame, message); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(finalized_); + if (!running_) + running_ = true; + + MultiQueryManager* manager = GetManager(browser, frame); + return manager->OnQuery(browser, frame, query_id, request, persistent, + callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + EXPECT_TRUE(finalized_); + if (!running_) + running_ = true; + + MultiQueryManager* manager = GetManager(browser, frame); + manager->OnQueryCanceled(browser, frame, query_id); + } + + virtual void OnManualQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + const int size = static_cast(manager_map_.size()); + EXPECT_LT(manual_complete_count_, size); + if (++manual_complete_count_ == size) { + running_ = false; + + // Notify observers. + if (!observer_set_.empty()) { + // Use a copy of the set in case an Observer is removed while we're + // iterating. + ObserverSet observer_set = observer_set_; + + ObserverSet::const_iterator it = observer_set.begin(); + for (; it != observer_set.end(); ++it) { + (*it)->OnMapManualQueriesCompleted(this); + } + } + } + } + + virtual void OnAllQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + const int size = static_cast(manager_map_.size()); + EXPECT_LT(total_complete_count_, size); + if (++total_complete_count_ == size) { + running_ = false; + + // Notify observers. + if (!observer_set_.empty()) { + // Use a copy of the set in case an Observer is removed while we're + // iterating. + ObserverSet observer_set = observer_set_; + + ObserverSet::const_iterator it = observer_set.begin(); + for (; it != observer_set.end(); ++it) { + (*it)->OnMapAllQueriesCompleted(this); + } + } + } + } + + bool AllComplete() const { + EXPECT_TRUE(finalized_); + + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) { + if (!it->second->IsAllComplete()) + return false; + } + return true; + } + + void AssertAllComplete() const { + EXPECT_TRUE(finalized_); + EXPECT_FALSE(running_); + + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) + it->second->AssertAllComplete(); + } + + bool HasAutoQueries() const { + if (manager_map_.empty()) + return false; + + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) { + if (it->second->HasAutoQueries()) + return true; + } + + return false; + } + + MultiQueryManager* GetManager(CefRefPtr browser, + CefRefPtr frame) const { + const std::string& url = frame->GetURL(); + URLManagerMap::const_iterator it = manager_map_.find(url); + EXPECT_NE(it, manager_map_.end()); + return it->second; + } + + void RemoveAllManagers() { + if (manager_map_.empty()) + return; + + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) + delete it->second; + manager_map_.clear(); + } + + std::string GetURLForManager(MultiQueryManager* manager) const { + if (!manager_map_.empty()) { + URLManagerMap::const_iterator it = manager_map_.begin(); + for (; it != manager_map_.end(); ++it) { + if (it->second == manager) + return it->first; + } + } + return std::string(); + } + + static std::string GetNameForURL(const std::string& url) { + // Extract the file name without extension. + int pos1 = static_cast(url.rfind("/")); + int pos2 = static_cast(url.rfind(".")); + EXPECT_TRUE(pos1 >= 0 && pos2 >= 0 && pos1 < pos2); + return url.substr(pos1 + 1, pos2 - pos1 - 1); + } + + private: + // Map of page URL to MultiQueryManager instance. + typedef std::map URLManagerMap; + URLManagerMap manager_map_; + + typedef std::set ObserverSet; + ObserverSet observer_set_; + + // Set to true after all query managers have been added. + bool finalized_; + // Set to true while queries are pending. + bool running_; + + // Number of managers that have completed. + int manual_complete_count_; + int total_complete_count_; +}; + +// Test multiple queries in a single page load with multiple frames. +class MultiQueryMultiFrameTestHandler : + public SingleLoadTestHandler, + public MultiQueryManagerMap::Observer { + public: + MultiQueryMultiFrameTestHandler(bool synchronous, bool cancel_with_subnav) + : synchronous_(synchronous), + cancel_with_subnav_(cancel_with_subnav) { + manager_map_.AddObserver(this); + } + + virtual void AddOtherResources() OVERRIDE { + AddSubFrameResource("sub1"); + AddSubFrameResource("sub2"); + AddSubFrameResource("sub3"); + manager_map_.Finalize(); + + if (manager_map_.HasAutoQueries()) { + cancel_url_ = std::string(kTestDomain1) + "cancel.html"; + AddResource(cancel_url_, "cancel", "text/html"); + } + } + + virtual std::string GetMainHTML() OVERRIDE { + return manager_map_.GetMainHTML(); + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + AssertMainBrowser(browser); + EXPECT_FALSE(frame->IsMain()); + + manager_map_.OnNotify(browser, frame, message); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + AssertMainBrowser(browser); + EXPECT_FALSE(frame->IsMain()); + + return manager_map_.OnQuery(browser, frame, query_id, request, persistent, + callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + AssertMainBrowser(browser); + EXPECT_FALSE(frame->IsMain()); + + manager_map_.OnQueryCanceled(browser, frame, query_id); + } + + virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) OVERRIDE { + EXPECT_EQ(map, &manager_map_); + if (manager_map_.HasAutoQueries()) { + CefRefPtr frame = GetBrowser()->GetMainFrame(); + + // Navigate somewhere else to terminate the auto queries. + if (cancel_with_subnav_) { + // Navigate each subframe individually. + const std::string js = + "document.getElementById('sub1').src = '" + cancel_url_ + "';" + "document.getElementById('sub2').src = '" + cancel_url_ + "';" + "document.getElementById('sub3').src = '" + cancel_url_ + "';"; + + frame->ExecuteJavaScript(js, frame->GetURL(), 0); + } else { + // Navigate the main frame. + frame->LoadURL(cancel_url_); + } + } + } + + virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) OVERRIDE { + EXPECT_EQ(map, &manager_map_); + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + manager_map_.AssertAllComplete(); + TestHandler::DestroyTest(); + } + + private: + void AddSubFrameResource(const std::string& name) { + const std::string& url = std::string(kTestDomain1) + name + ".html"; + + MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_); + MakeTestQueries(manager, false, 100); + + const std::string& html = manager->GetHTML(false, false); + AddResource(url, html, "text/html"); + } + + const bool synchronous_; + const bool cancel_with_subnav_; + + MultiQueryManagerMap manager_map_; + + std::string cancel_url_; +}; + +} // namespace + +// Test that multiple frames can run many queries successfully in a synchronous +// manner. +TEST(MessageRouterTest, MultiQueryMultiFrameSync) { + CefRefPtr handler = + new MultiQueryMultiFrameTestHandler(true, false); + handler->ExecuteTest(); +} + +// Test that multiple frames can run many queries successfully in an +// asynchronous manner. +TEST(MessageRouterTest, MultiQueryMultiFrameAsync) { + CefRefPtr handler = + new MultiQueryMultiFrameTestHandler(false, false); + handler->ExecuteTest(); +} + +// Test that multiple frames can run many queries successfully in a synchronous +// manner. Cancel auto queries with sub-frame navigation. +TEST(MessageRouterTest, MultiQueryMultiFrameSyncSubnavCancel) { + CefRefPtr handler = + new MultiQueryMultiFrameTestHandler(true, true); + handler->ExecuteTest(); +} + +// Test that multiple frames can run many queries successfully in an +// asynchronous manner. Cancel auto queries with sub-frame navigation. +TEST(MessageRouterTest, MultiQueryMultiFrameAsyncSubnavCancel) { + CefRefPtr handler = + new MultiQueryMultiFrameTestHandler(false, true); + handler->ExecuteTest(); +} + + +namespace { + +// Implementation of MRTestHandler that loads multiple pages and/or browsers and +// executes multiple queries. +class MultiQueryMultiLoadTestHandler : + public MRTestHandler, + public CefMessageRouterBrowserSide::Handler, + public MultiQueryManagerMap::Observer, + public MultiQueryManager::Observer { + public: + MultiQueryMultiLoadTestHandler(bool some, bool synchronous) + : some_(some), + synchronous_(synchronous) { + manager_map_.AddObserver(this); + } + + virtual void OnNotify(CefRefPtr browser, + CefRefPtr frame, + const std::string& message) OVERRIDE { + manager_map_.OnNotify(browser, frame, message); + } + + virtual bool OnQuery(CefRefPtr browser, + CefRefPtr frame, + int64 query_id, + const CefString& request, + bool persistent, + CefRefPtr callback) OVERRIDE { + return manager_map_.OnQuery(browser, frame, query_id, request, persistent, + callback); + } + + virtual void OnQueryCanceled(CefRefPtr browser, + CefRefPtr frame, + int64 query_id) OVERRIDE { + manager_map_.OnQueryCanceled(browser, frame, query_id); + } + + virtual void OnMapManualQueriesCompleted(MultiQueryManagerMap* map) OVERRIDE { + EXPECT_EQ(map, &manager_map_); + if (manager_map_.HasAutoQueries()) { + // Navigate all browsers somewhere else to terminate the auto queries. + BrowserMap map; + GetAllBrowsers(&map); + + BrowserMap::const_iterator it = map.begin(); + for (; it != map.end(); ++it) { + it->second->GetMainFrame()->LoadURL(cancel_url_); + } + } + } + + virtual void OnMapAllQueriesCompleted(MultiQueryManagerMap* map) OVERRIDE { + EXPECT_EQ(map, &manager_map_); + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + manager_map_.AssertAllComplete(); + TestHandler::DestroyTest(); + } + + protected: + virtual void AddHandlers( + CefRefPtr message_router) OVERRIDE { + message_router->AddHandler(this, false); + } + + void AddManagedResource(const std::string& url, + bool assert_total, + bool assert_browser) { + MultiQueryManager* manager = manager_map_.CreateManager(url, synchronous_); + manager->AddObserver(this); + MakeTestQueries(manager, some_, 75); + + const std::string& html = manager->GetHTML(assert_total, assert_browser); + AddResource(url, html, "text/html"); + } + + void Finalize() { + manager_map_.Finalize(); + + if (manager_map_.HasAutoQueries()) { + cancel_url_ = std::string(kTestDomain1) + "cancel.html"; + AddResource(cancel_url_, "cancel", "text/html"); + } + } + + MultiQueryManagerMap manager_map_; + + private: + const bool some_; + const bool synchronous_; + + std::string cancel_url_; +}; + +// Test multiple browsers that send queries at the same time. +class MultiQueryMultiBrowserTestHandler : public MultiQueryMultiLoadTestHandler { + public: + MultiQueryMultiBrowserTestHandler(bool synchronous, bool same_origin) + : MultiQueryMultiLoadTestHandler(false, synchronous), + same_origin_(same_origin) { + } + + protected: + virtual void RunMRTest() { + const std::string& url1 = std::string(kTestDomain1) + "browser1.html"; + const std::string& url2 = + std::string(same_origin_ ? kTestDomain1 : kTestDomain2) + + "browser2.html"; + const std::string& url3 = + std::string(same_origin_ ? kTestDomain1 : kTestDomain3) + + "browser3.html"; + + AddManagedResource(url1, false, true); + AddManagedResource(url2, false, true); + AddManagedResource(url3, false, true); + Finalize(); + + // Create 2 browsers simultaniously. + CreateBrowser(url1, NULL); + CreateBrowser(url2, NULL); + CreateBrowser(url3, NULL); + } + + private: + bool same_origin_; +}; + +} // namespace + +// Test that multiple browsers can query simultaniously from the same origin. +TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginSync) { + CefRefPtr handler = + new MultiQueryMultiBrowserTestHandler(true, true); + handler->ExecuteTest(); +} + +// Test that multiple browsers can query simultaniously from the same origin. +TEST(MessageRouterTest, MultiQueryMultiBrowserSameOriginAsync) { + CefRefPtr handler = + new MultiQueryMultiBrowserTestHandler(false, true); + handler->ExecuteTest(); +} + +// Test that multiple browsers can query simultaniously from different origins. +TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginSync) { + CefRefPtr handler = + new MultiQueryMultiBrowserTestHandler(true, false); + handler->ExecuteTest(); +} + +// Test that multiple browsers can query simultaniously from different origins. +TEST(MessageRouterTest, MultiQueryMultiBrowserDifferentOriginAsync) { + CefRefPtr handler = + new MultiQueryMultiBrowserTestHandler(false, false); + handler->ExecuteTest(); +} + + +namespace { + +// Test multiple navigations that send queries sequentially. +class MultiQueryMultiNavigateTestHandler : public MultiQueryMultiLoadTestHandler { + public: + MultiQueryMultiNavigateTestHandler(bool synchronous, bool same_origin) + : MultiQueryMultiLoadTestHandler(false, synchronous), + same_origin_(same_origin) { + } + + virtual void OnManualQueriesCompleted(MultiQueryManager* manager) OVERRIDE { + const std::string& url = manager_map_.GetURLForManager(manager); + if (url == url1_) // 2. Load the 2nd url. + GetBrowser()->GetMainFrame()->LoadURL(url2_); + else if (url == url2_) // 3. Load the 3rd url. + GetBrowser()->GetMainFrame()->LoadURL(url3_); + } + + protected: + virtual void RunMRTest() { + url1_ = std::string(kTestDomain1) + "browser1.html"; + url2_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain2) + + "browser2.html"; + url3_ = std::string(same_origin_ ? kTestDomain1 : kTestDomain3) + + "browser3.html"; + + AddManagedResource(url1_, true, true); + AddManagedResource(url2_, true, true); + AddManagedResource(url3_, true, true); + Finalize(); + + // 1. Load the 1st url. + CreateBrowser(url1_, NULL); + } + + private: + bool same_origin_; + + std::string url1_; + std::string url2_; + std::string url3_; +}; + +} // namespace + +// Test that multiple navigations can query from the same origin. +TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginSync) { + CefRefPtr handler = + new MultiQueryMultiNavigateTestHandler(true, true); + handler->ExecuteTest(); +} + +// Test that multiple navigations can query from the same origin. +TEST(MessageRouterTest, MultiQueryMultiNavigateSameOriginAsync) { + CefRefPtr handler = + new MultiQueryMultiNavigateTestHandler(false, true); + handler->ExecuteTest(); +} + +// Test that multiple navigations can query from different origins. +TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginSync) { + CefRefPtr handler = + new MultiQueryMultiNavigateTestHandler(true, false); + handler->ExecuteTest(); +} + +// Test that multiple navigations can query from different origins. +TEST(MessageRouterTest, MultiQueryMultiNavigateDifferentOriginAsync) { + CefRefPtr handler = + new MultiQueryMultiNavigateTestHandler(false, false); + handler->ExecuteTest(); +} diff --git a/tests/unittests/navigation_unittest.cc b/tests/unittests/navigation_unittest.cc new file mode 100644 index 000000000..9a7467d6f --- /dev/null +++ b/tests/unittests/navigation_unittest.cc @@ -0,0 +1,2090 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include +#include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/base/cef_bind.h" +#include "include/cef_callback.h" +#include "include/cef_scheme.h" +#include "include/wrapper/cef_closure_task.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/cefclient/client_app.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_util.h" + +namespace { + +const char kHNav1[] = "http://tests-hnav/nav1.html"; +const char kHNav2[] = "http://tests-hnav/nav2.html"; +const char kHNav3[] = "http://tests-hnav/nav3.html"; +const char kHistoryNavMsg[] = "NavigationTest.HistoryNav"; + +enum NavAction { + NA_LOAD = 1, + NA_BACK, + NA_FORWARD, + NA_CLEAR +}; + +typedef struct { + NavAction action; // What to do + const char* target; // Where to be after navigation + bool can_go_back; // After navigation, can go back? + bool can_go_forward; // After navigation, can go forward? +} NavListItem; + +// Array of navigation actions: X = current page, . = history exists +static NavListItem kHNavList[] = { + // kHNav1 | kHNav2 | kHNav3 + {NA_LOAD, kHNav1, false, false}, // X + {NA_LOAD, kHNav2, true, false}, // . X + {NA_BACK, kHNav1, false, true}, // X . + {NA_FORWARD, kHNav2, true, false}, // . X + {NA_LOAD, kHNav3, true, false}, // . . X + {NA_BACK, kHNav2, true, true}, // . X . + // TODO(cef): Enable once ClearHistory is implemented + // {NA_CLEAR, kHNav2, false, false}, // X +}; + +#define NAV_LIST_SIZE() (sizeof(kHNavList) / sizeof(NavListItem)) + +bool g_history_nav_test = false; + +// Browser side. +class HistoryNavBrowserTest : public ClientApp::BrowserDelegate { + public: + HistoryNavBrowserTest() {} + + virtual void OnBeforeChildProcessLaunch( + CefRefPtr app, + CefRefPtr command_line) OVERRIDE { + if (!g_history_nav_test) + return; + + // Indicate to the render process that the test should be run. + command_line->AppendSwitchWithValue("test", kHistoryNavMsg); + } + + protected: + IMPLEMENT_REFCOUNTING(HistoryNavBrowserTest); +}; + +// Renderer side. +class HistoryNavRendererTest : public ClientApp::RenderDelegate, + public CefLoadHandler { + public: + HistoryNavRendererTest() + : run_test_(false), + nav_(0) {} + + virtual void OnRenderThreadCreated( + CefRefPtr app, + CefRefPtr extra_info) OVERRIDE { + if (!g_history_nav_test) { + // Check that the test should be run. + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); + const std::string& test = command_line->GetSwitchValue("test"); + if (test != kHistoryNavMsg) + return; + } + + run_test_ = true; + } + + virtual CefRefPtr GetLoadHandler( + CefRefPtr app) OVERRIDE { + if (!run_test_) + return NULL; + + return this; + } + + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + const std::string& url = browser->GetMainFrame()->GetURL(); + if (isLoading) { + got_loading_state_start_.yes(); + + EXPECT_STRNE(item.target, url.c_str()); + + if (nav_ > 0) { + const NavListItem& last_item = kHNavList[nav_ - 1]; + EXPECT_EQ(last_item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(last_item.can_go_back, canGoBack); + EXPECT_EQ(last_item.can_go_forward, browser->CanGoForward()); + EXPECT_EQ(last_item.can_go_forward, canGoForward); + } else { + EXPECT_FALSE(browser->CanGoBack()); + EXPECT_FALSE(canGoBack); + EXPECT_FALSE(browser->CanGoForward()); + EXPECT_FALSE(canGoForward); + } + } else { + got_loading_state_end_.yes(); + + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_back, canGoBack); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + EXPECT_EQ(item.can_go_forward, canGoForward); + + SendTestResultsIfDone(browser); + } + } + + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_load_start_.yes(); + + const std::string& url = frame->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_load_end_.yes(); + + const std::string& url = frame->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + + SendTestResultsIfDone(browser); + } + + virtual bool OnBeforeNavigation(CefRefPtr app, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + cef_navigation_type_t navigation_type, + bool is_redirect) OVERRIDE { + if (!run_test_) + return false; + + const NavListItem& item = kHNavList[nav_]; + + std::string url = request->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(RT_SUB_RESOURCE, request->GetResourceType()); + EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType()); + + if (item.action == NA_LOAD) + EXPECT_EQ(NAVIGATION_OTHER, navigation_type); + else if (item.action == NA_BACK || item.action == NA_FORWARD) + EXPECT_EQ(NAVIGATION_BACK_FORWARD, navigation_type); + + if (nav_ > 0) { + const NavListItem& last_item = kHNavList[nav_ - 1]; + EXPECT_EQ(last_item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(last_item.can_go_forward, browser->CanGoForward()); + } else { + EXPECT_FALSE(browser->CanGoBack()); + EXPECT_FALSE(browser->CanGoForward()); + } + + return false; + } + + protected: + void SendTestResultsIfDone(CefRefPtr browser) { + if (got_load_end_ && got_loading_state_end_) + SendTestResults(browser); + } + + // Send the test results. + void SendTestResults(CefRefPtr browser) { + EXPECT_TRUE(got_loading_state_start_); + EXPECT_TRUE(got_loading_state_end_); + EXPECT_TRUE(got_load_start_); + EXPECT_TRUE(got_load_end_); + + // Check if the test has failed. + bool result = !TestFailed(); + + // Return the result to the browser process. + CefRefPtr return_msg = + CefProcessMessage::Create(kHistoryNavMsg); + CefRefPtr args = return_msg->GetArgumentList(); + EXPECT_TRUE(args.get()); + EXPECT_TRUE(args->SetInt(0, nav_)); + EXPECT_TRUE(args->SetBool(1, result)); + EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + + // Reset the test results for the next navigation. + got_loading_state_start_.reset(); + got_loading_state_end_.reset(); + got_load_start_.reset(); + got_load_end_.reset(); + + nav_++; + } + + bool run_test_; + int nav_; + + TrackCallback got_loading_state_start_; + TrackCallback got_loading_state_end_; + TrackCallback got_load_start_; + TrackCallback got_load_end_; + + IMPLEMENT_REFCOUNTING(HistoryNavRendererTest); +}; + +// Browser side. +class HistoryNavTestHandler : public TestHandler { + public: + HistoryNavTestHandler() + : nav_(0), + load_end_confirmation_(false), + renderer_confirmation_(false) {} + + virtual void RunTest() OVERRIDE { + // Add the resources that we will navigate to/from. + AddResource(kHNav1, "Nav1", "text/html"); + AddResource(kHNav2, "Nav2", "text/html"); + AddResource(kHNav3, "Nav3", "text/html"); + + // Create the browser. + CreateBrowser(CefString()); + } + + void RunNav(CefRefPtr browser) { + if (nav_ == NAV_LIST_SIZE()) { + // End of the nav list. + DestroyTest(); + return; + } + + const NavListItem& item = kHNavList[nav_]; + + // Perform the action. + switch (item.action) { + case NA_LOAD: + browser->GetMainFrame()->LoadURL(item.target); + break; + case NA_BACK: + browser->GoBack(); + break; + case NA_FORWARD: + browser->GoForward(); + break; + case NA_CLEAR: + // TODO(cef): Enable once ClearHistory is implemented + // browser->GetHost()->ClearHistory(); + // Not really a navigation action so go to the next one. + nav_++; + RunNav(browser); + break; + default: + break; + } + } + + void RunNextNavIfReady(CefRefPtr browser) { + if (load_end_confirmation_ && renderer_confirmation_) { + load_end_confirmation_ = false; + renderer_confirmation_ = false; + nav_++; + RunNav(browser); + } + } + + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE { + TestHandler::OnAfterCreated(browser); + + RunNav(browser); + } + + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_before_browse_[nav_].yes(); + + std::string url = request->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType()); + if (item.action == NA_LOAD) + EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType()); + else if (item.action == NA_BACK || item.action == NA_FORWARD) + EXPECT_EQ(TT_EXPLICIT | TT_FORWARD_BACK_FLAG, request->GetTransitionType()); + + if (nav_ > 0) { + const NavListItem& last_item = kHNavList[nav_ - 1]; + EXPECT_EQ(last_item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(last_item.can_go_forward, browser->CanGoForward()); + } else { + EXPECT_FALSE(browser->CanGoBack()); + EXPECT_FALSE(browser->CanGoForward()); + } + + return false; + } + + virtual bool OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType()); + if (item.action == NA_LOAD) + EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType()); + else if (item.action == NA_BACK || item.action == NA_FORWARD) + EXPECT_EQ(TT_EXPLICIT | TT_FORWARD_BACK_FLAG, request->GetTransitionType()); + + got_before_resource_load_[nav_].yes(); + + std::string url = request->GetURL(); + if (url == item.target) + got_correct_target_[nav_].yes(); + + return false; + } + + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_loading_state_change_[nav_].yes(); + + if (item.can_go_back == canGoBack) + got_correct_can_go_back_[nav_].yes(); + if (item.can_go_forward == canGoForward) + got_correct_can_go_forward_[nav_].yes(); + } + + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { + if(browser->IsPopup() || !frame->IsMain()) + return; + + const NavListItem& item = kHNavList[nav_]; + + got_load_start_[nav_].yes(); + + std::string url1 = browser->GetMainFrame()->GetURL(); + std::string url2 = frame->GetURL(); + if (url1 == item.target && url2 == item.target) + got_correct_load_start_url_[nav_].yes(); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + if (browser->IsPopup() || !frame->IsMain()) + return; + + const NavListItem& item = kHNavList[nav_]; + + got_load_end_[nav_].yes(); + + std::string url1 = browser->GetMainFrame()->GetURL(); + std::string url2 = frame->GetURL(); + if (url1 == item.target && url2 == item.target) + got_correct_load_end_url_[nav_].yes(); + + if (item.can_go_back == browser->CanGoBack()) + got_correct_can_go_back2_[nav_].yes(); + if (item.can_go_forward == browser->CanGoForward()) + got_correct_can_go_forward2_[nav_].yes(); + + load_end_confirmation_ = true; + RunNextNavIfReady(browser); + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + if (message->GetName().ToString() == kHistoryNavMsg) { + got_before_navigation_[nav_].yes(); + + // Test that the renderer side succeeded. + CefRefPtr args = message->GetArgumentList(); + EXPECT_TRUE(args.get()); + EXPECT_EQ(nav_, args->GetInt(0)); + EXPECT_TRUE(args->GetBool(1)); + + renderer_confirmation_ = true; + RunNextNavIfReady(browser); + return true; + } + + // Message not handled. + return false; + } + + int nav_; + bool load_end_confirmation_; + bool renderer_confirmation_; + + TrackCallback got_before_browse_[NAV_LIST_SIZE()]; + TrackCallback got_before_navigation_[NAV_LIST_SIZE()]; + TrackCallback got_before_resource_load_[NAV_LIST_SIZE()]; + TrackCallback got_correct_target_[NAV_LIST_SIZE()]; + TrackCallback got_loading_state_change_[NAV_LIST_SIZE()]; + TrackCallback got_correct_can_go_back_[NAV_LIST_SIZE()]; + TrackCallback got_correct_can_go_forward_[NAV_LIST_SIZE()]; + TrackCallback got_load_start_[NAV_LIST_SIZE()]; + TrackCallback got_correct_load_start_url_[NAV_LIST_SIZE()]; + TrackCallback got_load_end_[NAV_LIST_SIZE()]; + TrackCallback got_correct_load_end_url_[NAV_LIST_SIZE()]; + TrackCallback got_correct_can_go_back2_[NAV_LIST_SIZE()]; + TrackCallback got_correct_can_go_forward2_[NAV_LIST_SIZE()]; +}; + +} // namespace + +// Verify history navigation. +TEST(NavigationTest, History) { + g_history_nav_test = true; + CefRefPtr handler = + new HistoryNavTestHandler(); + handler->ExecuteTest(); + g_history_nav_test = false; + + for (size_t i = 0; i < NAV_LIST_SIZE(); ++i) { + if (kHNavList[i].action != NA_CLEAR) { + ASSERT_TRUE(handler->got_before_browse_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_before_navigation_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_before_resource_load_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_target_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_load_start_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_load_start_url_[i]) << "i = " << i; + } + + ASSERT_TRUE(handler->got_loading_state_change_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_can_go_back_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_can_go_forward_[i]) << "i = " << i; + + if (kHNavList[i].action != NA_CLEAR) { + ASSERT_TRUE(handler->got_load_end_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_load_end_url_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_can_go_back2_[i]) << "i = " << i; + ASSERT_TRUE(handler->got_correct_can_go_forward2_[i]) << "i = " << i; + } + } +} + + +namespace { + +const char kFNav1[] = "http://tests/nav1.html"; +const char kFNav2[] = "http://tests/nav2.html"; +const char kFNav3[] = "http://tests/nav3.html"; + +class FrameNameIdentNavTestHandler : public TestHandler { + public: + FrameNameIdentNavTestHandler() : browse_ct_(0) {} + + virtual void RunTest() OVERRIDE { + // Add the frame resources. + std::stringstream ss; + + // Page with named frame + ss << "Nav1" + "" + "", + "text/html"); + AddResource(std::string(kTypeTestOrigin) + "sub.html", + "Sub", + "text/html"); + AddResource(std::string(kTypeTestOrigin) + "style.css", + "@font-face {" + " font-family: custom_font;" + " src: url('font.ttf');" + "}" + "p {" + " font-family: custom_font;" + "}", + "text/css"); + AddResource(std::string(kTypeTestOrigin) + "script.js", + "", + "text/javascript"); + AddResource(std::string(kTypeTestOrigin) + "image.png", + "", + "image/png"); + AddResource(std::string(kTypeTestOrigin) + "font.ttf", + "", + "font/ttf"); + AddResource(std::string(kTypeTestOrigin) + "xhr.html", + "XHR", + "text/html"); + + CreateBrowser(std::string(kTypeTestOrigin) + "main.html"); + + // Time out the test after a reasonable period of time. + CefPostDelayedTask(TID_UI, base::Bind(&TypeTestHandler::DestroyTest, this), + 2000); + } + + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) OVERRIDE { + browse_expectations_.GotRequest(request); + + return false; + } + + virtual bool OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) OVERRIDE { + load_expectations_.GotRequest(request); + + return false; + } + + virtual CefRefPtr GetResourceHandler( + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) OVERRIDE { + if (get_expectations_.GotRequest(request) && + get_expectations_.IsDone(false)) { + completed_browser_side_ = true; + // Destroy the test on the UI thread. + CefPostTask(TID_UI, + base::Bind(&TypeTestHandler::DestroyTestIfComplete, this)); + } + + return TestHandler::GetResourceHandler(browser, frame, request); + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + const std::string& msg_name = message->GetName(); + if (msg_name == kTypeTestCompleteMsg) { + // Test that the renderer side succeeded. + CefRefPtr args = message->GetArgumentList(); + EXPECT_TRUE(args.get()); + EXPECT_TRUE(args->GetBool(0)); + + completed_render_side_ = true; + DestroyTestIfComplete(); + return true; + } + + // Message not handled. + return false; + } + + private: + void DestroyTestIfComplete() { + if (destroyed_) + return; + + if (completed_browser_side_ && completed_render_side_) + DestroyTest(); + } + + virtual void DestroyTest() OVERRIDE { + if (destroyed_) + return; + destroyed_ = true; + + // Verify test expectations. + EXPECT_TRUE(completed_browser_side_); + EXPECT_TRUE(completed_render_side_); + EXPECT_TRUE(browse_expectations_.IsDone(true)); + EXPECT_TRUE(load_expectations_.IsDone(true)); + EXPECT_TRUE(get_expectations_.IsDone(true)); + + TestHandler::DestroyTest(); + } + + TypeExpectations browse_expectations_; + TypeExpectations load_expectations_; + TypeExpectations get_expectations_; + + bool completed_browser_side_; + bool completed_render_side_; + bool destroyed_; +}; + +} // namespace + +// Verify the order of navigation-related callbacks. +TEST(RequestTest, ResourceAndTransitionType) { + CefRefPtr handler = + new TypeTestHandler(); + handler->ExecuteTest(); +} + + +// Entry point for creating request renderer test objects. +// Called from client_app_delegates.cc. +void CreateRequestRendererTests(ClientApp::RenderDelegateSet& delegates) { + delegates.insert(new TypeRendererTest); +} diff --git a/tests/unittests/routing_test_handler.cc b/tests/unittests/routing_test_handler.cc new file mode 100644 index 000000000..903a5698c --- /dev/null +++ b/tests/unittests/routing_test_handler.cc @@ -0,0 +1,107 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "tests/unittests/routing_test_handler.h" +#include "tests/cefclient/client_app.h" + +namespace { + +void SetRouterConfig(CefMessageRouterConfig& config) { + config.js_query_function = "testQuery"; + config.js_cancel_function = "testQueryCancel"; +} + +// Handle the renderer side of the routing implementation. +class RoutingRenderDelegate : public ClientApp::RenderDelegate { + public: + RoutingRenderDelegate() {} + + virtual void OnWebKitInitialized(CefRefPtr app) OVERRIDE { + // Create the renderer-side router for query handling. + CefMessageRouterConfig config; + SetRouterConfig(config); + message_router_ = CefMessageRouterRendererSide::Create(config); + } + + virtual void OnContextCreated(CefRefPtr app, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + message_router_->OnContextCreated(browser, frame, context); + } + + virtual void OnContextReleased(CefRefPtr app, + CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { + message_router_->OnContextReleased(browser, frame, context); + } + + virtual bool OnProcessMessageReceived( + CefRefPtr app, + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + return message_router_->OnProcessMessageReceived( + browser, source_process, message); + } + + private: + CefRefPtr message_router_; + + IMPLEMENT_REFCOUNTING(RoutingRenderDelegate); +}; + +} // namespace + +RoutingTestHandler::RoutingTestHandler() { +} + +void RoutingTestHandler::OnAfterCreated(CefRefPtr browser) { + if (!message_router_) { + // Create the browser-side router for query handling. + CefMessageRouterConfig config; + SetRouterConfig(config); + message_router_ = CefMessageRouterBrowserSide::Create(config); + message_router_->AddHandler(this, false); + } + TestHandler::OnAfterCreated(browser); +} + +void RoutingTestHandler::OnBeforeClose(CefRefPtr browser) { + message_router_->OnBeforeClose(browser); + TestHandler::OnBeforeClose(browser); +} + +void RoutingTestHandler::OnRenderProcessTerminated( + CefRefPtr browser, + TerminationStatus status) { + message_router_->OnRenderProcessTerminated(browser); +} + +bool RoutingTestHandler::OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) { + message_router_->OnBeforeBrowse(browser, frame); + return false; +} + +bool RoutingTestHandler::OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) { + return message_router_->OnProcessMessageReceived( + browser, source_process, message); +} + +// Entry point for creating the test delegate. +// Called from client_app_delegates.cc. +void CreateRoutingTestHandlerDelegate( + ClientApp::RenderDelegateSet& delegates) { + delegates.insert(new RoutingRenderDelegate); +} diff --git a/tests/unittests/routing_test_handler.h b/tests/unittests/routing_test_handler.h new file mode 100644 index 000000000..67dd9906e --- /dev/null +++ b/tests/unittests/routing_test_handler.h @@ -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_UNITTESTS_ROUTING_TEST_HANDLER_H_ +#define CEF_TESTS_UNITTESTS_ROUTING_TEST_HANDLER_H_ +#pragma once + +#include "include/wrapper/cef_message_router.h" +#include "tests/unittests/test_handler.h" + +// Extends TestHandler to provide message routing functionality. The +// RoutingTestHandler implementation must be called from subclass +// overrides unless otherwise indicated. +class RoutingTestHandler : + public TestHandler, + public CefMessageRouterBrowserSide::Handler { + public: + RoutingTestHandler(); + + virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; + virtual void OnRenderProcessTerminated( + CefRefPtr browser, + TerminationStatus status) OVERRIDE; + + // Only call this method if the navigation isn't canceled. + virtual bool OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + bool is_redirect) OVERRIDE; + + // Returns true if the router handled the navigation. + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE; + + private: + CefRefPtr message_router_; +}; + + +#endif // CEF_TESTS_UNITTESTS_ROUTING_TEST_HANDLER_H_ diff --git a/tests/unittests/run_all_unittests.cc b/tests/unittests/run_all_unittests.cc new file mode 100644 index 000000000..acbbff030 --- /dev/null +++ b/tests/unittests/run_all_unittests.cc @@ -0,0 +1,147 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "base/threading/thread.h" + +#include "include/base/cef_bind.h" +#include "include/cef_app.h" +#include "include/cef_task.h" +#include "include/wrapper/cef_helpers.h" +#include "include/wrapper/cef_closure_task.h" +#include "tests/cefclient/client_app.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_suite.h" + +#if defined(OS_WIN) +#include "include/cef_sandbox_win.h" +#endif + +namespace { + +// Thread used to run the test suite. +class CefTestThread : public base::Thread { + public: + explicit CefTestThread(CefTestSuite* test_suite) + : base::Thread("test_thread"), + test_suite_(test_suite) { + } + + void RunTests() { + // Run the test suite. + retval_ = test_suite_->Run(); + + // Wait for all browsers to exit. + while (TestHandler::HasBrowser()) + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); + + // Quit the CEF message loop. + CefPostTask(TID_UI, base::Bind(&CefQuitMessageLoop)); + } + + int retval() { return retval_; } + + protected: + CefTestSuite* test_suite_; + int retval_; +}; + +// Called on the UI thread. +void RunTests(CefTestThread* thread) { + // Run the test suite on the test thread. + thread->message_loop()->PostTask(FROM_HERE, + base::Bind(&CefTestThread::RunTests, base::Unretained(thread))); +} + +} // namespace + + +int main(int argc, char* argv[]) { +#if defined(OS_LINUX) + // 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(); +#else + char** argv_copy = argv; +#endif + +#if defined(OS_WIN) + CefMainArgs main_args(::GetModuleHandle(NULL)); +#else + CefMainArgs main_args(argc, argv); +#endif + + void* windows_sandbox_info = NULL; + +#if defined(OS_WIN) + // Manages the life span of the sandbox information object. + CefScopedSandboxInfo scoped_sandbox; + windows_sandbox_info = scoped_sandbox.sandbox_info(); +#endif + + CefRefPtr app(new ClientApp); + + // Execute the secondary process, if any. + int exit_code = CefExecuteProcess(main_args, app, windows_sandbox_info); + if (exit_code >= 0) + return exit_code; + + // Initialize the CommandLine object. + CefTestSuite::InitCommandLine(argc, argv_copy); + + CefSettings settings; + CefTestSuite::GetSettings(settings); + +#if defined(OS_MACOSX) + // Platform-specific initialization. + extern void PlatformInit(); + PlatformInit(); +#endif + + // Initialize CEF. + CefInitialize(main_args, settings, app, windows_sandbox_info); + + // Create the test suite object. TestSuite will modify |argv_copy|. + CefTestSuite test_suite(argc, argv_copy); + + int retval; + + if (settings.multi_threaded_message_loop) { + // Run the test suite on the main thread. + retval = test_suite.Run(); + } else { + // Create the test thread. + scoped_ptr thread; + thread.reset(new CefTestThread(&test_suite)); + if (!thread->Start()) + return 1; + + // Start the tests from the UI thread so that any pending UI tasks get a + // chance to execute first. + CefPostTask(TID_UI, base::Bind(&RunTests, thread.get())); + + // Run the CEF message loop. + CefRunMessageLoop(); + + // The test suite has completed. + retval = thread->retval(); + + // Terminate the test thread. + thread.reset(); + } + + // Shut down CEF. + CefShutdown(); + +#if defined(OS_MACOSX) + // Platform-specific cleanup. + extern void PlatformCleanup(); + PlatformCleanup(); +#endif + + return retval; +} diff --git a/tests/unittests/run_all_unittests_mac.mm b/tests/unittests/run_all_unittests_mac.mm new file mode 100644 index 000000000..2b81f5f43 --- /dev/null +++ b/tests/unittests/run_all_unittests_mac.mm @@ -0,0 +1,48 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_app.h" +#import "include/cef_application_mac.h" + +// Memory AutoRelease pool. +static NSAutoreleasePool* g_autopool = nil; + +// Provide the CefAppProtocol implementation required by CEF. +@interface TestApplication : NSApplication { +@private + BOOL handlingSendEvent_; +} +@end + +@implementation TestApplication +- (BOOL)isHandlingSendEvent { + return handlingSendEvent_; +} + +- (void)setHandlingSendEvent:(BOOL)handlingSendEvent { + handlingSendEvent_ = handlingSendEvent; +} + +- (void)sendEvent:(NSEvent*)event { + CefScopedSendingEvent sendingEventScoper; + [super sendEvent:event]; +} +@end + +void PlatformInit() { + // Initialize the AutoRelease pool. + g_autopool = [[NSAutoreleasePool alloc] init]; + + // Initialize the TestApplication instance. + [TestApplication sharedApplication]; +} + +void PlatformCleanup() { + // Release the AutoRelease pool. + [g_autopool release]; +} + diff --git a/tests/unittests/scheme_handler_unittest.cc b/tests/unittests/scheme_handler_unittest.cc new file mode 100644 index 000000000..c471ba21b --- /dev/null +++ b/tests/unittests/scheme_handler_unittest.cc @@ -0,0 +1,1530 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/base/cef_bind.h" +#include "include/cef_origin_whitelist.h" +#include "include/cef_callback.h" +#include "include/cef_scheme.h" +#include "include/wrapper/cef_closure_task.h" +#include "tests/unittests/test_handler.h" + +namespace { + +class TestResults { + public: + TestResults() + : status_code(0), + sub_status_code(0), + delay(0) { + } + + void reset() { + url.clear(); + html.clear(); + status_code = 0; + redirect_url.clear(); + sub_url.clear(); + sub_html.clear(); + sub_status_code = 0; + sub_allow_origin.clear(); + exit_url.clear(); + delay = 0; + got_request.reset(); + got_read.reset(); + got_output.reset(); + got_redirect.reset(); + got_error.reset(); + got_sub_request.reset(); + got_sub_read.reset(); + got_sub_success.reset(); + } + + std::string url; + std::string html; + int status_code; + + // Used for testing redirects + std::string redirect_url; + + // Used for testing XHR requests + std::string sub_url; + std::string sub_html; + int sub_status_code; + std::string sub_allow_origin; + std::string sub_redirect_url; + std::string exit_url; + + // Delay for returning scheme handler results. + int delay; + + TrackCallback + got_request, + got_read, + got_output, + got_redirect, + got_error, + got_sub_redirect, + got_sub_request, + got_sub_read, + got_sub_success; +}; + +// Current scheme handler object. Used when destroying the test from +// ClientSchemeHandler::ProcessRequest(). +class TestSchemeHandler; +TestSchemeHandler* g_current_handler = NULL; + +class TestSchemeHandler : public TestHandler { + public: + explicit TestSchemeHandler(TestResults* tr) + : test_results_(tr) { + g_current_handler = this; + } + + virtual void RunTest() OVERRIDE { + CreateBrowser(test_results_->url); + } + + // Necessary to make the method public in order to destroy the test from + // ClientSchemeHandler::ProcessRequest(). + void DestroyTest() { + TestHandler::DestroyTest(); + } + + virtual bool OnBeforeResourceLoad(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request) OVERRIDE { + std::string newUrl = request->GetURL(); + if (!test_results_->exit_url.empty() && + newUrl.find(test_results_->exit_url) != std::string::npos) { + // XHR tests use an exit URL to destroy the test. + if (newUrl.find("SUCCESS") != std::string::npos) + test_results_->got_sub_success.yes(); + DestroyTest(); + return true; + } + + if (!test_results_->sub_redirect_url.empty() && + newUrl == test_results_->sub_redirect_url) { + test_results_->got_sub_redirect.yes(); + // Redirect to the sub URL. + request->SetURL(test_results_->sub_url); + } else if (newUrl == test_results_->redirect_url) { + test_results_->got_redirect.yes(); + + // No read should have occurred for the redirect. + EXPECT_TRUE(test_results_->got_request); + EXPECT_FALSE(test_results_->got_read); + + // Now loading the redirect URL. + test_results_->url = test_results_->redirect_url; + test_results_->redirect_url.clear(); + } + + return false; + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url == test_results_->url || test_results_->status_code != 200) { + test_results_->got_output.yes(); + + // Test that the status code is correct. + EXPECT_EQ(httpStatusCode, test_results_->status_code); + + if (test_results_->sub_url.empty()) + DestroyTest(); + } + } + + virtual void OnLoadError(CefRefPtr browser, + CefRefPtr frame, + ErrorCode errorCode, + const CefString& errorText, + const CefString& failedUrl) OVERRIDE { + test_results_->got_error.yes(); + DestroyTest(); + } + + protected: + TestResults* test_results_; +}; + +class ClientSchemeHandler : public CefResourceHandler { + public: + explicit ClientSchemeHandler(TestResults* tr) + : test_results_(tr), + offset_(0), + is_sub_(false), + has_delayed_(false) { + } + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + + bool handled = false; + + std::string url = request->GetURL(); + is_sub_ = (!test_results_->sub_url.empty() && + test_results_->sub_url == url); + + if (is_sub_) { + test_results_->got_sub_request.yes(); + + if (!test_results_->sub_html.empty()) + handled = true; + } else { + EXPECT_EQ(url, test_results_->url); + + test_results_->got_request.yes(); + + if (!test_results_->html.empty()) + handled = true; + } + + if (handled) { + if (test_results_->delay > 0) { + // Continue after the delay. + CefPostDelayedTask(TID_IO, + base::Bind(&CefCallback::Continue, callback), + test_results_->delay); + } else { + // Continue immediately. + callback->Continue(); + } + return true; + } + + // Response was canceled. + if (g_current_handler) + g_current_handler->DestroyTest(); + return false; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + if (is_sub_) { + response->SetStatus(test_results_->sub_status_code); + + if (!test_results_->sub_allow_origin.empty()) { + // Set the Access-Control-Allow-Origin header to allow cross-domain + // scripting. + CefResponse::HeaderMap headers; + headers.insert(std::make_pair("Access-Control-Allow-Origin", + test_results_->sub_allow_origin)); + response->SetHeaderMap(headers); + } + + if (!test_results_->sub_html.empty()) { + response->SetMimeType("text/html"); + response_length = test_results_->sub_html.size(); + } + } else if (!test_results_->redirect_url.empty()) { + redirectUrl = test_results_->redirect_url; + } else { + response->SetStatus(test_results_->status_code); + + if (!test_results_->html.empty()) { + response->SetMimeType("text/html"); + response_length = test_results_->html.size(); + } + } + } + + virtual void Cancel() OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + + if (test_results_->delay > 0) { + if (!has_delayed_) { + // Continue after a delay. + CefPostDelayedTask(TID_IO, + base::Bind(&ClientSchemeHandler::ContinueAfterDelay, + this, callback), + test_results_->delay); + bytes_read = 0; + return true; + } + + has_delayed_ = false; + } + + std::string* data; + + if (is_sub_) { + test_results_->got_sub_read.yes(); + data = &test_results_->sub_html; + } else { + test_results_->got_read.yes(); + data = &test_results_->html; + } + + bool has_data = false; + bytes_read = 0; + + size_t size = data->size(); + if (offset_ < size) { + int transfer_size = + std::min(bytes_to_read, static_cast(size - offset_)); + memcpy(data_out, data->c_str() + offset_, transfer_size); + offset_ += transfer_size; + + bytes_read = transfer_size; + has_data = true; + } + + return has_data; + } + + private: + void ContinueAfterDelay(CefRefPtr callback) { + has_delayed_ = true; + callback->Continue(); + } + + TestResults* test_results_; + size_t offset_; + bool is_sub_; + bool has_delayed_; + + IMPLEMENT_REFCOUNTING(ClientSchemeHandler); +}; + +class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + explicit ClientSchemeHandlerFactory(TestResults* tr) + : test_results_(tr) { + } + + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) + OVERRIDE { + EXPECT_TRUE(CefCurrentlyOn(TID_IO)); + return new ClientSchemeHandler(test_results_); + } + + TestResults* test_results_; + + IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); +}; + +// Global test results object. +TestResults g_TestResults; + +// If |domain| is empty the scheme will be registered as non-standard. +void RegisterTestScheme(const std::string& scheme, const std::string& domain) { + g_TestResults.reset(); + + EXPECT_TRUE(CefRegisterSchemeHandlerFactory(scheme, domain, + new ClientSchemeHandlerFactory(&g_TestResults))); + WaitForIOThread(); +} + +void ClearTestSchemes() { + EXPECT_TRUE(CefClearSchemeHandlerFactories()); + WaitForIOThread(); +} + +struct XHRTestSettings { + XHRTestSettings() + : synchronous(true) {} + + std::string url; + std::string sub_url; + std::string sub_allow_origin; + std::string sub_redirect_url; + bool synchronous; +}; + +void SetUpXHR(const XHRTestSettings& settings) { + g_TestResults.sub_url = settings.sub_url; + g_TestResults.sub_html = "SUCCESS"; + g_TestResults.sub_status_code = 200; + g_TestResults.sub_allow_origin = settings.sub_allow_origin; + g_TestResults.sub_redirect_url = settings.sub_redirect_url; + + std::string request_url; + if (!settings.sub_redirect_url.empty()) + request_url = settings.sub_redirect_url; + else + request_url = settings.sub_url; + + g_TestResults.url = settings.url; + std::stringstream ss; + ss << "" + "" + "" + "Running execXMLHttpRequest..." + ""; + g_TestResults.html = ss.str(); + g_TestResults.status_code = 200; + + g_TestResults.exit_url = "http://tests/exit"; +} + +void SetUpXSS(const std::string& url, const std::string& sub_url, + const std::string& domain = std::string()) { + // 1. Load |url| which contains an iframe. + // 2. The iframe loads |xss_url|. + // 3. |xss_url| tries to call a JS function in |url|. + // 4. |url| tries to call a JS function in |xss_url|. + + std::stringstream ss; + std::string domain_line; + if (!domain.empty()) + domain_line = "document.domain = '" + domain + "';"; + + g_TestResults.sub_url = sub_url; + ss << "" + "" + "" + "Running execXSSRequest..." + ""; + g_TestResults.sub_html = ss.str(); + g_TestResults.sub_status_code = 200; + + g_TestResults.url = url; + ss.str(""); + ss << "" + "" + "" + "" + "", "text/html"); + AddResource(kV8ContextChildTestUrl, "" + "CHILD", + "text/html"); + CreateBrowser(kV8ContextParentTestUrl); + } else if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION || + test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) { + AddResource(kV8OnUncaughtExceptionTestUrl, "" + "

OnUncaughtException

" + "\n" + "\n", + "text/html"); + CreateBrowser(kV8OnUncaughtExceptionTestUrl); + } else { + EXPECT_TRUE(test_url_ != NULL); + AddResource(test_url_, "" + "TEST", "text/html"); + CreateBrowser(test_url_); + } + } + + virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE { + if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS && + browser->IsPopup()) { + // Generate the uncaught exception in the main browser. + GetBrowser()->GetMainFrame()->ExecuteJavaScript( + "window.setTimeout(test, 0);", + GetBrowser()->GetMainFrame()->GetURL(), 0); + } + + TestHandler::OnBeforeClose(browser); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) { + if (!browser->IsPopup()) { + // Create the DevTools window. + CefWindowInfo windowInfo; + CefBrowserSettings settings; + +#if defined(OS_WIN) + windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools"); +#endif + + browser->GetHost()->ShowDevTools(windowInfo, this, settings); + } + return; + } + + const std::string& url = frame->GetURL(); + if (url != kV8NavTestUrl && url != kV8ContextParentTestUrl && + url.find("http://tests/") != std::string::npos) { + // Run the test. + CefRefPtr return_msg = + CefProcessMessage::Create(kV8RunTestMsg); + EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, return_msg)); + } + } + + virtual bool OnProcessMessageReceived( + CefRefPtr browser, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { + EXPECT_TRUE(browser.get()); + EXPECT_EQ(PID_RENDERER, source_process); + EXPECT_TRUE(message.get()); + EXPECT_TRUE(message->IsReadOnly()); + + const std::string& message_name = message->GetName(); + EXPECT_STREQ(kV8TestMsg, message_name.c_str()); + + got_message_.yes(); + + if (message->GetArgumentList()->GetBool(0)) + got_success_.yes(); + + // Test is complete. + DestroyTest(); + + return true; + } + + V8TestMode test_mode_; + const char* test_url_; + TrackCallback got_message_; + TrackCallback got_success_; +}; + +} // namespace + + +// Entry point for creating V8 browser test objects. +// Called from client_app_delegates.cc. +void CreateV8BrowserTests(ClientApp::BrowserDelegateSet& delegates) { + delegates.insert(new V8BrowserTest); +} + +// Entry point for creating V8 renderer test objects. +// Called from client_app_delegates.cc. +void CreateV8RendererTests(ClientApp::RenderDelegateSet& delegates) { + delegates.insert(new V8RendererTest); +} + + +// Helpers for defining V8 tests. +#define V8_TEST_EX(name, test_mode, test_url) \ + TEST(V8Test, name) { \ + g_current_test_mode = test_mode; \ + CefRefPtr handler = \ + new V8TestHandler(test_mode, test_url); \ + handler->ExecuteTest(); \ + EXPECT_TRUE(handler->got_message_); \ + EXPECT_TRUE(handler->got_success_); \ + g_current_test_mode = V8TEST_NONE; \ + } + +#define V8_TEST(name, test_mode) \ + V8_TEST_EX(name, test_mode, kV8TestUrl) + + +// Define the tests. +V8_TEST(NullCreate, V8TEST_NULL_CREATE); +V8_TEST(BoolCreate, V8TEST_BOOL_CREATE); +V8_TEST(IntCreate, V8TEST_INT_CREATE); +V8_TEST(UIntCreate, V8TEST_UINT_CREATE); +V8_TEST(DoubleCreate, V8TEST_DOUBLE_CREATE); +V8_TEST(DateCreate, V8TEST_DATE_CREATE); +V8_TEST(StringCreate, V8TEST_STRING_CREATE); +V8_TEST(EmptyStringCreate, V8TEST_EMPTY_STRING_CREATE); +V8_TEST(ArrayCreate, V8TEST_ARRAY_CREATE); +V8_TEST(ArrayValue, V8TEST_ARRAY_VALUE); +V8_TEST(ObjectCreate, V8TEST_OBJECT_CREATE); +V8_TEST(ObjectUserData, V8TEST_OBJECT_USERDATA); +V8_TEST(ObjectAccessor, V8TEST_OBJECT_ACCESSOR); +V8_TEST(ObjectAccessorException, V8TEST_OBJECT_ACCESSOR_EXCEPTION); +V8_TEST(ObjectAccessorFail, V8TEST_OBJECT_ACCESSOR_FAIL); +V8_TEST(ObjectAccessorReadOnly, V8TEST_OBJECT_ACCESSOR_READONLY); +V8_TEST(ObjectValue, V8TEST_OBJECT_VALUE); +V8_TEST(ObjectValueReadOnly, V8TEST_OBJECT_VALUE_READONLY); +V8_TEST(ObjectValueEnum, V8TEST_OBJECT_VALUE_ENUM); +V8_TEST(ObjectValueDontEnum, V8TEST_OBJECT_VALUE_DONTENUM); +V8_TEST(ObjectValueDelete, V8TEST_OBJECT_VALUE_DELETE); +V8_TEST(ObjectValueDontDelete, V8TEST_OBJECT_VALUE_DONTDELETE); +V8_TEST(ObjectValueEmptyKey, V8TEST_OBJECT_VALUE_EMPTYKEY); +V8_TEST(FunctionCreate, V8TEST_FUNCTION_CREATE); +V8_TEST(FunctionHandler, V8TEST_FUNCTION_HANDLER); +V8_TEST(FunctionHandlerException, V8TEST_FUNCTION_HANDLER_EXCEPTION); +V8_TEST(FunctionHandlerFail, V8TEST_FUNCTION_HANDLER_FAIL); +V8_TEST(FunctionHandlerNoObject, V8TEST_FUNCTION_HANDLER_NO_OBJECT); +V8_TEST(FunctionHandlerWithContext, V8TEST_FUNCTION_HANDLER_WITH_CONTEXT); +V8_TEST(FunctionHandlerEmptyString, V8TEST_FUNCTION_HANDLER_EMPTY_STRING); +V8_TEST(ContextEval, V8TEST_CONTEXT_EVAL); +V8_TEST(ContextEvalException, V8TEST_CONTEXT_EVAL_EXCEPTION); +V8_TEST_EX(ContextEntered, V8TEST_CONTEXT_ENTERED, NULL); +V8_TEST(ContextInvalid, V8TEST_CONTEXT_INVALID); +V8_TEST_EX(Binding, V8TEST_BINDING, kV8BindingTestUrl); +V8_TEST(StackTrace, V8TEST_STACK_TRACE); +V8_TEST(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION); +V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS); +V8_TEST(Extension, V8TEST_EXTENSION); diff --git a/tests/unittests/values_unittest.cc b/tests/unittests/values_unittest.cc new file mode 100644 index 000000000..4ddd99119 --- /dev/null +++ b/tests/unittests/values_unittest.cc @@ -0,0 +1,736 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_task.h" +#include "include/cef_values.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "tests/unittests/test_handler.h" +#include "tests/unittests/test_util.h" + +namespace { + +// Dictionary test keys. +const char* kNullKey = "null_key"; +const char* kBoolKey = "bool_key"; +const char* kIntKey = "int_key"; +const char* kDoubleKey = "double_key"; +const char* kStringKey = "string_key"; +const char* kBinaryKey = "binary_key"; +const char* kDictionaryKey = "dict_key"; +const char* kListKey = "list_key"; + +// List test indexes. +enum { + kNullIndex = 0, + kBoolIndex, + kIntIndex, + kDoubleIndex, + kStringIndex, + kBinaryIndex, + kDictionaryIndex, + kListIndex, +}; + +// Dictionary/list test values. +const bool kBoolValue = true; +const int kIntValue = 12; +const double kDoubleValue = 4.5432; +const char* kStringValue = "My string value"; + + +// BINARY TEST HELPERS + +// Test a binary value. +void TestBinary(CefRefPtr value, char* data, size_t data_size) { + // Testing requires strings longer than 15 characters. + EXPECT_GT(data_size, (size_t)15); + + EXPECT_EQ(data_size, value->GetSize()); + + char* buff = new char[data_size+1]; + char old_char; + + // Test full read. + memset(buff, 0, data_size+1); + EXPECT_EQ(data_size, value->GetData(buff, data_size, 0)); + EXPECT_TRUE(!strcmp(buff, data)); + + // Test partial read with offset. + memset(buff, 0, data_size+1); + old_char = data[15]; + data[15] = 0; + EXPECT_EQ((size_t)10, value->GetData(buff, 10, 5)); + EXPECT_TRUE(!strcmp(buff, data+5)); + data[15] = old_char; + + // Test that changes to the original data have no effect. + memset(buff, 0, data_size+1); + old_char = data[0]; + data[0] = '.'; + EXPECT_EQ((size_t)1, value->GetData(buff, 1, 0)); + EXPECT_EQ(old_char, buff[0]); + data[0] = old_char; + + // Test copy. + CefRefPtr copy = value->Copy(); + TestBinaryEqual(copy, value); + + delete [] buff; +} + +// Used to test access of binary data on a different thread. +class BinaryTask : public CefTask { + public: + BinaryTask(CefRefPtr value, char* data, size_t data_size) + : value_(value), + data_(data), + data_size_(data_size) {} + + virtual void Execute() OVERRIDE { + TestBinary(value_, data_, data_size_); + } + + private: + CefRefPtr value_; + char* data_; + size_t data_size_; + + IMPLEMENT_REFCOUNTING(BinaryTask); +}; + + +// DICTIONARY TEST HELPERS + +// Test dictionary null value. +void TestDictionaryNull(CefRefPtr value) { + EXPECT_FALSE(value->HasKey(kNullKey)); + EXPECT_TRUE(value->SetNull(kNullKey)); + EXPECT_TRUE(value->HasKey(kNullKey)); + EXPECT_EQ(VTYPE_NULL, value->GetType(kNullKey)); +} + +// Test dictionary bool value. +void TestDictionaryBool(CefRefPtr value) { + EXPECT_FALSE(value->HasKey(kBoolKey)); + EXPECT_TRUE(value->SetBool(kBoolKey, kBoolValue)); + EXPECT_TRUE(value->HasKey(kBoolKey)); + EXPECT_EQ(VTYPE_BOOL, value->GetType(kBoolKey)); + EXPECT_EQ(kBoolValue, value->GetBool(kBoolKey)); +} + +// Test dictionary int value. +void TestDictionaryInt(CefRefPtr value) { + EXPECT_FALSE(value->HasKey(kIntKey)); + EXPECT_TRUE(value->SetInt(kIntKey, kIntValue)); + EXPECT_TRUE(value->HasKey(kIntKey)); + EXPECT_EQ(VTYPE_INT, value->GetType(kIntKey)); + EXPECT_EQ(kIntValue, value->GetInt(kIntKey)); +} + +// Test dictionary double value. +void TestDictionaryDouble(CefRefPtr value) { + EXPECT_FALSE(value->HasKey(kDoubleKey)); + EXPECT_TRUE(value->SetDouble(kDoubleKey, kDoubleValue)); + EXPECT_TRUE(value->HasKey(kDoubleKey)); + EXPECT_EQ(VTYPE_DOUBLE, value->GetType(kDoubleKey)); + EXPECT_EQ(kDoubleValue, value->GetDouble(kDoubleKey)); +} + +// Test dictionary string value. +void TestDictionaryString(CefRefPtr value) { + EXPECT_FALSE(value->HasKey(kStringKey)); + EXPECT_TRUE(value->SetString(kStringKey, kStringValue)); + EXPECT_TRUE(value->HasKey(kStringKey)); + EXPECT_EQ(VTYPE_STRING, value->GetType(kStringKey)); + EXPECT_EQ(kStringValue, value->GetString(kStringKey).ToString()); +} + +// Test dictionary binary value. +void TestDictionaryBinary(CefRefPtr value, + char* binary_data, size_t binary_data_size, + CefRefPtr& binary_value) { + binary_value = CefBinaryValue::Create(binary_data, binary_data_size); + EXPECT_TRUE(binary_value.get()); + EXPECT_TRUE(binary_value->IsValid()); + EXPECT_FALSE(binary_value->IsOwned()); + EXPECT_FALSE(value->HasKey(kBinaryKey)); + EXPECT_TRUE(value->SetBinary(kBinaryKey, binary_value)); + EXPECT_FALSE(binary_value->IsValid()); // Value should be detached + EXPECT_TRUE(value->HasKey(kBinaryKey)); + EXPECT_EQ(VTYPE_BINARY, value->GetType(kBinaryKey)); + binary_value = value->GetBinary(kBinaryKey); + EXPECT_TRUE(binary_value.get()); + EXPECT_TRUE(binary_value->IsValid()); + EXPECT_TRUE(binary_value->IsOwned()); + TestBinary(binary_value, binary_data, binary_data_size); +} + +// Test dictionary dictionary value. +void TestDictionaryDictionary(CefRefPtr value, + CefRefPtr& dictionary_value) { + dictionary_value = CefDictionaryValue::Create(); + EXPECT_TRUE(dictionary_value.get()); + EXPECT_TRUE(dictionary_value->IsValid()); + EXPECT_FALSE(dictionary_value->IsOwned()); + EXPECT_FALSE(dictionary_value->IsReadOnly()); + EXPECT_TRUE(dictionary_value->SetInt(kIntKey, kIntValue)); + EXPECT_EQ((size_t)1, dictionary_value->GetSize()); + EXPECT_FALSE(value->HasKey(kDictionaryKey)); + EXPECT_TRUE(value->SetDictionary(kDictionaryKey, dictionary_value)); + EXPECT_FALSE(dictionary_value->IsValid()); // Value should be detached + EXPECT_TRUE(value->HasKey(kDictionaryKey)); + EXPECT_EQ(VTYPE_DICTIONARY, value->GetType(kDictionaryKey)); + dictionary_value = value->GetDictionary(kDictionaryKey); + EXPECT_TRUE(dictionary_value.get()); + EXPECT_TRUE(dictionary_value->IsValid()); + EXPECT_TRUE(dictionary_value->IsOwned()); + EXPECT_FALSE(dictionary_value->IsReadOnly()); + EXPECT_EQ((size_t)1, dictionary_value->GetSize()); + EXPECT_EQ(kIntValue, dictionary_value->GetInt(kIntKey)); +} + +// Test dictionary list value. +void TestDictionaryList(CefRefPtr value, + CefRefPtr& list_value) { + list_value = CefListValue::Create(); + EXPECT_TRUE(list_value.get()); + EXPECT_TRUE(list_value->IsValid()); + EXPECT_FALSE(list_value->IsOwned()); + EXPECT_FALSE(list_value->IsReadOnly()); + EXPECT_TRUE(list_value->SetInt(0, kIntValue)); + EXPECT_EQ((size_t)1, list_value->GetSize()); + EXPECT_FALSE(value->HasKey(kListKey)); + EXPECT_TRUE(value->SetList(kListKey, list_value)); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + EXPECT_TRUE(value->HasKey(kListKey)); + EXPECT_EQ(VTYPE_LIST, value->GetType(kListKey)); + list_value = value->GetList(kListKey); + EXPECT_TRUE(list_value.get()); + EXPECT_TRUE(list_value->IsValid()); + EXPECT_TRUE(list_value->IsOwned()); + EXPECT_FALSE(list_value->IsReadOnly()); + EXPECT_EQ((size_t)1, list_value->GetSize()); + EXPECT_EQ(kIntValue, list_value->GetInt(0)); +} + +// Test dictionary value. +void TestDictionary(CefRefPtr value, + char* binary_data, size_t binary_data_size) { + CefRefPtr binary_value; + CefRefPtr dictionary_value; + CefRefPtr list_value; + + // Test the size. + EXPECT_EQ((size_t)0, value->GetSize()); + + TestDictionaryNull(value); + TestDictionaryBool(value); + TestDictionaryInt(value); + TestDictionaryDouble(value); + TestDictionaryString(value); + TestDictionaryBinary(value, binary_data, binary_data_size, binary_value); + TestDictionaryDictionary(value, dictionary_value); + TestDictionaryList(value, list_value); + + // Test the size. + EXPECT_EQ((size_t)8, value->GetSize()); + + // Test copy. + CefRefPtr copy = value->Copy(false); + TestDictionaryEqual(value, copy); + + // Test removal. + EXPECT_TRUE(value->Remove(kNullKey)); + EXPECT_FALSE(value->HasKey(kNullKey)); + + EXPECT_TRUE(value->Remove(kBoolKey)); + EXPECT_FALSE(value->HasKey(kBoolKey)); + + EXPECT_TRUE(value->Remove(kIntKey)); + EXPECT_FALSE(value->HasKey(kIntKey)); + + EXPECT_TRUE(value->Remove(kDoubleKey)); + EXPECT_FALSE(value->HasKey(kDoubleKey)); + + EXPECT_TRUE(value->Remove(kStringKey)); + EXPECT_FALSE(value->HasKey(kStringKey)); + + EXPECT_TRUE(value->Remove(kBinaryKey)); + EXPECT_FALSE(value->HasKey(kBinaryKey)); + EXPECT_FALSE(binary_value->IsValid()); // Value should be detached + + EXPECT_TRUE(value->Remove(kDictionaryKey)); + EXPECT_FALSE(value->HasKey(kDictionaryKey)); + EXPECT_FALSE(dictionary_value->IsValid()); // Value should be detached + + EXPECT_TRUE(value->Remove(kListKey)); + EXPECT_FALSE(value->HasKey(kListKey)); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + + // Test the size. + EXPECT_EQ((size_t)0, value->GetSize()); + + // Re-add some values. + TestDictionaryNull(value); + TestDictionaryBool(value); + TestDictionaryDictionary(value, dictionary_value); + + // Test the size. + EXPECT_EQ((size_t)3, value->GetSize()); + + // Clear the values. + EXPECT_TRUE(value->Clear()); + EXPECT_EQ((size_t)0, value->GetSize()); + EXPECT_FALSE(dictionary_value->IsValid()); // Value should be detached +} + +// Used to test access of dictionary data on a different thread. +class DictionaryTask : public CefTask { + public: + DictionaryTask(CefRefPtr value, char* binary_data, + size_t binary_data_size) + : value_(value), + binary_data_(binary_data), + binary_data_size_(binary_data_size) {} + + virtual void Execute() OVERRIDE { + TestDictionary(value_, binary_data_, binary_data_size_); + } + + private: + CefRefPtr value_; + char* binary_data_; + size_t binary_data_size_; + + IMPLEMENT_REFCOUNTING(DictionaryTask); +}; + + +// LIST TEST HELPERS + +// Test list null value. +void TestListNull(CefRefPtr value, int index) { + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetNull(index)); + EXPECT_EQ(VTYPE_NULL, value->GetType(index)); +} + +// Test list bool value. +void TestListBool(CefRefPtr value, int index) { + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetBool(index, kBoolValue)); + EXPECT_EQ(VTYPE_BOOL, value->GetType(index)); + EXPECT_EQ(kBoolValue, value->GetBool(index)); +} + +// Test list int value. +void TestListInt(CefRefPtr value, int index) { + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetInt(index, kIntValue)); + EXPECT_EQ(VTYPE_INT, value->GetType(index)); + EXPECT_EQ(kIntValue, value->GetInt(index)); +} + +// Test list double value. +void TestListDouble(CefRefPtr value, int index) { + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetDouble(index, kDoubleValue)); + EXPECT_EQ(VTYPE_DOUBLE, value->GetType(index)); + EXPECT_EQ(kDoubleValue, value->GetDouble(index)); +} + +// Test list string value. +void TestListString(CefRefPtr value, int index) { + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetString(index, kStringValue)); + EXPECT_EQ(VTYPE_STRING, value->GetType(index)); + EXPECT_EQ(kStringValue, value->GetString(index).ToString()); +} + +// Test list binary value. +void TestListBinary(CefRefPtr value, int index, + char* binary_data, size_t binary_data_size, + CefRefPtr& binary_value) { + binary_value = CefBinaryValue::Create(binary_data, binary_data_size); + EXPECT_TRUE(binary_value.get()); + EXPECT_TRUE(binary_value->IsValid()); + EXPECT_FALSE(binary_value->IsOwned()); + + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetBinary(index, binary_value)); + EXPECT_FALSE(binary_value->IsValid()); // Value should be detached + EXPECT_EQ(VTYPE_BINARY, value->GetType(index)); + binary_value = value->GetBinary(index); + EXPECT_TRUE(binary_value.get()); + EXPECT_TRUE(binary_value->IsValid()); + EXPECT_TRUE(binary_value->IsOwned()); + TestBinary(binary_value, binary_data, binary_data_size); +} + +// Test list dictionary value. +void TestListDictionary(CefRefPtr value, int index, + CefRefPtr& dictionary_value) { + dictionary_value = CefDictionaryValue::Create(); + EXPECT_TRUE(dictionary_value.get()); + EXPECT_TRUE(dictionary_value->IsValid()); + EXPECT_FALSE(dictionary_value->IsOwned()); + EXPECT_FALSE(dictionary_value->IsReadOnly()); + EXPECT_TRUE(dictionary_value->SetInt(kIntKey, kIntValue)); + EXPECT_EQ((size_t)1, dictionary_value->GetSize()); + + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetDictionary(index, dictionary_value)); + EXPECT_FALSE(dictionary_value->IsValid()); // Value should be detached + EXPECT_EQ(VTYPE_DICTIONARY, value->GetType(index)); + dictionary_value = value->GetDictionary(index); + EXPECT_TRUE(dictionary_value.get()); + EXPECT_TRUE(dictionary_value->IsValid()); + EXPECT_TRUE(dictionary_value->IsOwned()); + EXPECT_FALSE(dictionary_value->IsReadOnly()); + EXPECT_EQ((size_t)1, dictionary_value->GetSize()); + EXPECT_EQ(kIntValue, dictionary_value->GetInt(kIntKey)); +} + +// Test list list value. +void TestListList(CefRefPtr value, int index, + CefRefPtr& list_value) { + list_value = CefListValue::Create(); + EXPECT_TRUE(list_value.get()); + EXPECT_TRUE(list_value->IsValid()); + EXPECT_FALSE(list_value->IsOwned()); + EXPECT_FALSE(list_value->IsReadOnly()); + EXPECT_TRUE(list_value->SetInt(0, kIntValue)); + EXPECT_EQ((size_t)1, list_value->GetSize()); + + CefValueType type = value->GetType(index); + EXPECT_TRUE(type == VTYPE_INVALID || type == VTYPE_NULL); + + EXPECT_TRUE(value->SetList(index, list_value)); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + EXPECT_EQ(VTYPE_LIST, value->GetType(index)); + list_value = value->GetList(index); + EXPECT_TRUE(list_value.get()); + EXPECT_TRUE(list_value->IsValid()); + EXPECT_TRUE(list_value->IsOwned()); + EXPECT_FALSE(list_value->IsReadOnly()); + EXPECT_EQ((size_t)1, list_value->GetSize()); + EXPECT_EQ(kIntValue, list_value->GetInt(0)); +} + +// Test list value. +void TestList(CefRefPtr value, + char* binary_data, size_t binary_data_size) { + CefRefPtr binary_value; + CefRefPtr dictionary_value; + CefRefPtr list_value; + + // Test the size. + EXPECT_EQ((size_t)0, value->GetSize()); + + // Set the size. + EXPECT_TRUE(value->SetSize(8)); + EXPECT_EQ((size_t)8, value->GetSize()); + + EXPECT_EQ(VTYPE_NULL, value->GetType(kNullIndex)); + TestListNull(value, kNullIndex); + EXPECT_EQ(VTYPE_NULL, value->GetType(kBoolIndex)); + TestListBool(value, kBoolIndex); + EXPECT_EQ(VTYPE_NULL, value->GetType(kIntIndex)); + TestListInt(value, kIntIndex); + EXPECT_EQ(VTYPE_NULL, value->GetType(kDoubleIndex)); + TestListDouble(value, kDoubleIndex); + EXPECT_EQ(VTYPE_NULL, value->GetType(kStringIndex)); + TestListString(value, kStringIndex); + EXPECT_EQ(VTYPE_NULL, value->GetType(kBinaryIndex)); + TestListBinary(value, kBinaryIndex, binary_data, binary_data_size, + binary_value); + EXPECT_EQ(VTYPE_NULL, value->GetType(kDictionaryIndex)); + TestListDictionary(value, kDictionaryIndex, dictionary_value); + EXPECT_EQ(VTYPE_NULL, value->GetType(kListIndex)); + TestListList(value, kListIndex, list_value); + + // Test the size. + EXPECT_EQ((size_t)8, value->GetSize()); + + // Test copy. + CefRefPtr copy = value->Copy(); + TestListEqual(value, copy); + + // Test removal (in reverse order so indexes stay valid). + EXPECT_TRUE(value->Remove(kListIndex)); + EXPECT_EQ((size_t)7, value->GetSize()); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + + EXPECT_TRUE(value->Remove(kDictionaryIndex)); + EXPECT_EQ((size_t)6, value->GetSize()); + EXPECT_FALSE(dictionary_value->IsValid()); // Value should be detached + + EXPECT_TRUE(value->Remove(kBinaryIndex)); + EXPECT_EQ((size_t)5, value->GetSize()); + EXPECT_FALSE(binary_value->IsValid()); // Value should be detached + + EXPECT_TRUE(value->Remove(kStringIndex)); + EXPECT_EQ((size_t)4, value->GetSize()); + + EXPECT_TRUE(value->Remove(kDoubleIndex)); + EXPECT_EQ((size_t)3, value->GetSize()); + + EXPECT_TRUE(value->Remove(kIntIndex)); + EXPECT_EQ((size_t)2, value->GetSize()); + + EXPECT_TRUE(value->Remove(kBoolIndex)); + EXPECT_EQ((size_t)1, value->GetSize()); + + EXPECT_TRUE(value->Remove(kNullIndex)); + EXPECT_EQ((size_t)0, value->GetSize()); + + // Re-add some values. + EXPECT_EQ(VTYPE_INVALID, value->GetType(0)); + TestListNull(value, 0); + EXPECT_EQ(VTYPE_INVALID, value->GetType(1)); + TestListBool(value, 1); + EXPECT_EQ(VTYPE_INVALID, value->GetType(2)); + TestListList(value, 2, list_value); + + // Test the size. + EXPECT_EQ((size_t)3, value->GetSize()); + + // Clear the values. + EXPECT_TRUE(value->Clear()); + EXPECT_EQ((size_t)0, value->GetSize()); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + + // Add some values in random order. + EXPECT_EQ(VTYPE_INVALID, value->GetType(2)); + TestListInt(value, 2); + EXPECT_EQ(VTYPE_NULL, value->GetType(0)); + TestListBool(value, 0); + EXPECT_EQ(VTYPE_NULL, value->GetType(1)); + TestListList(value, 1, list_value); + + EXPECT_EQ(VTYPE_BOOL, value->GetType(0)); + EXPECT_EQ(VTYPE_LIST, value->GetType(1)); + EXPECT_EQ(VTYPE_INT, value->GetType(2)); + + // Test the size. + EXPECT_EQ((size_t)3, value->GetSize()); + + // Clear some values. + EXPECT_TRUE(value->SetSize(1)); + EXPECT_EQ((size_t)1, value->GetSize()); + EXPECT_FALSE(list_value->IsValid()); // Value should be detached + + EXPECT_EQ(VTYPE_BOOL, value->GetType(0)); + EXPECT_EQ(VTYPE_INVALID, value->GetType(1)); + EXPECT_EQ(VTYPE_INVALID, value->GetType(2)); + + // Clear all values. + EXPECT_TRUE(value->Clear()); + EXPECT_EQ((size_t)0, value->GetSize()); +} + +// Used to test access of list data on a different thread. +class ListTask : public CefTask { + public: + ListTask(CefRefPtr value, char* binary_data, + size_t binary_data_size) + : value_(value), + binary_data_(binary_data), + binary_data_size_(binary_data_size) {} + + virtual void Execute() OVERRIDE { + TestList(value_, binary_data_, binary_data_size_); + } + + private: + CefRefPtr value_; + char* binary_data_; + size_t binary_data_size_; + + IMPLEMENT_REFCOUNTING(ListTask); +}; + +} // namespace + + +// Test binary value access. +TEST(ValuesTest, BinaryAccess) { + char data[] = "This is my test data"; + + CefRefPtr value = + CefBinaryValue::Create(data, sizeof(data)-1); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + + // Test on this thread. + TestBinary(value, data, sizeof(data)-1); +} + +// Test binary value access on a different thread. +TEST(ValuesTest, BinaryAccessOtherThread) { + char data[] = "This is my test data"; + + CefRefPtr value = + CefBinaryValue::Create(data, sizeof(data)-1); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + + // Test on a different thread. + CefPostTask(TID_UI, new BinaryTask(value, data, sizeof(data)-1)); + WaitForUIThread(); +} + +// Test dictionary value access. +TEST(ValuesTest, DictionaryAccess) { + CefRefPtr value = CefDictionaryValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + char binary_data[] = "This is my test data"; + + // Test on this thread. + TestDictionary(value, binary_data, sizeof(binary_data)-1); +} + +// Test dictionary value access on a different thread. +TEST(ValuesTest, DictionaryAccessOtherThread) { + CefRefPtr value = CefDictionaryValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + char binary_data[] = "This is my test data"; + + // Test on a different thread. + CefPostTask(TID_UI, + new DictionaryTask(value, binary_data, sizeof(binary_data)-1)); + WaitForUIThread(); +} + +// Test dictionary value nested detachment +TEST(ValuesTest, DictionaryDetachment) { + CefRefPtr value = CefDictionaryValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + CefRefPtr dictionary_value = CefDictionaryValue::Create(); + CefRefPtr dictionary_value2 = + CefDictionaryValue::Create(); + CefRefPtr dictionary_value3 = + CefDictionaryValue::Create(); + + dictionary_value2->SetDictionary(kDictionaryKey, dictionary_value3); + EXPECT_FALSE(dictionary_value3->IsValid()); + dictionary_value->SetDictionary(kDictionaryKey, dictionary_value2); + EXPECT_FALSE(dictionary_value2->IsValid()); + value->SetDictionary(kDictionaryKey, dictionary_value); + EXPECT_FALSE(dictionary_value->IsValid()); + + dictionary_value = value->GetDictionary(kDictionaryKey); + EXPECT_TRUE(dictionary_value.get()); + EXPECT_TRUE(dictionary_value->IsValid()); + + dictionary_value2 = dictionary_value->GetDictionary(kDictionaryKey); + EXPECT_TRUE(dictionary_value2.get()); + EXPECT_TRUE(dictionary_value2->IsValid()); + + dictionary_value3 = dictionary_value2->GetDictionary(kDictionaryKey); + EXPECT_TRUE(dictionary_value3.get()); + EXPECT_TRUE(dictionary_value3->IsValid()); + + EXPECT_TRUE(value->Remove(kDictionaryKey)); + EXPECT_FALSE(dictionary_value->IsValid()); + EXPECT_FALSE(dictionary_value2->IsValid()); + EXPECT_FALSE(dictionary_value3->IsValid()); +} + +// Test list value access. +TEST(ValuesTest, ListAccess) { + CefRefPtr value = CefListValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + char binary_data[] = "This is my test data"; + + // Test on this thread. + TestList(value, binary_data, sizeof(binary_data)-1); +} + +// Test list value access on a different thread. +TEST(ValuesTest, ListAccessOtherThread) { + CefRefPtr value = CefListValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + char binary_data[] = "This is my test data"; + + // Test on a different thread. + CefPostTask(TID_UI, new ListTask(value, binary_data, sizeof(binary_data)-1)); + WaitForUIThread(); +} + +// Test list value nested detachment +TEST(ValuesTest, ListDetachment) { + CefRefPtr value = CefListValue::Create(); + EXPECT_TRUE(value.get()); + EXPECT_TRUE(value->IsValid()); + EXPECT_FALSE(value->IsOwned()); + EXPECT_FALSE(value->IsReadOnly()); + + CefRefPtr list_value = CefListValue::Create(); + CefRefPtr list_value2 = CefListValue::Create(); + CefRefPtr list_value3 = CefListValue::Create(); + + list_value2->SetList(0, list_value3); + EXPECT_FALSE(list_value3->IsValid()); + list_value->SetList(0, list_value2); + EXPECT_FALSE(list_value2->IsValid()); + value->SetList(0, list_value); + EXPECT_FALSE(list_value->IsValid()); + + list_value = value->GetList(0); + EXPECT_TRUE(list_value.get()); + EXPECT_TRUE(list_value->IsValid()); + + list_value2 = list_value->GetList(0); + EXPECT_TRUE(list_value2.get()); + EXPECT_TRUE(list_value2->IsValid()); + + list_value3 = list_value2->GetList(0); + EXPECT_TRUE(list_value3.get()); + EXPECT_TRUE(list_value3->IsValid()); + + EXPECT_TRUE(value->Remove(0)); + EXPECT_FALSE(list_value->IsValid()); + EXPECT_FALSE(list_value2->IsValid()); + EXPECT_FALSE(list_value3->IsValid()); +} diff --git a/tests/unittests/version_unittest.cc b/tests/unittests/version_unittest.cc new file mode 100644 index 000000000..b4d5f3016 --- /dev/null +++ b/tests/unittests/version_unittest.cc @@ -0,0 +1,27 @@ +// 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 this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_version.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(VersionTest, BuildRevision) { + EXPECT_EQ(CEF_REVISION, cef_build_revision()); +} + +TEST(VersionTest, VersionInfo) { + EXPECT_EQ(CEF_VERSION_MAJOR, cef_version_info(0)); + EXPECT_EQ(CEF_REVISION, cef_version_info(1)); + EXPECT_EQ(CHROME_VERSION_MAJOR, cef_version_info(2)); + EXPECT_EQ(CHROME_VERSION_MINOR, cef_version_info(3)); + EXPECT_EQ(CHROME_VERSION_BUILD, cef_version_info(4)); + EXPECT_EQ(CHROME_VERSION_PATCH, cef_version_info(5)); +} + +TEST(VersionTest, ApiHash) { + EXPECT_STREQ(CEF_API_HASH_PLATFORM, cef_api_hash(0)); + EXPECT_STREQ(CEF_API_HASH_UNIVERSAL, cef_api_hash(1)); +} diff --git a/tests/unittests/xml_reader_unittest.cc b/tests/unittests/xml_reader_unittest.cc new file mode 100644 index 000000000..aa7f8b730 --- /dev/null +++ b/tests/unittests/xml_reader_unittest.cc @@ -0,0 +1,645 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_stream.h" +#include "include/cef_xml_reader.h" +#include "include/wrapper/cef_xml_object.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +char g_test_xml[] = + "\n" + "\n" + "\n" + " \n" + "]>\n" + "\n" + " value A\n" + " \n" + " \n" + " value B1\n" + " data]]>\n" + " &EB;\n" + " this is mixed content &EA;\n" + " \n" + " " + "\n" + "\n"; + +} // namespace + +// Test XML reading +TEST(XmlReaderTest, Read) { + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(g_test_xml, sizeof(g_test_xml) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + // Create the XML reader. + CefRefPtr reader( + CefXmlReader::Create(stream, XML_ENCODING_NONE, + "http://www.example.org/example.xml")); + ASSERT_TRUE(reader.get() != NULL); + + // Move to the processing instruction node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 0); + ASSERT_EQ(reader->GetType(), XML_NODE_PROCESSING_INSTRUCTION); + ASSERT_EQ(reader->GetLocalName(), "my_instruction"); + ASSERT_EQ(reader->GetQualifiedName(), "my_instruction"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "my_value"); + + // Move to the DOCTYPE node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 0); + ASSERT_EQ(reader->GetType(), XML_NODE_DOCUMENT_TYPE); + ASSERT_EQ(reader->GetLocalName(), "my_document"); + ASSERT_EQ(reader->GetQualifiedName(), "my_document"); + ASSERT_FALSE(reader->HasValue()); + + // Move to ns:obj element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 0); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "obj"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:obj"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasAttributes()); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)1); + ASSERT_EQ(reader->GetAttribute(0), "http://www.example.org/ns"); + ASSERT_EQ(reader->GetAttribute("xmlns:ns"), "http://www.example.org/ns"); + ASSERT_EQ(reader->GetAttribute("ns", "http://www.w3.org/2000/xmlns/"), + "http://www.example.org/ns"); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objA element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objA"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objA"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the ns:objA value node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_TEXT); + ASSERT_EQ(reader->GetLocalName(), "#text"); + ASSERT_EQ(reader->GetQualifiedName(), "#text"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "value A"); + + // Move to the ns:objA element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objA"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objA"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the comment node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_COMMENT); + ASSERT_EQ(reader->GetLocalName(), "#comment"); + ASSERT_EQ(reader->GetQualifiedName(), "#comment"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), " my comment "); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objB"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB_1 element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objB_1"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_1"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the ns:objB_1 value node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_TEXT); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "value B1"); + + // Move to the ns:objB_1 element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objB_1"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_1"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB_2 element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objB_2"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_2"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the ns:objB_2 value node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_CDATA); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "some
data"); + + // Move to the ns:objB_2 element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objB_2"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_2"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB_3 element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objB_3"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_3"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the EB entity reference node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_ENTITY_REFERENCE); + ASSERT_EQ(reader->GetLocalName(), "EB"); + ASSERT_EQ(reader->GetQualifiedName(), "EB"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "EB Value"); + + // Move to the ns:objB_3 element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objB_3"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_3"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB_4 element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objB_4"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_4"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + ASSERT_EQ(reader->GetInnerXml(), "this is mixed content &EA;"); + ASSERT_EQ(reader->GetOuterXml(), + "" + "this is mixed content &EA;"); + + // Move to the element node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "b"); + ASSERT_EQ(reader->GetQualifiedName(), "b"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the text node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 4); + ASSERT_EQ(reader->GetType(), XML_NODE_TEXT); + ASSERT_EQ(reader->GetLocalName(), "#text"); + ASSERT_EQ(reader->GetQualifiedName(), "#text"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "this is"); + + // Move to the element node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "b"); + ASSERT_EQ(reader->GetQualifiedName(), "b"); + + // Move to the text node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_TEXT); + ASSERT_EQ(reader->GetLocalName(), "#text"); + ASSERT_EQ(reader->GetQualifiedName(), "#text"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), " mixed content "); + + // Move to the EA entity reference node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 3); + ASSERT_EQ(reader->GetType(), XML_NODE_ENTITY_REFERENCE); + ASSERT_EQ(reader->GetLocalName(), "EA"); + ASSERT_EQ(reader->GetQualifiedName(), "EA"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_EQ(reader->GetValue(), "EA Value"); + + // Move to the ns:objB_4 element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objB_4"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB_4"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objB element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objB"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objB"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to the ns:objC element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objC"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objC"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->IsEmptyElement()); + ASSERT_TRUE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)2); + ASSERT_EQ(reader->GetAttribute(0), "value C1"); + ASSERT_EQ(reader->GetAttribute("ns:attr1"), "value C1"); + ASSERT_EQ(reader->GetAttribute("attr1", "http://www.example.org/ns"), + "value C1"); + ASSERT_EQ(reader->GetAttribute(1), "value C2"); + ASSERT_EQ(reader->GetAttribute("ns:attr2"), "value C2"); + ASSERT_EQ(reader->GetAttribute("attr2", "http://www.example.org/ns"), + "value C2"); + + // Move to the ns:attr1 attribute. + ASSERT_TRUE(reader->MoveToFirstAttribute()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE); + ASSERT_EQ(reader->GetLocalName(), "attr1"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:attr1"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_EQ(reader->GetValue(), "value C1"); + + // Move to the ns:attr2 attribute. + ASSERT_TRUE(reader->MoveToNextAttribute()); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE); + ASSERT_EQ(reader->GetLocalName(), "attr2"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:attr2"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_EQ(reader->GetValue(), "value C2"); + + // No more attributes. + ASSERT_FALSE(reader->MoveToNextAttribute()); + + // Return to the ns:objC element start node. + ASSERT_TRUE(reader->MoveToCarryingElement()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objC"); + + // Move to the ns:attr1 attribute. + ASSERT_TRUE(reader->MoveToAttribute(0)); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE); + ASSERT_EQ(reader->GetLocalName(), "attr1"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:attr1"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_EQ(reader->GetValue(), "value C1"); + + // Return to the ns:objC element start node. + ASSERT_TRUE(reader->MoveToCarryingElement()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objC"); + + // Move to the ns:attr2 attribute. + ASSERT_TRUE(reader->MoveToAttribute("ns:attr2")); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE); + ASSERT_EQ(reader->GetLocalName(), "attr2"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:attr2"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_EQ(reader->GetValue(), "value C2"); + + // Move to the ns:attr1 attribute without returning to the ns:objC element. + ASSERT_TRUE(reader->MoveToAttribute("attr1", "http://www.example.org/ns")); + ASSERT_EQ(reader->GetDepth(), 2); + ASSERT_EQ(reader->GetType(), XML_NODE_ATTRIBUTE); + ASSERT_EQ(reader->GetLocalName(), "attr1"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:attr1"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_TRUE(reader->HasValue()); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_EQ(reader->GetValue(), "value C1"); + + // Move to the ns:objD element start node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_START); + ASSERT_EQ(reader->GetLocalName(), "objD"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objD"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the ns:objD element end node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 1); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "objD"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:objD"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_FALSE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + + // Move to the whitespace node without returning to the ns:objC element. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetType(), XML_NODE_WHITESPACE); + + // Move to ns:obj element ending node. + ASSERT_TRUE(reader->MoveToNextNode()); + ASSERT_EQ(reader->GetDepth(), 0); + ASSERT_EQ(reader->GetType(), XML_NODE_ELEMENT_END); + ASSERT_EQ(reader->GetLocalName(), "obj"); + ASSERT_EQ(reader->GetPrefix(), "ns"); + ASSERT_EQ(reader->GetQualifiedName(), "ns:obj"); + ASSERT_EQ(reader->GetNamespaceURI(), "http://www.example.org/ns"); + ASSERT_FALSE(reader->IsEmptyElement()); + ASSERT_TRUE(reader->HasAttributes()); + ASSERT_FALSE(reader->HasValue()); + // Strangely, the end node will report if the starting node has attributes + // but will not provide access to them. + ASSERT_TRUE(reader->HasAttributes()); + ASSERT_EQ(reader->GetAttributeCount(), (size_t)0); + + // And we're done. + ASSERT_FALSE(reader->MoveToNextNode()); + + ASSERT_TRUE(reader->Close()); +} + +// Test XML read error handling. +TEST(XmlReaderTest, ReadError) { + char test_str[] = + "\n" + "\n"; + + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(test_str, sizeof(test_str) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + // Create the XML reader. + CefRefPtr reader( + CefXmlReader::Create(stream, XML_ENCODING_NONE, + "http://www.example.org/example.xml")); + ASSERT_TRUE(reader.get() != NULL); + + // Move to the processing instruction node and generate parser error. + ASSERT_FALSE(reader->MoveToNextNode()); + ASSERT_TRUE(reader->HasError()); +} + +// Test XmlObject load behavior. +TEST(XmlReaderTest, ObjectLoad) { + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(g_test_xml, sizeof(g_test_xml) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + // Create the XML reader. + CefRefPtr object(new CefXmlObject("object")); + ASSERT_TRUE(object->Load(stream, XML_ENCODING_NONE, + "http://www.example.org/example.xml", NULL)); + + ASSERT_FALSE(object->HasAttributes()); + ASSERT_TRUE(object->HasChildren()); + ASSERT_EQ(object->GetChildCount(), (size_t)1); + + CefRefPtr obj(object->FindChild("ns:obj")); + ASSERT_TRUE(obj.get()); + ASSERT_TRUE(obj->HasChildren()); + ASSERT_EQ(obj->GetChildCount(), (size_t)4); + + CefRefPtr obj_child(obj->FindChild("ns:objC")); + ASSERT_TRUE(obj_child.get()); + ASSERT_EQ(obj_child->GetName(), "ns:objC"); + ASSERT_FALSE(obj_child->HasChildren()); + ASSERT_FALSE(obj_child->HasValue()); + ASSERT_TRUE(obj_child->HasAttributes()); + + CefXmlObject::ObjectVector obj_children; + ASSERT_EQ(obj->GetChildren(obj_children), (size_t)4); + ASSERT_EQ(obj_children.size(), (size_t)4); + + CefXmlObject::ObjectVector::const_iterator it = obj_children.begin(); + for (int ct = 0; it != obj_children.end(); ++it, ++ct) { + obj_child = *it; + ASSERT_TRUE(obj_child.get()); + if (ct == 0) { + // ns:objA + ASSERT_EQ(obj_child->GetName(), "ns:objA"); + ASSERT_FALSE(obj_child->HasChildren()); + ASSERT_TRUE(obj_child->HasValue()); + ASSERT_FALSE(obj_child->HasAttributes()); + ASSERT_EQ(obj_child->GetValue(), "value A"); + } else if (ct == 1) { + // ns:objB + ASSERT_EQ(obj_child->GetName(), "ns:objB"); + ASSERT_TRUE(obj_child->HasChildren()); + ASSERT_FALSE(obj_child->HasValue()); + ASSERT_FALSE(obj_child->HasAttributes()); + ASSERT_EQ(obj_child->GetChildCount(), (size_t)4); + obj_child = obj_child->FindChild("ns:objB_4"); + ASSERT_TRUE(obj_child.get()); + ASSERT_TRUE(obj_child->HasValue()); + ASSERT_EQ(obj_child->GetValue(), + "this is mixed content EA Value"); + } else if (ct == 2) { + // ns:objC + ASSERT_EQ(obj_child->GetName(), "ns:objC"); + ASSERT_FALSE(obj_child->HasChildren()); + ASSERT_FALSE(obj_child->HasValue()); + ASSERT_TRUE(obj_child->HasAttributes()); + + CefXmlObject::AttributeMap attribs; + ASSERT_EQ(obj_child->GetAttributes(attribs), (size_t)2); + ASSERT_EQ(attribs.size(), (size_t)2); + ASSERT_EQ(attribs["ns:attr1"], "value C1"); + ASSERT_EQ(attribs["ns:attr2"], "value C2"); + + ASSERT_EQ(obj_child->GetAttributeCount(), (size_t)2); + ASSERT_TRUE(obj_child->HasAttribute("ns:attr1")); + ASSERT_EQ(obj_child->GetAttributeValue("ns:attr1"), "value C1"); + ASSERT_TRUE(obj_child->HasAttribute("ns:attr2")); + ASSERT_EQ(obj_child->GetAttributeValue("ns:attr2"), "value C2"); + } else if (ct == 3) { + // ns:objD + ASSERT_EQ(obj_child->GetName(), "ns:objD"); + ASSERT_FALSE(obj_child->HasChildren()); + ASSERT_FALSE(obj_child->HasValue()); + ASSERT_FALSE(obj_child->HasAttributes()); + } + } +} + +// Test XmlObject load error handling behavior. +TEST(XmlReaderTest, ObjectLoadError) { + // Test start/end tag mismatch error. + { + char error_xml[] = "\n\n\n
"; + + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(error_xml, sizeof(error_xml) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + CefString error_str; + + // Create the XML reader. + CefRefPtr object(new CefXmlObject("object")); + ASSERT_FALSE(object->Load(stream, XML_ENCODING_NONE, + "http://www.example.org/example.xml", &error_str)); + ASSERT_EQ(error_str, + "Opening and ending tag mismatch: foo line 2 and obj, line 3"); + } + + // Test value following child error. + { + char error_xml[] = "\n\ndisallowed value\n"; + + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(error_xml, sizeof(error_xml) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + CefString error_str; + + // Create the XML reader. + CefRefPtr object(new CefXmlObject("object")); + ASSERT_FALSE(object->Load(stream, XML_ENCODING_NONE, + "http://www.example.org/example.xml", &error_str)); + ASSERT_EQ(error_str, + "Value following child element, line 4"); + } +} diff --git a/tests/unittests/zip_reader_unittest.cc b/tests/unittests/zip_reader_unittest.cc new file mode 100644 index 000000000..4ae10b8cc --- /dev/null +++ b/tests/unittests/zip_reader_unittest.cc @@ -0,0 +1,256 @@ +// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +// Include this first to avoid type conflicts with CEF headers. +#include "tests/unittests/chromium_includes.h" + +#include "include/cef_stream.h" +#include "include/cef_zip_reader.h" +#include "include/wrapper/cef_zip_archive.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + + unsigned char g_test_zip[] = { + 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x7f, + 0x57, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, + 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x50, 0x4b, 0x03, 0x04, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x7f, 0x57, 0x3d, 0xf8, 0x47, 0x0c, + 0xc6, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, + 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x2e, 0x74, 0x78, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x2e, 0x50, 0x4b, 0x03, 0x04, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x7f, 0x57, 0x3d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7f, 0x57, + 0x3d, 0x43, 0xe3, 0x11, 0x5f, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, + 0x20, 0x31, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x61, 0x2e, 0x74, + 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, + 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x41, 0x2e, 0x50, 0x4b, + 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x7f, 0x57, 0x3d, + 0x80, 0xb0, 0x3c, 0x74, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, + 0x31, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x62, 0x2e, 0x74, 0x78, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x42, 0x2e, 0x50, 0x4b, 0x03, + 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x7f, 0x57, 0x3d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, + 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x61, 0x2f, 0x50, + 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7f, 0x57, + 0x3d, 0x15, 0xed, 0x04, 0x2c, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x2c, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, + 0x20, 0x31, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x61, + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x61, 0x31, 0x2e, 0x74, 0x78, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x41, 0x31, 0x2e, 0x50, 0x4b, + 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x7f, 0x57, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, + 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, + 0x32, 0x2f, 0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x80, 0x57, 0x3d, 0x1a, 0x5d, 0x57, 0x5d, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x20, 0x32, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x32, + 0x61, 0x2e, 0x74, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x32, 0x41, + 0x2e, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x67, 0x7f, 0x57, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, + 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x7f, 0x57, 0x3d, 0xf8, 0x47, 0x0c, 0xc6, 0x13, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x20, 0x31, 0x2e, 0x74, 0x78, 0x74, 0x50, 0x4b, 0x01, + 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x7f, 0x57, + 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, + 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, + 0x65, 0x72, 0x20, 0x31, 0x2f, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x7f, 0x57, 0x3d, 0x43, 0xe3, 0x11, + 0x5f, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa7, + 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, + 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x31, 0x61, 0x2e, 0x74, 0x78, 0x74, + 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x7f, 0x57, 0x3d, 0x80, 0xb0, 0x3c, 0x74, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, + 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x2f, 0x66, 0x69, 0x6c, 0x65, + 0x20, 0x31, 0x62, 0x2e, 0x74, 0x78, 0x74, 0x50, 0x4b, 0x01, 0x02, 0x14, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x7f, 0x57, 0x3d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x4d, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, + 0x20, 0x31, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x61, + 0x2f, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x7f, 0x57, 0x3d, 0x15, 0xed, 0x04, 0x2c, 0x15, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, + 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x31, 0x2f, 0x66, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x20, 0x31, 0x61, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x31, 0x61, 0x31, 0x2e, 0x74, 0x78, 0x74, 0x50, 0x4b, 0x01, 0x02, 0x14, + 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x7f, 0x57, 0x3d, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xea, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, + 0x63, 0x68, 0x69, 0x76, 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, + 0x20, 0x32, 0x2f, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x80, 0x57, 0x3d, 0x1a, 0x5d, 0x57, 0x5d, 0x14, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, + 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, + 0x65, 0x2f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x32, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x20, 0x32, 0x61, 0x2e, 0x74, 0x78, 0x74, 0x50, 0x4b, + 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00, 0x9d, 0x02, + 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +} // namespace + +// Test Zip reading. +TEST(ZipReaderTest, Read) { + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(g_test_zip, sizeof(g_test_zip) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + // Create the Zip reader. + CefRefPtr reader(CefZipReader::Create(stream)); + ASSERT_TRUE(reader.get() != NULL); + + char buff[25]; + + // Walk through the archive contents. + ASSERT_TRUE(reader->MoveToFirstFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/"); + ASSERT_EQ(reader->GetFileSize(), 0); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/file 1.txt"); + ASSERT_EQ(reader->GetFileSize(), 19); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 19); + ASSERT_TRUE(!strncmp(buff, "Contents of file 1.", 19)); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 1/"); + ASSERT_EQ(reader->GetFileSize(), 0); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 1/file 1a.txt"); + ASSERT_EQ(reader->GetFileSize(), 20); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 20); + ASSERT_TRUE(reader->CloseFile()); + ASSERT_TRUE(!strncmp(buff, "Contents of file 1A.", 20)); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 1/file 1b.txt"); + ASSERT_EQ(reader->GetFileSize(), 20); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 20); + ASSERT_TRUE(reader->CloseFile()); + ASSERT_TRUE(!strncmp(buff, "Contents of file 1B.", 20)); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 1/folder 1a/"); + ASSERT_EQ(reader->GetFileSize(), 0); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), + "test_archive/folder 1/folder 1a/file 1a1.txt"); + ASSERT_EQ(reader->GetFileSize(), 21); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 21); + ASSERT_TRUE(reader->CloseFile()); + ASSERT_TRUE(!strncmp(buff, "Contents of file 1A1.", 21)); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 2/"); + ASSERT_EQ(reader->GetFileSize(), 0); + + ASSERT_TRUE(reader->MoveToNextFile()); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 2/file 2a.txt"); + ASSERT_EQ(reader->GetFileSize(), 20); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 20); + ASSERT_TRUE(reader->CloseFile()); + ASSERT_TRUE(!strncmp(buff, "Contents of file 2A.", 20)); + + ASSERT_FALSE(reader->MoveToNextFile()); + + // Try seeking a particular file + ASSERT_TRUE(reader->MoveToFile("TEST_ARCHIVE/FOLDER 1/FILE 1B.TXT", false)); + ASSERT_EQ(reader->GetFileName(), "test_archive/folder 1/file 1b.txt"); + ASSERT_EQ(reader->GetFileSize(), 20); + ASSERT_TRUE(reader->OpenFile("")); + ASSERT_EQ(reader->ReadFile(buff, sizeof(buff)), 20); + ASSERT_TRUE(reader->CloseFile()); + ASSERT_TRUE(!strncmp(buff, "Contents of file 1B.", 20)); + + ASSERT_TRUE(reader->MoveToFile("test_archive/folder 1/file 1b.txt", true)); + ASSERT_FALSE(reader->MoveToFile("test_archive/folder 1/FILE 1B.txt", true)); + + ASSERT_TRUE(reader->Close()); +} + +// Test CefZipArchive object. +TEST(ZipReaderTest, ReadArchive) { + // Create the stream reader. + CefRefPtr stream( + CefStreamReader::CreateForData(g_test_zip, sizeof(g_test_zip) - 1)); + ASSERT_TRUE(stream.get() != NULL); + + // Create the Zip archive object. + CefRefPtr archive(new CefZipArchive()); + + ASSERT_EQ(archive->Load(stream, CefString(), false), (size_t)5); + + ASSERT_TRUE(archive->HasFile("test_archive/file 1.txt")); + ASSERT_TRUE(archive->HasFile("test_archive/folder 1/file 1a.txt")); + ASSERT_TRUE(archive->HasFile("test_archive/FOLDER 1/file 1b.txt")); + ASSERT_TRUE(archive->HasFile("test_archive/folder 1/folder 1a/file 1a1.txt")); + ASSERT_TRUE(archive->HasFile("test_archive/folder 2/file 2a.txt")); + + // Test content retrieval. + CefRefPtr file; + file = archive->GetFile("test_archive/folder 2/file 2a.txt"); + ASSERT_TRUE(file.get()); + + ASSERT_EQ(file->GetDataSize(), (size_t)20); + ASSERT_TRUE(!strncmp(reinterpret_cast(file->GetData()), + "Contents of file 2A.", 20)); + + // Test stream reading. + CefRefPtr reader(file->GetStreamReader()); + ASSERT_TRUE(reader.get()); + + char buff[8]; + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)8); + ASSERT_TRUE(!strncmp(buff, "Contents", 8)); + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)8); + ASSERT_TRUE(!strncmp(buff, " of file", 8)); + ASSERT_EQ(reader->Read(buff, 1, 8), (size_t)4); + ASSERT_TRUE(!strncmp(buff, " 2A.", 4)); + ASSERT_TRUE(reader->Eof()); +} diff --git a/tools/automate/automate-git.py b/tools/automate/automate-git.py new file mode 100644 index 000000000..88a142909 --- /dev/null +++ b/tools/automate/automate-git.py @@ -0,0 +1,941 @@ +# 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. + +from optparse import OptionParser +import os +import shlex +import shutil +import subprocess +import sys +import tempfile +import urllib +import xml.etree.ElementTree as ET +import zipfile + +## +# Default URLs. +## + +depot_tools_url = 'http://src.chromium.org/svn/trunk/tools/depot_tools' + +cef_git_trunk_url = 'https://chromiumembedded@bitbucket.org/chromiumembedded/trunk-cef3.git' +cef_git_branch_url = 'https://chromiumembedded@bitbucket.org/chromiumembedded/branches-%1-cef3.git' +cef_svn_trunk_url = 'https://chromiumembedded.googlecode.com/svn/trunk/cef3' +cef_svn_branch_url = 'https://chromiumembedded.googlecode.com/svn/branches/%1/cef3' + + +## +# Global system variables. +## + +# Operating system. +platform = ''; +if sys.platform == 'win32': + platform = 'windows' +elif sys.platform == 'darwin': + platform = 'macosx' +elif sys.platform.startswith('linux'): + platform = 'linux' + +# Script directory. +script_dir = os.path.dirname(__file__) + +# Script extension. +if platform == 'windows': + script_ext = '.bat' +else: + script_ext = '.sh' + + +## +# Helper functions. +## + +def msg(message): + """ Output a message. """ + sys.stdout.write('--> ' + message + "\n") + +def run(command_line, working_dir, depot_tools_dir=None, output_file=None): + """ Runs the specified command. """ + # add depot_tools to the path + env = os.environ + if not depot_tools_dir is None: + env['PATH'] = depot_tools_dir+os.pathsep+env['PATH'] + + sys.stdout.write('-------- Running "'+command_line+'" in "'+\ + working_dir+'"...'+"\n") + if not options.dryrun: + args = shlex.split(command_line.replace('\\', '\\\\')) + + if not output_file: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32')) + with open(output_file, "w") as f: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32'), + stderr=subprocess.STDOUT, stdout=f) + +def create_directory(path): + """ Creates a directory if it doesn't already exist. """ + if not os.path.exists(path): + msg("Creating directory %s" % (path)); + if not options.dryrun: + os.makedirs(path) + +def delete_directory(path): + """ Removes an existing directory. """ + if os.path.exists(path): + msg("Removing directory %s" % (path)); + if not options.dryrun: + shutil.rmtree(path, onerror=onerror) + +def copy_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Copying directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.copytree(source, target) + +def move_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Moving directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.move(source, target) + +def is_git_checkout(path): + """ Returns true if the path represents a git checkout. """ + return os.path.exists(os.path.join(path, '.git')) + +def is_svn_checkout(path): + """ Returns true if the path represents an svn checkout. """ + return os.path.exists(os.path.join(path, '.svn')) + +def exec_cmd(cmd, path): + """ Execute the specified command and return the result. """ + out = '' + err = '' + sys.stdout.write("-------- Running \"%s\" in \"%s\"...\n" % (cmd, path)) + parts = cmd.split() + try: + process = subprocess.Popen(parts, cwd=path, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=(sys.platform == 'win32')) + out, err = process.communicate() + except IOError, (errno, strerror): + raise + except: + raise + return {'out': out, 'err': err} + +def get_git_hash(path, branch): + """ Returns the git hash for the specified branch/tag/hash. """ + cmd = "%s rev-parse %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_git_url(path): + """ Returns the origin url for the specified path. """ + cmd = "%s config --get remote.origin.url" % (git_exe) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_git_svn_revision(path, branch): + """ Returns the SVN revision associated with the specified path and git + branch/tag/hash. """ + svn_rev = "None" + cmd = "%s log --grep=^git-svn-id: -n 1 %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['err'] == '': + for line in result['out'].split('\n'): + if line.find("git-svn-id") > 0: + svn_rev = line.split("@")[1].split()[0] + break + return svn_rev + +def get_svn_info(path): + """ Retrieves the URL and revision from svn info. """ + url = 'None' + rev = 'None' + cmd = "%s info --xml %s" % (svn_exe, path) + is_http = path[0:4] == 'http' + if is_http or os.path.exists(path): + result = exec_cmd(cmd, path if not is_http else '.') + if result['err'] == '': + tree = ET.ElementTree(ET.fromstring(result['out'])) + entry = tree.getroot().find('entry') + url = entry.find('url').text + rev = entry.attrib['revision'] + else: + raise Exception("Failed to execute svn info: %s" % (result['err'])) + return {'url': url, 'revision': rev} + +def download_and_extract(src, target, contents_prefix): + """ Extracts the contents of src, which may be a URL or local file, to the + target directory. """ + temporary = False + + if src[:4] == 'http': + # Attempt to download a URL. + opener = urllib.FancyURLopener({}) + response = opener.open(src) + + temporary = True + handle, archive_path = tempfile.mkstemp(suffix = '.zip') + os.write(handle, response.read()) + os.close(handle) + elif os.path.exists(src): + # Use a local file. + archive_path = src + else: + raise Exception('Path type is unsupported or does not exist: ' + src) + + if not zipfile.is_zipfile(archive_path): + raise Exception('Not a valid zip archive: ' + src) + + def remove_prefix(zip, prefix): + offset = len(prefix) + for zipinfo in zip.infolist(): + name = zipinfo.filename + if len(name) > offset and name[:offset] == prefix: + zipinfo.filename = name[offset:] + yield zipinfo + + # Attempt to extract the archive file. + try: + os.makedirs(target) + zf = zipfile.ZipFile(archive_path, 'r') + zf.extractall(target, remove_prefix(zf, contents_prefix)) + except: + shutil.rmtree(target, onerror=onerror) + raise + zf.close() + + # Delete the archive file if temporary. + if temporary and os.path.exists(archive_path): + os.remove(archive_path) + +def read_config_file(path): + """ Read a configuration file. """ + if os.path.exists(path): + fp = open(path, 'r') + data = fp.read() + fp.close() + else: + raise Exception("Path does not exist: %s" % (path)) + + # Parse the contents. + return eval(data, {'__builtins__': None}, None) + +def write_config_file(path, contents): + """ Write a configuration file. """ + msg('Writing file: %s' % path) + if not options.dryrun: + fp = open(path, 'w') + fp.write("{\n") + for key in sorted(contents.keys()): + fp.write(" '%s': '%s',\n" % (key, contents[key])) + fp.write("}\n") + fp.close() + +def read_branch_config_file(path): + """ Read the CEF branch from the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if os.path.isfile(config_file): + contents = read_config_file(config_file) + if 'branch' in contents: + return contents['branch'] + return '' + +def write_branch_config_file(path, branch): + """ Write the CEF branch to the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if not os.path.isfile(config_file): + write_config_file(config_file, {'branch': branch}) + +def remove_deps_entry(path, entry): + """ Remove an entry from the DEPS file at the specified path. """ + msg('Updating DEPS file: %s' % path) + if not options.dryrun: + if not os.path.isfile(path): + raise Exception('Path does not exist: %s' % path) + + # Read the DEPS file. + fp = open(path, 'r') + lines = fp.readlines() + fp.close() + + # Write the DEPS file. + # Each entry takes 2 lines. Skip both lines if found. + fp = open(path, 'w') + skip_next = False + for line in lines: + if skip_next: + skip_next = False + continue + elif line.find(entry) >= 0: + skip_next = True + continue + fp.write(line) + fp.close() + +def onerror(func, path, exc_info): + """ + Error handler for ``shutil.rmtree``. + + If the error is due to an access error (read only file) + it attempts to add write permission and then retries. + + If the error is for another reason it re-raises the error. + + Usage : ``shutil.rmtree(path, onerror=onerror)`` + """ + import stat + if not os.access(path, os.W_OK): + # Is the error an access error ? + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + +## +# Program entry point. +## + +# Cannot be loaded as a module. +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# Parse command-line options. +disc = """ +This utility implements automation for the download, update, build and +distribution of CEF. +""" + +parser = OptionParser(description=disc) + +# Setup options. +parser.add_option('--download-dir', dest='downloaddir', metavar='DIR', + help='Download directory with no spaces [required].') +parser.add_option('--depot-tools-dir', dest='depottoolsdir', metavar='DIR', + help='Download directory for depot_tools.', default='') +parser.add_option('--depot-tools-archive', dest='depottoolsarchive', + help='Zip archive file that contains a single top-level '+\ + 'depot_tools directory.', default='') +parser.add_option('--branch', dest='branch', + help='Branch of CEF to build (trunk, 1916, ...). This '+\ + 'will be used to name the CEF download directory and '+\ + 'to identify the correct URL if --url is not '+\ + 'specified. The default value is trunk.', + default='trunk') +parser.add_option('--url', dest='url', + help='CEF download URL. If not specified the default URL '+\ + 'will be used for the chosen branch.', + default='') +parser.add_option('--checkout', dest='checkout', + help='Version of CEF to checkout. If not specified the '+\ + 'most recent version of the branch will be used. '+\ + 'If --use-git is specified this should be a Git '+\ + 'branch/hash/tag instead of an SVN revision number.', + default='') +parser.add_option('--use-svn', + action='store_true', dest='usesvn', default=False, + help="Download CEF source code using SVN instead of Git.") +parser.add_option('--chromium-checkout', dest='chromiumcheckout', + help='Version of Chromium to checkout (Git '+\ + 'branch/hash/tag). This overrides the value specified '+\ + 'by CEF in CHROMIUM_BUILD_COMPATIBILITY.txt.', + default='') + +# Miscellaneous options. +parser.add_option('--force-config', + action='store_true', dest='forceconfig', default=False, + help='Force creation of a new gclient config file.') +parser.add_option('--force-clean', + action='store_true', dest='forceclean', default=False, + help='Force a clean CEF checkout. This will trigger a new '+\ + 'update, build and distribution.') +parser.add_option('--dry-run', + action='store_true', dest='dryrun', default=False, + help="Output commands without executing them.") + +# Update-related options. +parser.add_option('--force-update', + action='store_true', dest='forceupdate', default=False, + help='Force a Chromium and CEF update. This will trigger a '+\ + 'new build and distribution.') +parser.add_option('--no-update', + action='store_true', dest='noupdate', default=False, + help='Do not update Chromium or CEF. Pass --force-build or '+\ + '--force-distrib if you desire a new build or '+\ + 'distribution.') + +# Build-related options. +parser.add_option('--force-build', + action='store_true', dest='forcebuild', default=False, + help='Force CEF debug and release builds. This builds '+\ + 'cefclient on all platforms and chrome_sandbox on '+\ + 'Linux.') +parser.add_option('--no-build', + action='store_true', dest='nobuild', default=False, + help='Do not build CEF.') +parser.add_option('--build-tests', + action='store_true', dest='buildtests', default=False, + help='Also build the cef_unittests target.') +parser.add_option('--no-debug-build', + action='store_true', dest='nodebugbuild', default=False, + help="Don't perform the CEF debug build.") +parser.add_option('--no-release-build', + action='store_true', dest='noreleasebuild', default=False, + help="Don't perform the CEF release build.") +parser.add_option('--verbose-build', + action='store_true', dest='verbosebuild', default=False, + help='Show all command lines while building.') +parser.add_option('--build-log-file', + action='store_true', dest='buildlogfile', default=False, + help='Write build logs to file. The file will be named '+\ + '"build-[branch]-[debug|release].log" in the download '+\ + 'directory.') +parser.add_option('--x64-build', + action='store_true', dest='x64build', default=False, + help='Build for 64-bit systems (Windows and Mac OS X only).') + +# Distribution-related options. +parser.add_option('--force-distrib', + action='store_true', dest='forcedistrib', default=False, + help='Force creation of a CEF binary distribution.') +parser.add_option('--no-distrib', + action='store_true', dest='nodistrib', default=False, + help="Don't create a CEF binary distribution.") +parser.add_option('--minimal-distrib', + action='store_true', dest='minimaldistrib', default=False, + help='Create a minimal CEF binary distribution.') +parser.add_option('--minimal-distrib-only', + action='store_true', dest='minimaldistribonly', default=False, + help='Create a minimal CEF binary distribution only.') +parser.add_option('--client-distrib', + action='store_true', dest='clientdistrib', default=False, + help='Create a client CEF binary distribution.') +parser.add_option('--client-distrib-only', + action='store_true', dest='clientdistribonly', default=False, + help='Create a client CEF binary distribution only.') +parser.add_option('--no-distrib-docs', + action='store_true', dest='nodistribdocs', default=False, + help="Don't create CEF documentation.") +parser.add_option('--no-distrib-archive', + action='store_true', dest='nodistribarchive', default=False, + help="Don't create archives for output directories.") +parser.add_option('--clean-artifacts', + action='store_true', dest='cleanartifacts', default=False, + help='Clean the artifacts output directory.') + +(options, args) = parser.parse_args() + +if options.downloaddir is None: + print "The --download-dir option is required." + parser.print_help(sys.stderr) + sys.exit() + +if options.noupdate and options.forceupdate or \ + options.nobuild and options.forcebuild or \ + options.nodistrib and options.forcedistrib: + print "Invalid combination of options." + parser.print_help(sys.stderr) + sys.exit() + +if (options.noreleasebuild and \ + (options.minimaldistrib or options.minimaldistribonly or \ + options.clientdistrib or options.clientdistribonly)) or \ + (options.minimaldistribonly and options.clientdistribonly): + print 'Invalid combination of options.' + parser.print_help(sys.stderr) + sys.exit() + +if options.x64build and platform != 'windows' and platform != 'macosx': + print 'The x64 build option is only used on Windows and Mac OS X.' + sys.exit() + +if platform == 'windows' and not 'GYP_MSVS_VERSION' in os.environ.keys(): + print 'You must set the GYP_MSVS_VERSION environment variable on Windows.' + sys.exit() + +# Options that force the sources to change. +force_change = options.forceclean or options.forceupdate + + +## +# Manage the download directory. +## + +# Create the download directory if necessary. +download_dir = os.path.abspath(options.downloaddir) +create_directory(download_dir) + +msg("Download Directory: %s" % (download_dir)) + + +## +# Manage the depot_tools directory. +## + +# Check if the depot_tools directory exists. +if options.depottoolsdir != '': + depot_tools_dir = os.path.abspath(options.depottoolsdir) +else: + depot_tools_dir = os.path.join(download_dir, 'depot_tools') + +msg("Depot Tools Directory: %s" % (depot_tools_dir)) + +if not os.path.exists(depot_tools_dir): + if options.depottoolsarchive != '': + # Extract depot_tools from an archive file. + msg('Extracting %s to %s.' % \ + (options.depottoolsarchive, depot_tools_dir)) + if not options.dryrun: + download_and_extract(options.depottoolsarchive, depot_tools_dir, \ + 'depot_tools/') + else: + # Checkout depot_tools. + run('svn checkout '+depot_tools_url+' '+depot_tools_dir, download_dir) + +if not options.noupdate: + # Update depot_tools. It will download required scripts (svn, git, python). + if platform == 'windows': + run('update_depot_tools.bat', depot_tools_dir, depot_tools_dir); + else: + run('update_depot_tools', depot_tools_dir, depot_tools_dir); + +# Determine the svn/git executables to use. +if platform == 'windows': + # Force use of the version bundled with depot_tools. + svn_exe = os.path.join(depot_tools_dir, 'svn.bat') + git_exe = os.path.join(depot_tools_dir, 'git.bat') + if options.dryrun and (not os.path.exists(svn_exe) or \ + not os.path.exists(git_exe)): + sys.stdout.write("WARNING: --dry-run assumes that depot_tools" \ + " is already in your PATH. If it isn't\nplease" \ + " specify a --depot-tools-dir value.\n") + svn_exe = 'svn.bat' + git_exe = 'git.bat' +else: + svn_exe = 'svn' + git_exe = 'git' + + +## +# Manage the cef directory. +## + +# Validate the branch value. +if options.branch != 'trunk' and not options.branch.isdigit(): + raise Exception("Invalid branch value: %s" % (options.branch)) +cef_branch = options.branch + +cef_dir = os.path.join(download_dir, 'cef_' + cef_branch) + +# Delete the existing CEF directory if requested. +if options.forceclean and os.path.exists(cef_dir): + delete_directory(cef_dir) + +# Determine the type of CEF checkout to use. +if os.path.exists(cef_dir): + if is_git_checkout(cef_dir): + cef_use_git = True + elif is_svn_checkout(cef_dir): + cef_use_git = False + else: + raise Exception("Not a valid CEF checkout: %s" % (cef_dir)) + + if cef_use_git == options.usesvn: + raise Exception( + "The existing and requested CEF checkout types do not match") +else: + cef_use_git = not options.usesvn + +# Determine the CEF download URL to use. +if options.url == '': + if cef_branch == 'trunk': + if cef_use_git: + cef_url = cef_git_trunk_url + else: + cef_url = cef_svn_trunk_url + else: + if cef_use_git: + cef_url = cef_git_branch_url + else: + cef_url = cef_svn_branch_url + cef_url = cef_url.replace('%1', cef_branch) +else: + cef_url = options.url + +# Verify that the requested CEF URL matches the existing checkout. +if os.path.exists(cef_dir): + if cef_use_git: + cef_existing_url = get_git_url(cef_dir) + else: + cef_existing_url = get_svn_info(cef_dir)['url'] + if cef_url != cef_existing_url: + raise Exception('Requested CEF checkout URL %s does not match existing '+\ + 'URL %s' % (cef_url, cef_existing_url)) + +msg("CEF Branch: %s" % (cef_branch)) +msg("CEF URL: %s" % (cef_url)) +msg("CEF Source Directory: %s" % (cef_dir)) + +# Determine the CEF SVN revision or Git checkout to use. +if options.checkout == '': + # Use the CEF head revision. + if cef_use_git: + cef_checkout = 'master' + else: + cef_checkout = get_svn_info(cef_url)['revision'] +else: + cef_checkout = options.checkout + if not cef_use_git and not cef_checkout.isdigit(): + raise Exception("Invalid SVN revision number: %s" % (cef_checkout)) + +# Create the CEF checkout if necessary. +if not options.noupdate and not os.path.exists(cef_dir): + cef_checkout_new = True + if cef_use_git: + run('%s clone %s %s' % (git_exe, cef_url, cef_dir), download_dir, \ + depot_tools_dir) + else: + run('%s checkout %s -r %s %s' % (svn_exe, cef_url, cef_checkout, cef_dir), \ + download_dir, depot_tools_dir) +else: + cef_checkout_new = False + +# Verify the CEF checkout. +if not options.dryrun: + if cef_use_git and not is_git_checkout(cef_dir): + raise Exception('Not a valid git checkout: %s' % (cef_dir)) + if not cef_use_git and not is_svn_checkout(cef_dir): + raise Exception('Not a valid svn checkout: %s' % (cef_dir)) + +# Update the CEF checkout if necessary. +if not options.noupdate and os.path.exists(cef_dir): + if cef_use_git: + cef_current_hash = get_git_hash(cef_dir, 'HEAD') + cef_desired_hash = get_git_hash(cef_dir, cef_checkout) + cef_checkout_changed = cef_checkout_new or force_change or \ + cef_current_hash != cef_desired_hash + + msg("CEF Current Checkout: %s" % (cef_current_hash)) + msg("CEF Current Revision: %s" % \ + (get_git_svn_revision(cef_dir, cef_current_hash))) + msg("CEF Desired Checkout: %s (%s)" % (cef_desired_hash, cef_checkout)) + msg("CEF Desired Revision: %s" % \ + (get_git_svn_revision(cef_dir, cef_desired_hash))) + + if cef_checkout_changed: + if not cef_checkout_new: + # Fetch new sources. + run('%s fetch' % (git_exe), cef_dir, depot_tools_dir) + + # Checkout the requested branch. + run('%s checkout %s%s' % + (git_exe, ('--force ' if options.forceclean else ''), cef_checkout), \ + cef_dir, depot_tools_dir) + else: + cef_current_info = get_svn_info(cef_dir) + if cef_current_info['url'] != cef_url: + raise Exception("CEF URL does not match; found %s, expected %s" % + (cef_current_info['url'], cef_url)) + + cef_checkout_changed = cef_checkout_new or force_change or \ + cef_current_info['revision'] != cef_checkout + + msg("CEF Current Revision: %s" % (cef_current_info['revision'])) + msg("CEF Desired Revision: %s" % (cef_checkout)) + + if cef_checkout_changed and not cef_checkout_new: + # Update to the requested revision. + run('%s update -r %s' % (svn_exe, cef_checkout), cef_dir, depot_tools_dir) +else: + cef_checkout_changed = False + + +## +# Manage the out directory. +## + +out_dir = os.path.join(download_dir, 'out_' + cef_branch) + +# Delete the existing out directory if requested. +if options.forceclean and os.path.exists(out_dir): + delete_directory(out_dir) + +msg("CEF Output Directory: %s" % (out_dir)) + + +## +# Manage the chromium directory. +## + +# Create the chromium directory if necessary. +chromium_dir = os.path.join(download_dir, 'chromium') +create_directory(chromium_dir) + +chromium_src_dir = os.path.join(chromium_dir, 'src') +cef_src_dir = os.path.join(chromium_src_dir, 'cef') +out_src_dir = os.path.join(chromium_src_dir, 'out') + +# Create gclient configuration file. +gclient_file = os.path.join(chromium_dir, '.gclient') +if not os.path.exists(gclient_file) or options.forceconfig: + # Exclude unnecessary directories. Intentionally written without newlines. + gclient_spec = \ + "solutions = [{"+\ + "u'managed': False,"+\ + "u'name': u'src', "+\ + "u'url': u'https://chromium.googlesource.com/chromium/src.git', "+\ + "u'custom_deps': {"+\ + "u'build': None, "+\ + "u'build/scripts/command_wrapper/bin': None, "+\ + "u'build/scripts/gsd_generate_index': None, "+\ + "u'build/scripts/private/data/reliability': None, "+\ + "u'build/third_party/lighttpd': None, "+\ + "u'commit-queue': None, "+\ + "u'depot_tools': None, "+\ + "u'src/chrome_frame/tools/test/reference_build/chrome': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_linux': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_mac': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_win': None, "+\ + "}, "+\ + "u'deps_file': u'.DEPS.git', "+\ + "u'safesync_url': u''"+\ + "}]" + + msg('Writing file: %s' % gclient_file) + if not options.dryrun: + fp = open(gclient_file, 'w') + fp.write(gclient_spec) + fp.close() + +# Initial Chromium checkout. +if not options.noupdate and not os.path.exists(chromium_src_dir): + chromium_checkout_new = True + run("gclient sync --nohooks --with_branch_heads --jobs 16", chromium_dir, \ + depot_tools_dir) +else: + chromium_checkout_new = False + +# Verify the Chromium checkout. +if not options.dryrun and not is_git_checkout(chromium_src_dir): + raise Exception('Not a valid git checkout: %s' % (chromium_src_dir)) + +if os.path.exists(chromium_src_dir): + msg("Chromium URL: %s" % (get_git_url(chromium_src_dir))) + +# Determine the Chromium checkout options required by CEF. +chromium_nohooks = False +if options.chromiumcheckout == '': + # Read the build compatibility file to identify the checkout name. + compat_path = os.path.join(cef_dir, 'CHROMIUM_BUILD_COMPATIBILITY.txt') + config = read_config_file(compat_path) + + if 'chromium_checkout' in config: + chromium_checkout = config['chromium_checkout'] + else: + raise Exception("Missing chromium_checkout value in %s" % (compat_path)) + + # Some branches run hooks using CEF instead of Chromium. + if 'chromium_nohooks' in config: + chromium_nohooks = config['chromium_nohooks'] +else: + chromium_checkout = options.chromiumcheckout + +# Determine if the Chromium checkout needs to change. +if not options.noupdate and os.path.exists(chromium_src_dir): + chromium_current_hash = get_git_hash(chromium_src_dir, 'HEAD') + chromium_desired_hash = get_git_hash(chromium_src_dir, chromium_checkout) + chromium_checkout_changed = chromium_checkout_new or force_change or \ + chromium_current_hash != chromium_desired_hash + + msg("Chromium Current Checkout: %s" % (chromium_current_hash)) + msg("Chromium Current Revision: %s" % \ + (get_git_svn_revision(chromium_src_dir, chromium_current_hash))) + msg("Chromium Desired Checkout: %s (%s)" % \ + (chromium_desired_hash, chromium_checkout)) + msg("Chromium Desired Revision: %s" % \ + (get_git_svn_revision(chromium_src_dir, chromium_desired_hash))) +else: + chromium_checkout_changed = options.dryrun + +# Delete the existing src/cef directory. It will be re-copied from the download +# directory later. +if cef_checkout_changed and os.path.exists(cef_src_dir): + delete_directory(cef_src_dir) + +# Delete the existing src/out directory if requested. +if options.forceclean and os.path.exists(out_src_dir): + delete_directory(out_src_dir) + +# Move the existing src/out directory to the correct location in the download +# directory. It will be moved back from the download directory later. +if os.path.exists(out_src_dir): + old_branch = read_branch_config_file(out_src_dir) + if chromium_checkout_changed or old_branch != cef_branch: + old_out_dir = os.path.join(download_dir, 'out_' + old_branch) + move_directory(out_src_dir, old_out_dir) + +# Update the Chromium checkout. +if chromium_checkout_changed: + if not chromium_checkout_new: + # Revert all changes in the Chromium checkout. + run("gclient revert --nohooks", chromium_dir, depot_tools_dir) + + # Fetch new sources. + run("%s fetch" % (git_exe), chromium_src_dir, depot_tools_dir) + + # Checkout the requested branch. + run("%s checkout %s%s" % \ + (git_exe, ('--force ' if options.forceclean else ''), chromium_checkout), \ + chromium_src_dir, depot_tools_dir) + + if cef_branch != 'trunk': + # Remove the 'src' entry from .DEPS.git for release branches. + # Otherwise, `gclient sync` will fail. + deps_path = os.path.join(chromium_src_dir, '.DEPS.git') + remove_deps_entry(deps_path, "'src'") + + # Update third-party dependencies including branch/tag information. + run("gclient sync %s%s--with_branch_heads --jobs 16" % \ + (('--reset ' if options.forceclean else ''), \ + ('--nohooks ' if chromium_nohooks else '')), \ + chromium_dir, depot_tools_dir) + + # Delete the src/out directory created by `gclient sync`. + delete_directory(out_src_dir) + +# Restore the src/cef directory. +if os.path.exists(cef_dir) and not os.path.exists(cef_src_dir): + copy_directory(cef_dir, cef_src_dir) + +# Restore the src/out directory. +if os.path.exists(out_dir) and not os.path.exists(out_src_dir): + move_directory(out_dir, out_src_dir) + + +## +# Build CEF. +## + +if not options.nobuild and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcebuild or \ + not os.path.exists(out_src_dir)): + # Building should also force a distribution. + options.forcedistrib = True + + # Run the cef_create_projects script to generate Ninja project files. + os.environ['GYP_GENERATORS'] = 'ninja' + if options.x64build: + if 'GYP_DEFINES' in os.environ.keys(): + os.environ['GYP_DEFINES'] = os.environ['GYP_DEFINES'] + ' ' + \ + 'target_arch=x64' + else: + os.environ['GYP_DEFINES'] = 'target_arch=x64' + path = os.path.join(cef_src_dir, 'cef_create_projects'+script_ext) + run(path, cef_src_dir, depot_tools_dir) + + # Write the config file for identifying the branch. + write_branch_config_file(out_src_dir, cef_branch) + + # Build using Ninja. + command = 'ninja -C ' + if options.verbosebuild: + command = 'ninja -v -C' + target = ' cefclient' + if options.buildtests: + target = target + ' cef_unittests' + if platform == 'linux': + target = target + ' chrome_sandbox' + build_dir_suffix = '' + if platform == 'windows' and options.x64build: + build_dir_suffix = '_x64' + + if not options.nodebugbuild: + # Make a CEF Debug build. + run(command + os.path.join('out', 'Debug' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-debug.log' % (cef_branch)) \ + if options.buildlogfile else None) + + if not options.noreleasebuild: + # Make a CEF Release build. + run(command + os.path.join('out', 'Release' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-release.log' % (cef_branch)) \ + if options.buildlogfile else None) + + +## +# Create the CEF binary distribution. +## + +if not options.nodistrib and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcedistrib): + if not options.forceclean and options.cleanartifacts: + # Clean the artifacts output directory. + artifacts_path = os.path.join(cef_src_dir, 'binary_distrib') + delete_directory(artifacts_path) + + # Determine the requested distribution types. + distrib_types = [] + if options.minimaldistribonly: + distrib_types.append('minimal') + elif options.clientdistribonly: + distrib_types.append('client') + else: + distrib_types.append('standard') + if options.minimaldistrib: + distrib_types.append('minimal') + if options.clientdistrib: + distrib_types.append('client') + + cef_tools_dir = os.path.join(cef_src_dir, 'tools') + + # Create the requested distribution types. + first_type = True + for type in distrib_types: + path = os.path.join(cef_tools_dir, 'make_distrib'+script_ext) + if options.nodebugbuild or options.noreleasebuild or type != 'standard': + path = path + ' --allow-partial' + path = path + ' --ninja-build' + if options.x64build: + path = path + ' --x64-build' + + if type == 'minimal': + path = path + ' --minimal' + elif type == 'client': + path = path + ' --client' + + if first_type: + if options.nodistribdocs: + path = path + ' --no-docs' + if options.nodistribarchive: + path = path + ' --no-archive' + first_type = False + else: + # Don't create the symbol archives or documentation more than once. + path = path + ' --no-symbols --no-docs' + + # Create the distribution. + run(path, cef_tools_dir, depot_tools_dir) diff --git a/tools/automate/automate.README.txt b/tools/automate/automate.README.txt new file mode 100644 index 000000000..505be746a --- /dev/null +++ b/tools/automate/automate.README.txt @@ -0,0 +1,99 @@ +Chromium Embedded Framework (CEF) Automation Tool +------------------------------------------------------------------------------- + +Document Last Updated: October 10, 2011 + + +OVERVIEW +-------- + +The CEF Automation Tool can perform the following actions in an automated manner: + +1. Download/update the Chromium and CEF source code. +2. Build the CEF Debug and Release targets. +3. Create the CEF binary distribution package. + + +SETUP +----- + +1. Install Subversion [1] and Python [2]. Make sure the bin directories for both + programs are discoverable via your system PATH configuration. On Windows + install CppDoc [3] in the default location (assumes a 64bit version of + Windows 7). + +2. Install build tools. On Windows install Visual Studio 2008 or newer and all + required prerequisite software [4]. On Mac install Xcode 3.2 or newer. + +3. Configure the GYP environment. On Windows set the GYP_MSVS_VERSION + environment variable to "2008" or "2010" depending on which version of Visual + Studio you're building with. On Mac Lion set the GYP_DEFINES environment + variable to 'mac_sdk=10.6'. + +4. Checkout the "automate" folder to a location on your hard drive. For the + trunk version of CEF you can use the following command: + + svn checkout http://chromiumembedded.googlecode.com/svn/trunk/cef3/tools/automate /path/to/automate + +5. Run the automate.py script at whatever interval is appropriate (for each + CEF commit, once per day, once per week, etc): + + python /path/to/automate/automate.py --download-dir=/path/to/download + + +HOW IT WORKS +------------ + +The automate.py script performs the following actions in the download directory +specified by the "--download-dir" flag. This path value must contain no spaces. + +1. Retrieve the Chromium URL and revision associated with a CEF URL and + revision. A specific CEF URL and revision can be specified using the "--url" + and "--revision" flags. Otherwise, the current CEF trunk URL [7] and HEAD + revision will be used. The Chromium URL and revision are retrieved by + querying the SVN repository for a CHROMIUM_BUILD_COMPATIBILITY.txt file. + +2. If a "depot_tools" folder does not already exist download depot_tools [5]. + The depot_tools folder will be added to the beginning of the PATH to support + execution of the below steps. + +3. If a "chromium" folder does not already exist create it and configure + gclient [6] using the Chromium URL retrieved in step 1. To force execution of + this step use the "--force-config" flag. + +4. If the "--force-clean" flag is specified all Chromium changes will be + reverted, all unversioned files including the CEF folder will be deleted and + steps 6-10 will be triggered automatically. + +5. If both Chromium and CEF are already at the correct URL and revision the + script will exit at this point. To force execution of steps 6-8 use the + "--force-update" flag. To force execution of step 9 use the "--force-build" + flag. To force execution of step 10 use the "--force-distrib" flag. + +6. Use gclient [6] to update the Chromium source code to the correct revision. + +7. If a "chromium/src/cef" folder does not already exist download the CEF source + code at the correct revision. Otherwise, update CEF source code to the + correct revision. + +8. Run the "chromium/src/cef/cef_create_projects.[sh|bat]" script to apply CEF + patches and generate CEF project files. + +9. Run the "chromium/src/cef/tools/build_projects.[sh|bat]" script twice; once + to build the Debug target and once to build the Release target. + +10.Run the "chromium/src/cef/tools/make_distrib.[sh|bat]" script to build the + binary distribution package. The resulting package will be output in a + "chromium/src/cef/binary_distrib/cef_binary_rXXX_[windows|macosx]" folder. + + +REFERENCES +---------- + +[1] http://subversion.apache.org/ +[2] http://www.python.org/ +[3] http://www.cppdoc.com/ +[4] http://dev.chromium.org/developers/how-tos/build-instructions-windows +[5] http://dev.chromium.org/developers/how-tos/depottools +[6] http://dev.chromium.org/developers/how-tos/get-the-code +[7] http://chromiumembedded.googlecode.com/svn/trunk/cef3 diff --git a/tools/automate/automate.py b/tools/automate/automate.py new file mode 100644 index 000000000..75588334f --- /dev/null +++ b/tools/automate/automate.py @@ -0,0 +1,643 @@ +# 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. + +from optparse import OptionParser +import httplib +import os +import re +import shlex +import shutil +import subprocess +import sys +import tempfile +import urllib +import xml.etree.ElementTree as ET +import zipfile + +# default URL values +cef_url = 'http://chromiumembedded.googlecode.com/svn/trunk/cef3' +depot_tools_url = 'http://src.chromium.org/svn/trunk/tools/depot_tools' + +def run(command_line, working_dir, depot_tools_dir=None, output_file=None): + # add depot_tools to the path + env = os.environ + if not depot_tools_dir is None: + env['PATH'] = depot_tools_dir+os.pathsep+env['PATH'] + + sys.stdout.write('-------- Running "'+command_line+'" in "'+\ + working_dir+'"...'+"\n") + if not options.dryrun: + args = shlex.split(command_line.replace('\\', '\\\\')) + + if not output_file: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32')) + with open(output_file, "w") as f: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32'), + stderr=subprocess.STDOUT, stdout=f) + +def check_url(url): + """ Check the URL and raise an exception if invalid. """ + if ':' in url[:7]: + parts = url.split(':', 1) + if (parts[0] == 'http' or parts[0] == 'https') and \ + parts[1] == urllib.quote(parts[1]): + return url + sys.stderr.write('Invalid URL: '+url+"\n") + raise Exception('Invalid URL: '+url) + +def get_svn_info(path): + """ Retrieves the URL and revision from svn info. """ + url = 'None' + rev = 'None' + sys.stdout.write("-------- Running \"%s info --xml %s\"...\n" % (svn_exe, path)) + if path[0:4] == 'http' or os.path.exists(path): + try: + p = subprocess.Popen([svn_exe, 'info', '--xml', path], \ + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + if err == '': + tree = ET.ElementTree(ET.fromstring(out)) + entry = tree.getroot().find('entry') + url = entry.find('url').text + rev = entry.attrib['revision'] + else: + raise Exception("Failed to execute svn info:\n"+err+"\n") + except IOError, (errno, strerror): + sys.stderr.write('Failed to read svn info: '+strerror+"\n") + raise + except: + raise + return {'url': url, 'revision': rev} + +def download_and_extract(src, target, contents_prefix): + """ Extracts the contents of src, which may be a URL or local file, to the + target directory. """ + sys.stdout.write('Extracting %s to %s.\n' % (src, target)) + temporary = False + + if src[:4] == 'http': + # Attempt to download a URL. + opener = urllib.FancyURLopener({}) + response = opener.open(src) + + temporary = True + handle, archive_path = tempfile.mkstemp(suffix = '.zip') + os.write(handle, response.read()) + os.close(handle) + elif os.path.exists(src): + # Use a local file. + archive_path = src + else: + raise Exception('Path type is unsupported or does not exist: ' + src) + + if not zipfile.is_zipfile(archive_path): + raise Exception('Not a valid zip archive: ' + src) + + def remove_prefix(zip, prefix): + offset = len(prefix) + for zipinfo in zip.infolist(): + name = zipinfo.filename + if len(name) > offset and name[:offset] == prefix: + zipinfo.filename = name[offset:] + yield zipinfo + + # Attempt to extract the archive file. + try: + os.makedirs(target) + zf = zipfile.ZipFile(archive_path, 'r') + zf.extractall(target, remove_prefix(zf, contents_prefix)) + except: + shutil.rmtree(target, onerror=onerror) + raise + zf.close() + + # Delete the archive file if temporary. + if temporary and os.path.exists(archive_path): + os.remove(archive_path) + +def onerror(func, path, exc_info): + """ + Error handler for ``shutil.rmtree``. + + If the error is due to an access error (read only file) + it attempts to add write permission and then retries. + + If the error is for another reason it re-raises the error. + + Usage : ``shutil.rmtree(path, onerror=onerror)`` + """ + import stat + if not os.access(path, os.W_OK): + # Is the error an access error ? + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# parse command-line options +disc = """ +This utility implements automation for the download, update, build and +distribution of CEF. +""" + +parser = OptionParser(description=disc) +parser.add_option('--download-dir', dest='downloaddir', metavar='DIR', + help='download directory with no spaces [required]') +parser.add_option('--revision', dest='revision', type="int", + help='CEF source revision') +parser.add_option('--url', dest='url', + help='CEF source URL') +parser.add_option('--depot-tools', dest='depottools', metavar='DIR', + help='download directory for depot_tools', default='') +parser.add_option('--depot-tools-archive', dest='depottoolsarchive', + help='zip archive file that contains a single top-level '+\ + 'depot_tools directory', default='') +parser.add_option('--force-config', + action='store_true', dest='forceconfig', default=False, + help='force Chromium configuration') +parser.add_option('--force-clean', + action='store_true', dest='forceclean', default=False, + help='force revert of all Chromium changes, deletion of '+\ + 'all unversioned files including the CEF folder and '+\ + 'trigger the force-update, force-build and '+\ + 'force-distrib options') +parser.add_option('--force-update', + action='store_true', dest='forceupdate', default=False, + help='force Chromium and CEF update') +parser.add_option('--no-update', + action='store_true', dest='noupdate', default=False, + help='do not update Chromium and CEF.' +\ + 'Cannot be used along with --force[update|config|clean]') +parser.add_option('--force-build', + action='store_true', dest='forcebuild', default=False, + help='force CEF debug and release builds') +parser.add_option('--build-tests', + action='store_true', dest='buildtests', default=False, + help='build cef_unittests target besides cefclient') +parser.add_option('--force-distrib', + action='store_true', dest='forcedistrib', default=False, + help='force creation of CEF binary distribution') +parser.add_option('--no-debug-build', + action='store_true', dest='nodebugbuild', default=False, + help="don't perform the CEF debug build") +parser.add_option('--no-release-build', + action='store_true', dest='noreleasebuild', default=False, + help="don't perform the CEF release build") +parser.add_option('--no-distrib', + action='store_true', dest='nodistrib', default=False, + help="don't create any CEF binary distribution") +parser.add_option('--minimal-distrib', + action='store_true', dest='minimaldistrib', default=False, + help='create a minimal CEF binary distribution') +parser.add_option('--minimal-distrib-only', + action='store_true', dest='minimaldistribonly', default=False, + help='create a minimal CEF binary distribution only') +parser.add_option('--client-distrib', + action='store_true', dest='clientdistrib', default=False, + help='create a client CEF binary distribution') +parser.add_option('--client-distrib-only', + action='store_true', dest='clientdistribonly', default=False, + help='create a client CEF binary distribution only') +parser.add_option('--no-distrib-docs', + action='store_true', dest='nodistribdocs', default=False, + help="don't create CEF documentation") +parser.add_option('--no-distrib-archive', + action='store_true', dest='nodistribarchive', default=False, + help="don't create archives for output directories") +parser.add_option('--ninja-build', + action='store_true', dest='ninjabuild', default=False, + help="build using ninja") +parser.add_option('--verbose', + action='store_true', dest='verbose', default=False, + help='show all command lines while building') +parser.add_option('--build-log-file', + action='store_true', dest='buildlogfile', default=False, + help='write build logs to files') +parser.add_option('--x64-build', + action='store_true', dest='x64build', default=False, + help='build for 64-bit systems (Windows and Mac OS X only)') +parser.add_option('--clean-artifacts', + action='store_true', dest='cleanartifacts', default=False, + help='clean the artifacts output directory') +parser.add_option('--dry-run', + action='store_true', dest='dryrun', default=False, + help="output commands without executing them") +(options, args) = parser.parse_args() + +# Test the operating system. +platform = ''; +if sys.platform == 'win32': + platform = 'windows' +elif sys.platform == 'darwin': + platform = 'macosx' +elif sys.platform.startswith('linux'): + platform = 'linux' + +# the downloaddir option is required +if options.downloaddir is None: + parser.print_help(sys.stderr) + sys.exit() + +if (options.noreleasebuild and (options.minimaldistrib or options.minimaldistribonly or \ + options.clientdistrib or options.clientdistribonly)) or \ + (options.minimaldistribonly and options.clientdistribonly): + print 'Invalid combination of options' + parser.print_help(sys.stderr) + sys.exit() + +if options.noupdate and (options.forceclean or options.forceupdate or options.forceconfig): + print "Invalid combination of options." + print "--no-update cannot be used along with --force-[update|config|clean]\n" + sys.exit() + +if options.x64build and platform != 'windows' and platform != 'macosx': + print 'The x64 build option is only used on Windows and Mac OS X.' + sys.exit() + +if options.x64build and platform == 'windows' and not options.ninjabuild: + print 'The x64 build option on Windows requires ninja.' + sys.exit() + +# script directory +script_dir = os.path.dirname(__file__) + +download_dir = os.path.abspath(options.downloaddir) +if not options.dryrun and not os.path.exists(download_dir): + # create the download directory + os.makedirs(download_dir) + +# set the expected script extension +if platform == 'windows': + script_ext = '.bat' +else: + script_ext = '.sh' + +# check if the "depot_tools" directory exists +if options.depottools != '': + depot_tools_dir = os.path.abspath(options.depottools) +else: + depot_tools_dir = os.path.join(download_dir, 'depot_tools') +if not os.path.exists(depot_tools_dir): + if options.depottoolsarchive != '': + # extract depot_tools from an archive file + download_and_extract(options.depottoolsarchive, depot_tools_dir, + 'depot_tools/') + else: + # checkout depot_tools + run('svn checkout '+depot_tools_url+' '+depot_tools_dir, download_dir) + +if not options.noupdate: + # Update depot_tools. It will download required scripts (svn, python, ...) + if platform == 'windows': + run('update_depot_tools.bat', depot_tools_dir, depot_tools_dir); + else: + run('update_depot_tools', depot_tools_dir, depot_tools_dir); + +if platform == 'windows': + # Force use of the SVN version bundled with depot_tools. + svn_exe = os.path.join(depot_tools_dir, 'svn.bat') + if options.dryrun and not os.path.exists(svn_exe): + sys.stdout.write("WARNING: --dry-run assumes that depot_tools" \ + " is already in your PATH. If it isn't\nplease" \ + " specify a --depot-tools value.\n") + svn_exe = 'svn.bat' +else: + svn_exe = 'svn' + +if not options.url is None: + # set the CEF URL + cef_url = check_url(options.url) + +if not options.revision is None: + # set the CEF revision + cef_rev = str(options.revision) +else: + # retrieve the CEF revision from the remote repo + info = get_svn_info(cef_url) + cef_rev = info['revision'] + if cef_rev == 'None': + sys.stderr.write('No SVN info for: '+cef_url+"\n") + raise Exception('No SVN info for: '+cef_url) + +# Retrieve the Chromium URL and revision from the CEF repo +compat_url = cef_url + "/CHROMIUM_BUILD_COMPATIBILITY.txt?r="+cef_rev + +release_url = None +chromium_url = None +chromium_rev = None + +try: + # Read the remote URL contents + handle = urllib.urlopen(compat_url) + compat_value = handle.read().strip() + handle.close() + + # Parse the contents + config = eval(compat_value, {'__builtins__': None}, None) + + if 'release_url' in config: + # building from a release + release_url = check_url(config['release_url']) + else: + # building from chromium src + if not 'chromium_url' in config: + raise Exception("Missing chromium_url value") + if not 'chromium_revision' in config: + raise Exception("Missing chromium_revision value") + + chromium_url = check_url(config['chromium_url']) + chromium_rev = str(int(config['chromium_revision'])) +except Exception, e: + sys.stderr.write('Failed to read URL and revision information from '+ \ + compat_url+"\n") + raise + +# check if the "chromium" directory exists +chromium_dir = os.path.join(download_dir, 'chromium') +if not options.dryrun and not os.path.exists(chromium_dir): + # create the "chromium" directory + os.makedirs(chromium_dir) + +chromium_src_dir = os.path.join(chromium_dir, 'src') +cef_src_dir = os.path.join(chromium_src_dir, 'cef') +cef_tools_dir = os.path.join(cef_src_dir, 'tools') + +# retrieve the current CEF URL and revision +info = get_svn_info(cef_src_dir) +current_cef_url = info['url'] +current_cef_rev = info['revision'] + +if release_url is None: + # retrieve the current Chromium URL and revision + info = get_svn_info(chromium_src_dir) + current_chromium_url = info['url'] + current_chromium_rev = info['revision'] + +changed_to_message = ' -> CHANGED TO: ' +if options.noupdate: + changed_to_message = ' -> AVAILABLE: ' + +# test if the CEF URL changed +cef_url_changed = current_cef_url != cef_url +sys.stdout.write('CEF URL: '+current_cef_url+"\n") +if cef_url_changed: + sys.stdout.write(changed_to_message+cef_url+"\n") + +# test if the CEF revision changed +cef_rev_changed = current_cef_rev != cef_rev +sys.stdout.write('CEF Revision: '+current_cef_rev+"\n") +if cef_rev_changed: + sys.stdout.write(changed_to_message+cef_rev+"\n") + +release_url_changed = False +chromium_url_changed = False +chromium_rev_changed = False + +if release_url is None: + # test if the Chromium URL changed + chromium_url_changed = current_chromium_url != chromium_url + sys.stdout.write('Chromium URL: '+current_chromium_url+"\n") + if chromium_url_changed: + sys.stdout.write(changed_to_message+chromium_url+"\n") + + # test if the Chromium revision changed + chromium_rev_changed = current_chromium_rev != chromium_rev + sys.stdout.write('Chromium Revision: '+current_chromium_rev+"\n") + if chromium_rev_changed: + sys.stdout.write(changed_to_message+chromium_rev+"\n") +else: + # test if the release URL changed + current_release_url = 'None' + + path = os.path.join(chromium_dir, '.gclient') + if os.path.exists(path): + # read the .gclient file + fp = open(path, 'r') + data = fp.read() + fp.close() + + # Parse the contents + config_dict = {} + try: + exec(data, config_dict) + current_release_url = config_dict['solutions'][0]['url'] + except Exception, e: + sys.stderr.write('Failed to parse existing .glient file.\n') + raise + + release_url_changed = current_release_url != release_url + sys.stdout.write('Release URL: '+current_release_url+"\n") + if release_url_changed: + sys.stdout.write(changed_to_message+release_url+"\n") + +# true if anything changed +any_changed = release_url_changed or chromium_url_changed or \ + chromium_rev_changed or cef_url_changed or cef_rev_changed +if not any_changed: + sys.stdout.write("No changes.\n") +elif options.noupdate: + sys.stdout.write("You have updates. Remove --no-update flag to update source code\n") + release_url_changed = False + chromium_url_changed = False + chromium_rev_changed = False + cef_url_changed = False + cef_rev_changed = False + any_changed = False + + +if release_url_changed or chromium_url_changed or options.forceconfig: + if release_url is None: + url = chromium_url + else: + url = release_url + + # run gclient config to create the .gclient file + run('gclient config '+url, chromium_dir, depot_tools_dir) + + if not options.dryrun: + path = os.path.join(chromium_dir, '.gclient') + if not os.path.exists(path): + sys.stderr.write(".gclient file was not created\n") + raise Exception('.gclient file was not created') + + # read the resulting .gclient file + fp = open(path, 'r') + data = fp.read() + fp.close() + + custom_deps = \ + "\n "+'"src/third_party/WebKit/LayoutTests": None,'+\ + "\n "+'"src/chrome_frame/tools/test/reference_build/chrome": None,'+\ + "\n "+'"src/chrome/tools/test/reference_build/chrome_mac": None,'+\ + "\n "+'"src/chrome/tools/test/reference_build/chrome_win": None,'+\ + "\n "+'"src/chrome/tools/test/reference_build/chrome_linux": None,' + + if not release_url is None: + # TODO: Read the DEPS file and exclude all non-src directories. + custom_deps += \ + "\n "+'"chromeos": None,'+\ + "\n "+'"depot_tools": None,' + + # populate "custom_deps" section + data = data.replace('"custom_deps" : {', '"custom_deps" : {'+custom_deps) + + # write the new .gclient file + fp = open(path, 'w') + fp.write(data) + fp.close() + +if options.forceclean: + if os.path.exists(chromium_src_dir): + # revert all Chromium changes and delete all unversioned files + run('gclient revert -n', chromium_dir, depot_tools_dir) + + if not options.dryrun: + # remove the build output directories + output_dirs = [] + if platform == 'windows': + output_dirs.append(os.path.join(chromium_src_dir, 'build\\Debug')) + output_dirs.append(os.path.join(chromium_src_dir, 'build\\Release')) + elif platform == 'macosx': + output_dirs.append(os.path.join(chromium_src_dir, 'xcodebuild')) + elif platform == 'linux': + output_dirs.append(os.path.join(chromium_src_dir, 'out')) + + if options.ninjabuild: + output_dirs.append(os.path.join(chromium_src_dir, 'out')) + + for output_dir in output_dirs: + if os.path.exists(output_dir): + shutil.rmtree(output_dir, onerror=onerror) + + # force update, build and distrib steps + options.forceupdate = True + options.forcebuild = True + options.forcedistrib = True + +if release_url is None: + if chromium_url_changed or chromium_rev_changed or options.forceupdate: + # download/update the Chromium source code + run('gclient sync --revision src@'+chromium_rev+' --jobs 8 --force', \ + chromium_dir, depot_tools_dir) +elif release_url_changed or options.forceupdate: + # download/update the release source code + run('gclient sync --jobs 8 --force', chromium_dir, depot_tools_dir) + +if not os.path.exists(cef_src_dir) or cef_url_changed: + if not options.dryrun and cef_url_changed and os.path.exists(cef_src_dir): + # delete the cef directory (it will be re-downloaded) + shutil.rmtree(cef_src_dir) + + # download the CEF source code + run(svn_exe+' checkout '+cef_url+' -r '+cef_rev+' '+cef_src_dir, download_dir) +elif cef_rev_changed or options.forceupdate: + # update the CEF source code + run(svn_exe+' update -r '+cef_rev+' '+cef_src_dir, download_dir) + +if any_changed or options.forceupdate: + # create CEF projects + if options.ninjabuild: + os.environ['GYP_GENERATORS'] = 'ninja' + if options.x64build: + if 'GYP_DEFINES' in os.environ.keys(): + os.environ['GYP_DEFINES'] = os.environ['GYP_DEFINES'] + ' ' + 'target_arch=x64' + else: + os.environ['GYP_DEFINES'] = 'target_arch=x64' + path = os.path.join(cef_src_dir, 'cef_create_projects'+script_ext) + run(path, cef_src_dir, depot_tools_dir) + +if any_changed or options.forcebuild: + if options.ninjabuild: + command = 'ninja -C ' + if options.verbose: + command = 'ninja -v -C' + target = ' cefclient' + if options.buildtests: + target = target + ' cef_unittests' + if platform == 'linux': + target = target + ' chrome_sandbox' + build_dir_suffix = '' + if platform == 'windows' and options.x64build: + build_dir_suffix = '_x64' + + if not options.nodebugbuild: + # make CEF Debug build + run(command + os.path.join('out', 'Debug' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(chromium_src_dir, 'ninja-build-debug.log') if options.buildlogfile else None) + + if not options.noreleasebuild: + # make CEF Release build + run(command + os.path.join('out', 'Release' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(chromium_src_dir, 'ninja-build-release.log') if options.buildlogfile else None) + else: + path = os.path.join(cef_tools_dir, 'build_projects'+script_ext) + + if not options.nodebugbuild: + # make CEF Debug build + run(path+' Debug', cef_tools_dir, depot_tools_dir, + os.path.join(chromium_src_dir, 'build-debug.log') if options.buildlogfile else None) + + if not options.noreleasebuild: + # make CEF Release build + run(path+' Release', cef_tools_dir, depot_tools_dir, + os.path.join(chromium_src_dir, 'build-release.log') if options.buildlogfile else None) + +if (any_changed or options.forcedistrib) and not options.nodistrib: + if not options.forceclean and options.cleanartifacts: + # clean the artifacts output directory + artifacts_path = os.path.join(cef_src_dir, 'binary_distrib') + if os.path.exists(artifacts_path): + shutil.rmtree(artifacts_path, onerror=onerror) + + # determine the requested distribution types + distrib_types = [] + if options.minimaldistribonly: + distrib_types.append('minimal') + elif options.clientdistribonly: + distrib_types.append('client') + else: + distrib_types.append('standard') + if options.minimaldistrib: + distrib_types.append('minimal') + if options.clientdistrib: + distrib_types.append('client') + + first_type = True + + # create the requested distribution types + for type in distrib_types: + path = os.path.join(cef_tools_dir, 'make_distrib'+script_ext) + if options.nodebugbuild or options.noreleasebuild or type != 'standard': + path = path + ' --allow-partial' + if options.ninjabuild: + path = path + ' --ninja-build' + if options.x64build: + path = path + ' --x64-build' + + if type == 'minimal': + path = path + ' --minimal' + elif type == 'client': + path = path + ' --client' + + if first_type: + if options.nodistribdocs: + path = path + ' --no-docs' + if options.nodistribarchive: + path = path + ' --no-archive' + first_type = False + else: + # don't create the symbol archives or documentation more than once + path = path + ' --no-symbols --no-docs' + + # create the distribution + run(path, cef_tools_dir, depot_tools_dir) diff --git a/tools/automate/gitsvnmirror.py b/tools/automate/gitsvnmirror.py new file mode 100644 index 000000000..32334a407 --- /dev/null +++ b/tools/automate/gitsvnmirror.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# 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. + +import httplib +from optparse import OptionParser +import os +import re +import shlex +import subprocess +import sys +import urllib +import urlparse + +# Cannot be loaded as a module. +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +def run(command_line, working_dir): + """ Run the specified command line. """ + if not options.quiet: + print '-------- Running "%s" in "%s"...' % (command_line, working_dir) + if not options.dryrun: + args = shlex.split(command_line.replace('\\', '\\\\')) + return subprocess.check_call(args, cwd=working_dir, env=os.environ, + shell=(sys.platform == 'win32')) + +def fail(message): + """ Exit the script due to an execution failure. """ + print message + sys.exit(1) + +def url_request(url, method, headers, body, expected_response): + """ Execute an arbitrary request. """ + parsed_url = urlparse.urlparse(url) + if parsed_url.scheme == "http": + connection = httplib.HTTPConnection(parsed_url.netloc) + elif parsed_url.scheme == "https": + connection = httplib.HTTPSConnection(parsed_url.netloc) + else: + print 'Unsupported URL format for %s' % url + return None + + connection.putrequest(method, url) + + if not headers is None: + for key, val in headers.iteritems(): + connection.putheader(key, val) + if not body is None: + connection.putheader('Content-Length', len(body)) + connection.endheaders() + + if not body is None: + connection.send(body) + + response = connection.getresponse() + if response.status == expected_response: + return response.read() + else: + print 'URL %s returned unexpected response code %d' % \ + (url, response.status) + return None + +def url_propfind(url, depth, body): + """ Execute a PROPFIND request. """ + return url_request(url, 'PROPFIND', + {'Depth': depth, 'Content-Type': 'text/xml'}, body, 207) + +def url_get(url): + """ Execute a GET request. """ + return url_request(url, 'GET', None, None, 200) + +def extract_string(str, start, end): + """ Returns the string between start and end. """ + s = str.find(start) + if s < 0: + return None + slen = len(start) + e = str.find(end, s + slen) + if e < 0: + return None + return str[s + slen:e] + +def extract_int(str, start, end): + """ Returns the integer between start and end. """ + val = extract_string(str, start, end) + if not val is None and re.match('^[0-9]{1,}$', val): + return int(val) + return None + +def read_file(name, normalize = True): + """ Read a file. """ + try: + f = open(name, 'r') + # read the data + data = f.read() + if normalize: + # normalize line endings + data = data.replace("\r\n", "\n") + return data + except IOError, (errno, strerror): + print 'Failed to read file %s: %s' % (name, strerror) + else: + f.close() + return None + +def write_file(name, data): + """ Write a file. """ + try: + f = open(name, 'w') + f.write(data) + return True + except IOError, (errno, strerror): + print 'Failed to write file %s: %s' % (name, strerror) + else: + f.close() + return True + +def read_cache_file(name, args): + """ Read and parse a cache file (key=value pairs, one per line). """ + content = read_file(name) + if content is None: + return False + lines = content.split("\n") + for line in lines: + parts = line.split('=', 1) + if len(parts) == 2: + args[parts[0]] = parts[1] + return True + +def write_cache_file(name, args): + """ Write a cache file (key=value pairs, one per line). """ + data = '' + for key, val in args.iteritems(): + data = data + key + '=' + str(val) + "\n" + return write_file(name, data) + + +# Parse command-line options. +disc = """This utility creates and synchronizes git-svn clones of CEF SVN +repositories.""" + +parser = OptionParser(description=disc) +parser.add_option('--storage-dir', dest='storagedir', metavar='DIR', + help='local directory where data will be stored') +parser.add_option('--branch', dest='branch', + help='CEF branch to clone ' + + '(trunk/cef3, branches/1453/cef3, etc)') +parser.add_option('--git-repo', dest='gitrepo', + help='remote repo where the git data will be pushed ' + + '(user@domain:path/to/repo.git)') +parser.add_option('--force', + action='store_true', dest='force', default=False, + help="force the run even if the revision hasn't changed") +parser.add_option('--dry-run', + action='store_true', dest='dryrun', default=False, + help="output commands without executing them") +parser.add_option('-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# Required options. +if options.storagedir is None or options.branch is None or \ + options.gitrepo is None: + parser.print_help(sys.stderr) + sys.exit(1) + +# Validate the git repo format. Should be user@domain:path/to/repo.git +if not re.match( + '^[a-zA-Z0-9_\-]{1,}@[a-zA-Z0-9\-\.]{1,}:[a-zA-Z0-9\-_/]{1,}\.git$', + options.gitrepo): + fail('Invalid git repo format: %s' % options.gitrepo) + +svn_url = 'https://chromiumembedded.googlecode.com/svn/' + options.branch + +# Verify that the requested branch is valid CEF root directory. +value = url_get(svn_url + '/CHROMIUM_BUILD_COMPATIBILITY.txt') +if value is None: + fail('Invalid branch "%s"' % options.branch) + +# Retrieve the most recent revision for the branch. +revision = None +request = '' + \ + '' +value = url_propfind(svn_url, 0, request) +if not value is None: + revision = extract_int(value, '', '') +if revision is None: + fail('Failed to discover revision for branch "%s"' % options.branch) + +branch_path_comp = options.branch.replace('/', '-') + +# Create the branch storage directory if it doesn't already exist. +branch_dir = os.path.join(options.storagedir, branch_path_comp) +if not os.path.exists(branch_dir): + os.makedirs(branch_dir) + +# Default cache configuration. +cache_config = { + 'last_revision': 0, +} + +# Create the authors.txt file if it doesn't already exist +authors_file_path = os.path.join(options.storagedir, 'authors.txt') +if not os.path.exists(authors_file_path): + content = 'magreenblatt@gmail.com = ' + \ + 'Marshall Greenblatt ' + if not write_file(authors_file_path, content): + fail('Failed to create authors.txt file: %s' % authors_file_path) + +# Read the cache file if it exists. +cache_file_path = os.path.join(branch_dir, 'cache.txt') +if os.path.exists(cache_file_path): + if not read_cache_file(cache_file_path, cache_config): + print 'Failed to read cache.txt file %s' % cache_file_path + +# Check if the revision has changed. +if not options.force and int(cache_config['last_revision']) == revision: + if not options.quiet: + print 'Already at revision %d' % revision + sys.exit() + +repo_dir = os.path.join(branch_dir, branch_path_comp) +if not os.path.exists(repo_dir): + # Create the git repository. + run('git svn clone -A %s %s %s' % (authors_file_path, svn_url, repo_dir), + branch_dir) + run('git remote add origin %s' % options.gitrepo, repo_dir) +else: + # Rebase the git repository. + run('git svn rebase --fetch-all -A %s' % authors_file_path, repo_dir) + +run('git push origin --all', repo_dir) + +# Write the cache file. +cache_config['last_revision'] = revision +if not write_cache_file(cache_file_path, cache_config): + print 'Failed to write cache file %s' % cache_file_path diff --git a/tools/build_projects.bat b/tools/build_projects.bat new file mode 100644 index 000000000..e8e2ed99f --- /dev/null +++ b/tools/build_projects.bat @@ -0,0 +1,48 @@ +@echo off +set RC= +setlocal + +if "%1" == "" ( +echo ERROR: Please specify a build target: Debug or Release +set ERRORLEVEL=1 +goto end +) + +if "%2" == "" ( +set PROJECT_NAME=cefclient +) else ( +set PROJECT_NAME=%2 +) + +echo Configuring Visual Studio environment... +if "%GYP_MSVS_VERSION%" == "2008" ( +call "%VS90COMNTOOLS%vsvars32.bat" +set PROJECT_EXT=.vcproj +) else ( +call "%VS100COMNTOOLS%vsvars32.bat" +set PROJECT_EXT=.vcxproj +set CEF_MSBUILD_PATH=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe +) + +if exist "%CEF_MSBUILD_PATH%" ( +"%CEF_MSBUILD_PATH%" /v:m /p:Configuration=%1;Platform=Win32 /t:"%PROJECT_NAME%" ..\cef.sln +) else if exist "%DevEnvDir%\devenv.com" ( +echo Building %1 target for %PROJECT_NAME% project... +"%DevEnvDir%\devenv.com" /build %1 ..\cef.sln /project %PROJECT_NAME%%PROJECT_EXT% +) else if exist "%VCINSTALLDIR%\vcpackages\vcbuild.exe" ( +echo Building %1 target for all projects... +"%VCINSTALLDIR%\vcpackages\vcbuild.exe" ..\cef.sln "%1|Win32" +) else ( +echo ERROR: Cannot find Visual Studio builder +set ERRORLEVEL=1 +) + +:end +endlocal & set RC=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RC% + +:omega +call :returncode %RC% diff --git a/tools/build_projects.sh b/tools/build_projects.sh new file mode 100755 index 000000000..13eade15d --- /dev/null +++ b/tools/build_projects.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "ERROR: Please specify a build target: Debug or Release" +else + if [ -z "$2" ]; then + PROJECT_NAME='cefclient' + else + PROJECT_NAME=$2 + fi + if [ `uname` = "Linux" ]; then + pushd ../../ + make -j16 $PROJECT_NAME BUILDTYPE=$1 + popd + else + xcodebuild -project ../cef.xcodeproj -configuration $1 -target "$PROJECT_NAME" + fi +fi diff --git a/tools/cef_api_hash.py b/tools/cef_api_hash.py new file mode 100644 index 000000000..df5c13505 --- /dev/null +++ b/tools/cef_api_hash.py @@ -0,0 +1,245 @@ +# 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. + +from file_util import * +import os +import re +import shutil +import string +import sys +import textwrap +import time +import itertools +import hashlib + + +class cef_api_hash: + """ CEF API hash calculator """ + + def __init__(self, headerdir, debugdir = None, verbose = False): + if headerdir is None or len(headerdir) == 0: + raise AssertionError("headerdir is not specified") + + self.__headerdir = headerdir; + self.__debugdir = debugdir; + self.__verbose = verbose; + self.__debug_enabled = not (self.__debugdir is None) and len(self.__debugdir) > 0; + + self.platforms = [ "windows", "macosx", "linux" ]; + + self.platform_files = { + "windows": [ + "internal/cef_types_win.h", + ], + "macosx": [ + "internal/cef_types_mac.h", + ], + "linux": [ + "internal/cef_types_linux.h", + ] + }; + + self.included_files = [ + ]; + + self.excluded_files = [ + "cef_version.h", + "internal/cef_tuple.h", + "internal/cef_types_wrappers.h", + "internal/cef_string_wrappers.h", + "internal/cef_win.h", + "internal/cef_mac.h", + "internal/cef_linux.h", + ]; + + def calculate(self): + filenames = [filename for filename in self.__get_filenames() if not filename in self.excluded_files] + + objects = [] + for filename in filenames: + if self.__verbose: + print "Processing " + filename + "..." + content = read_file(os.path.join(self.__headerdir, filename), True) + platforms = list([p for p in self.platforms if self.__is_platform_filename(filename, p)]) + + # Parse cef_string.h happens in special case: grab only defined CEF_STRING_TYPE_xxx declaration + content_objects = None + if filename == "internal/cef_string.h": + content_objects = self.__parse_string_type(content) + else: + content_objects = self.__parse_objects(content) + + for o in content_objects: + o["text"] = self.__prepare_text(o["text"]) + o["platforms"] = platforms + o["filename"] = filename + objects.append(o) + + # objects will be sorted including filename, to make stable universal hashes + objects = sorted(objects, key = lambda o: o["name"] + "@" + o["filename"]) + + if self.__debug_enabled: + namelen = max([len(o["name"]) for o in objects]) + filenamelen = max([len(o["filename"]) for o in objects]) + dumpsig = []; + for o in objects: + dumpsig.append(format(o["name"], str(namelen) + "s") + "|" + format(o["filename"], "" + str(filenamelen) + "s") + "|" + o["text"]); + self.__write_debug_file("objects.txt", dumpsig) + + revisions = { }; + + for platform in itertools.chain(["universal"], self.platforms): + sig = self.__get_final_sig(objects, platform) + if self.__debug_enabled: + self.__write_debug_file(platform + ".sig", sig) + rev = hashlib.sha1(sig).digest(); + revstr = ''.join(format(ord(i),'0>2x') for i in rev) + revisions[platform] = revstr + + return revisions + + def __parse_objects(self, content): + """ Returns array of objects in content file. """ + objects = [] + content = re.sub("//.*\n", "", content) + + # function declarations + for m in re.finditer("\nCEF_EXPORT\s+?.*?\s+?(\w+)\s*?\(.*?\)\s*?;", content, flags = re.DOTALL): + object = { + "name": m.group(1), + "text": m.group(0).strip() + } + objects.append(object) + + # structs + for m in re.finditer("\ntypedef\s+?struct\s+?(\w+)\s+?\{.*?\}\s+?(\w+)\s*?;", content, flags = re.DOTALL): + object = { + "name": m.group(2), + "text": m.group(0).strip() + } + objects.append(object) + + # enums + for m in re.finditer("\nenum\s+?(\w+)\s+?\{.*?\}\s*?;", content, flags = re.DOTALL): + object = { + "name": m.group(1), + "text": m.group(0).strip() + } + objects.append(object) + + # typedefs + for m in re.finditer("\ntypedef\s+?.*?\s+(\w+);", content, flags = 0): + object = { + "name": m.group(1), + "text": m.group(0).strip() + } + objects.append(object) + + return objects + + def __parse_string_type(self, content): + """ Grab defined CEF_STRING_TYPE_xxx """ + objects = [] + for m in re.finditer("\n\s*?#\s*?define\s+?(CEF_STRING_TYPE_\w+)\s+?.*?\n", content, flags = 0): + object = { + "name": m.group(1), + "text": m.group(0), + } + objects.append(object) + return objects + + def __prepare_text(self, text): + text = text.strip() + text = re.sub("\s+", " ", text); + text = re.sub("\(\s+", "(", text); + return text + + def __get_final_sig(self, objects, platform): + sig = [] + + for o in objects: + if platform == "universal" or platform in o["platforms"]: + sig.append(o["text"]) + + return "\n".join(sig) + + def __get_filenames(self): + """ Returns file names to be processed, relative to headerdir """ + headers = [os.path.join(self.__headerdir, filename) for filename in self.included_files]; + headers = itertools.chain(headers, get_files(os.path.join(self.__headerdir, "capi", "*.h"))) + headers = itertools.chain(headers, get_files(os.path.join(self.__headerdir, "internal", "*.h"))) + + for v in self.platform_files.values(): + headers = itertools.chain(headers, [os.path.join(self.__headerdir, f) for f in v]) + + normalized = [os.path.relpath(filename, self.__headerdir) for filename in headers]; + normalized = [f.replace('\\', '/').lower() for f in normalized]; + + return list(set(normalized)); + + def __is_platform_filename(self, filename, platform): + if platform == "universal": + return True + if not platform in self.platform_files: + return False + listed = False + for p in self.platforms: + if filename in self.platform_files[p]: + if p == platform: + return True + else: + listed = True + return not listed + + def __write_debug_file(self, filename, content): + make_dir(self.__debugdir); + outfile = os.path.join(self.__debugdir, filename); + dir = os.path.dirname(outfile); + make_dir(dir); + if not isinstance(content, basestring): + content = "\n".join(content) + write_file(outfile, content) + + +if __name__ == "__main__": + from optparse import OptionParser + import time + + disc = """ + This utility calculates CEF API hash. + """ + + parser = OptionParser(description=disc) + parser.add_option('--cpp-header-dir', dest='cppheaderdir', metavar='DIR', + help='input directory for C++ header files [required]') + parser.add_option('--debug-dir', dest='debugdir', metavar='DIR', + help='intermediate directory for easy debugging') + parser.add_option('-v', '--verbose', + action='store_true', dest='verbose', default=False, + help='output detailed status information') + (options, args) = parser.parse_args() + + # the cppheader option is required + if options.cppheaderdir is None: + parser.print_help(sys.stdout) + sys.exit() + + # calculate + c_start_time = time.time() + + calc = cef_api_hash(options.cppheaderdir, options.debugdir, options.verbose); + revisions = calc.calculate(); + + c_completed_in = time.time() - c_start_time + + print "{" + for k in sorted(revisions.keys()): + print format("\"" + k + "\"", ">12s") + ": \"" + revisions[k] + "\"" + print "}" + # print + # print 'Completed in: ' + str(c_completed_in) + # print + + # print "Press any key to continue..."; + # sys.stdin.readline(); diff --git a/tools/cef_parser.py b/tools/cef_parser.py new file mode 100644 index 000000000..44b1a9587 --- /dev/null +++ b/tools/cef_parser.py @@ -0,0 +1,1869 @@ +# 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. + +from date_util import * +from file_util import * +import os +import re +import shutil +import string +import sys +import textwrap +import time + + +def notify(msg): + """ Display a message. """ + sys.stdout.write(' NOTE: '+msg+'\n') + +def wrap_text(text, indent = '', maxchars = 80): + """ Wrap the text to the specified number of characters. If + necessary a line will be broken and wrapped after a word. + """ + result = '' + lines = textwrap.wrap(text, maxchars - len(indent)) + for line in lines: + result += indent+line+'\n' + return result + +def wrap_code(code, indent = ' ', maxchars = 80, splitchars = '(=,'): + """ Wrap the code lines to the specified number of characters. If + necessary a line will be broken and wrapped after one of the split + characters. + """ + output = '' + + # normalize line endings + code = code.replace("\r\n", "\n") + + # break the code chunk into lines + lines = string.split(code, '\n') + for line in lines: + if len(line) <= maxchars: + # line is short enough that it doesn't need to be wrapped + output += line + '\n' + continue + + # retrieve the whitespace at the beginning of the line for later use + # as padding + ws = '' + for char in line: + if char.isspace(): + ws += char + else: + break + + # iterate over all characters in the string keeping track of where the + # last valid break character was found and wrapping the line + # accordingly + lastsplit = 0 + nextsplit = -1 + splitct = 0 + pos = 0 + for char in line: + if splitchars.find(char) >= 0: + # a new split position has been found + nextsplit = pos + size = pos - lastsplit + 1 + if splitct > 0: + size += len(ws) + len(indent) + if size >= maxchars: + # the line is too long + section = line[lastsplit:nextsplit+1] + if len(section) > 0: + # output the line portion between the last split and the + # next split + if splitct > 0: + # start a new line and trim the line section + output += '\n'+ws+indent + section = string.strip(section) + output += section + lastsplit = nextsplit + 1 + splitct += 1 + pos += 1 + if len(line) - lastsplit > 0: + # output the remainder of the line + section = line[lastsplit:] + if splitct > 0: + # start a new line and trim the line section + output += '\n'+ws+indent + section = string.strip(section) + output += section + output += '\n' + + return output + +def get_capi_file_name(cppname): + """ Convert a C++ header file name to a C API header file name. """ + return cppname[:-2]+'_capi.h' + +def get_capi_name(cppname, isclassname, prefix = None): + """ Convert a C++ CamelCaps name to a C API underscore name. """ + result = '' + lastchr = '' + for chr in cppname: + # add an underscore if the current character is an upper case letter + # and the last character was a lower case letter + if len(result) > 0 and not chr.isdigit() \ + and string.upper(chr) == chr \ + and not string.upper(lastchr) == lastchr: + result += '_' + result += string.lower(chr) + lastchr = chr + + if isclassname: + result += '_t' + + if not prefix is None: + if prefix[0:3] == 'cef': + # if the prefix name is duplicated in the function name + # remove that portion of the function name + subprefix = prefix[3:] + pos = result.find(subprefix) + if pos >= 0: + result = result[0:pos]+ result[pos+len(subprefix):] + result = prefix+'_'+result + + return result + +def get_prev_line(body, pos): + """ Retrieve the start and end positions and value for the line immediately + before the line containing the specified position. + """ + end = string.rfind(body, '\n', 0, pos) + start = body.rfind('\n', 0, end)+1 + line = body[start:end] + return { 'start' : start, 'end' : end, 'line' : line } + +def get_comment(body, name): + """ Retrieve the comment for a class or function. """ + result = [] + + pos = body.find(name) + while pos > 0: + data = get_prev_line(body, pos) + line = string.strip(data['line']) + pos = data['start'] + if len(line) == 0: + # check if the next previous line is a comment + prevdata = get_prev_line(body, pos) + if string.strip(prevdata['line'])[0:2] == '//': + result.append(None) + else: + break + elif line[0:2] == '/*' or line[-2:] == '*/': + continue + elif line[0:2] == '//': + # keep the comment line including any leading spaces + result.append(line[2:]) + else: + break + + result.reverse() + return result + +def format_comment(comment, indent, translate_map = None, maxchars = 80): + """ Return the comments array as a formatted string. """ + result = '' + wrapme = '' + hasemptyline = False + for line in comment: + # if the line starts with a leading space, remove that space + if not line is None and len(line) > 0 and line[0:1] == ' ': + line = line[1:] + didremovespace = True + else: + didremovespace = False + + if line is None or len(line) == 0 or line[0:1] == ' ' \ + or line[0:1] == '/': + # the previous paragraph, if any, has ended + if len(wrapme) > 0: + if not translate_map is None: + # apply the translation + for key in translate_map.keys(): + wrapme = wrapme.replace(key, translate_map[key]) + # output the previous paragraph + result += wrap_text(wrapme, indent+'// ', maxchars) + wrapme = '' + + if not line is None: + if len(line) == 0 or line[0:1] == ' ' or line[0:1] == '/': + # blank lines or anything that's further indented should be + # output as-is + result += indent+'//' + if len(line) > 0: + if didremovespace: + result += ' '+line + else: + result += line + result += '\n' + else: + # add to the current paragraph + wrapme += line+' ' + else: + # output an empty line + hasemptyline = True + result += '\n' + + if len(wrapme) > 0: + if not translate_map is None: + # apply the translation + for key in translate_map.keys(): + wrapme = wrapme.replace(key, translate_map[key]) + # output the previous paragraph + result += wrap_text(wrapme, indent+'// ', maxchars) + + if hasemptyline: + # an empty line means a break between comments, so the comment is + # probably a section heading and should have an extra line before it + result = '\n' + result + return result + +def format_translation_changes(old, new): + """ Return a comment stating what is different between the old and new + function prototype parts. + """ + changed = False + result = '' + + # normalize C API attributes + oldargs = [x.replace('struct _', '') for x in old['args']] + oldretval = old['retval'].replace('struct _', '') + newargs = [x.replace('struct _', '') for x in new['args']] + newretval = new['retval'].replace('struct _', '') + + # check if the prototype has changed + oldset = set(oldargs) + newset = set(newargs) + if len(oldset.symmetric_difference(newset)) > 0: + changed = True + result += '\n // WARNING - CHANGED ATTRIBUTES' + + # in the implementation set only + oldonly = oldset.difference(newset) + for arg in oldonly: + result += '\n // REMOVED: '+arg + + # in the current set only + newonly = newset.difference(oldset) + for arg in newonly: + result += '\n // ADDED: '+arg + + # check if the return value has changed + if oldretval != newretval: + changed = True + result += '\n // WARNING - CHANGED RETURN VALUE'+ \ + '\n // WAS: '+old['retval']+ \ + '\n // NOW: '+new['retval'] + + if changed: + result += '\n #pragma message("Warning: "__FILE__": '+new['name']+ \ + ' prototype has changed")\n' + + return result + +def format_translation_includes(body): + """ Return the necessary list of includes based on the contents of the + body. + """ + result = '' + + # required for VS2013. + if body.find('std::min') > 0 or body.find('std::max') > 0: + result += '#include \n' + + if body.find('cef_api_hash(') > 0: + result += '#include "include/cef_version.h"\n' + + # identify what CppToC classes are being used + p = re.compile('([A-Za-z0-9_]{1,})CppToC') + list = sorted(set(p.findall(body))) + for item in list: + result += '#include "libcef_dll/cpptoc/'+ \ + get_capi_name(item[3:], False)+'_cpptoc.h"\n' + + # identify what CToCpp classes are being used + p = re.compile('([A-Za-z0-9_]{1,})CToCpp') + list = sorted(set(p.findall(body))) + for item in list: + result += '#include "libcef_dll/ctocpp/'+ \ + get_capi_name(item[3:], False)+'_ctocpp.h"\n' + + if body.find('transfer_') > 0: + result += '#include "libcef_dll/transfer_util.h"\n' + + return result + +def str_to_dict(str): + """ Convert a string to a dictionary. If the same key has multiple values + the values will be stored in a list. """ + dict = {} + parts = string.split(str, ',') + for part in parts: + part = string.strip(part) + if len(part) == 0: + continue + sparts = string.split(part, '=') + if len(sparts) > 2: + raise Exception('Invalid dictionary pair format: '+part) + name = string.strip(sparts[0]) + if len(sparts) == 2: + val = string.strip(sparts[1]) + else: + val = True + if name in dict: + # a value with this name already exists + curval = dict[name] + if not isinstance(curval, list): + # convert the string value to a list + dict[name] = [curval] + dict[name].append(val) + else: + dict[name] = val + return dict + +def dict_to_str(dict): + """ Convert a dictionary to a string. """ + str = [] + for name in dict.keys(): + if not isinstance(dict[name], list): + if dict[name] is True: + # currently a bool value + str.append(name) + else: + # currently a string value + str.append(name+'='+dict[name]) + else: + # currently a list value + for val in dict[name]: + str.append(name+'='+val) + return string.join(str, ',') + + +# regex for matching comment-formatted attributes +_cre_attrib = '/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/' +# regex for matching class and function names +_cre_cfname = '([A-Za-z0-9_]{1,})' +# regex for matching function return values +_cre_retval = '([A-Za-z0-9_<>:,\*\&]{1,})' +# regex for matching typedef value and name combination +_cre_typedef = '([A-Za-z0-9_<>:,\*\& ]{1,})' +# regex for matching function return value and name combination +_cre_func = '([A-Za-z][A-Za-z0-9_<>:,\*\& ]{1,})' +# regex for matching virtual function modifiers +_cre_vfmod = '([A-Za-z0-9_]{0,})' +# regex for matching arbitrary whitespace +_cre_space = '[\s]{1,}' + +# Simple translation types. Format is: +# 'cpp_type' : ['capi_type', 'capi_default_value'] +_simpletypes = { + 'void' : ['void', ''], + 'void*' : ['void*', 'NULL'], + 'int' : ['int', '0'], + 'int32' : ['int32', '0'], + 'uint32' : ['uint32', '0'], + 'int64' : ['int64', '0'], + 'uint64' : ['uint64', '0'], + 'double' : ['double', '0'], + 'float' : ['float', '0'], + 'long' : ['long', '0'], + 'unsigned long' : ['unsigned long', '0'], + 'long long' : ['long long', '0'], + 'size_t' : ['size_t', '0'], + 'time_t' : ['time_t', '0'], + 'bool' : ['int', '0'], + 'char': ['char', '0'], + 'char* const': ['char* const', 'NULL'], + 'CefCursorHandle' : ['cef_cursor_handle_t', 'kNullCursorHandle'], + 'CefEventHandle' : ['cef_event_handle_t', 'kNullEventHandle'], + 'CefWindowHandle' : ['cef_window_handle_t', 'kNullWindowHandle'], + 'CefTextInputContext' : ['cef_text_input_context_t' ,'NULL'], + 'CefRect' : ['cef_rect_t', 'CefRect()'], + 'CefSize' : ['cef_size_t', 'CefSize()'], + 'CefPageRange' : ['cef_page_range_t', 'CefPageRange()'], + 'CefThreadId' : ['cef_thread_id_t', 'TID_UI'], + 'CefTime' : ['cef_time_t', 'CefTime()'], +} + +def get_function_impls(content, ident): + """ Retrieve the function parts from the specified contents as a set of + return value, name, arguments and body. Ident must occur somewhere in + the value. + """ + # extract the functions + p = re.compile('\n'+_cre_func+'\((.*?)\)([A-Za-z0-9_\s]{0,})'+ + '\{(.*?)\n\}', + re.MULTILINE | re.DOTALL) + list = p.findall(content) + + # build the function map with the function name as the key + result = [] + for retval, argval, vfmod, body in list: + if retval.find(ident) < 0: + # the identifier was not found + continue + + # remove the identifier + retval = string.replace(retval, ident, '') + retval = string.strip(retval) + + # retrieve the function name + parts = string.split(retval, ' ') + name = parts[-1] + del parts[-1] + retval = string.join(parts, ' ') + + # parse the arguments + args = [] + for v in string.split(argval, ','): + v = string.strip(v) + if len(v) > 0: + args.append(v) + + result.append({ + 'retval' : string.strip(retval), + 'name' : name, + 'args' : args, + 'vfmod' : string.strip(vfmod), + 'body' : body + }) + + return result + +def get_next_function_impl(existing, name): + result = None + for item in existing: + if item['name'] == name: + result = item + existing.remove(item) + break + return result + +def get_copyright(): + result = \ +"""// Copyright (c) $YEAR$ 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +""" + # add the copyright year + return result.replace('$YEAR$', get_year()) + + +class obj_header: + """ Class representing a C++ header file. """ + + def __init__(self): + self.filenames = [] + self.typedefs = [] + self.funcs = [] + self.classes = [] + + def add_directory(self, directory, excluded_files = []): + """ Add all header files from the specified directory. """ + files = get_files(os.path.join(directory, '*.h')) + for file in files: + if len(excluded_files) == 0 or \ + not os.path.split(file)[1] in excluded_files: + self.add_file(file) + + def add_file(self, filepath): + """ Add a header file. """ + + filename = os.path.split(filepath)[1] + added = False + + # read the input file into memory + data = read_file(filepath) + + # remove space from between template definition end brackets + data = data.replace("> >", ">>") + + # extract global typedefs + p = re.compile('\ntypedef'+_cre_space+_cre_typedef+';', + re.MULTILINE | re.DOTALL) + list = p.findall(data) + if len(list) > 0: + # build the global typedef objects + for value in list: + pos = value.rfind(' ') + if pos < 0: + raise Exception('Invalid typedef: '+value) + alias = value[pos+1:] + value = value[:pos] + self.typedefs.append(obj_typedef(self, filename, value, alias)) + + # extract global functions + p = re.compile('\n'+_cre_attrib+'\n'+_cre_func+'\((.*?)\)', + re.MULTILINE | re.DOTALL) + list = p.findall(data) + if len(list) > 0: + added = True + + # build the global function objects + for attrib, retval, argval in list: + comment = get_comment(data, retval+'('+argval+');') + self.funcs.append(obj_function(self, filename, attrib, retval, + argval, comment)) + + # extract includes + p = re.compile('\n#include \"include/'+_cre_cfname+'.h') + includes = p.findall(data) + + # extract forward declarations + p = re.compile('\nclass'+_cre_space+_cre_cfname+';') + forward_declares = p.findall(data) + + # extract classes + p = re.compile('\n'+_cre_attrib+ + '\nclass'+_cre_space+_cre_cfname+_cre_space+ + ':'+_cre_space+'public'+_cre_space+'virtual'+ + _cre_space+'CefBase'+_cre_space+ + '{(.*?)};', re.MULTILINE | re.DOTALL) + list = p.findall(data) + if len(list) > 0: + added = True + + # build the class objects + for attrib, name, body in list: + comment = get_comment(data, name+' : public virtual CefBase') + self.classes.append( + obj_class(self, filename, attrib, name, body, comment, + includes, forward_declares)) + + if added: + # a global function or class was read from the header file + self.filenames.append(filename) + + def __repr__(self): + result = '' + + if len(self.typedefs) > 0: + strlist = [] + for cls in self.typedefs: + strlist.append(str(cls)) + result += string.join(strlist, "\n") + "\n\n" + + if len(self.funcs) > 0: + strlist = [] + for cls in self.funcs: + strlist.append(str(cls)) + result += string.join(strlist, "\n") + "\n\n" + + if len(self.classes) > 0: + strlist = [] + for cls in self.classes: + strlist.append(str(cls)) + result += string.join(strlist, "\n") + + return result + + def get_file_names(self): + """ Return the array of header file names. """ + return self.filenames + + def get_typedefs(self): + """ Return the array of typedef objects. """ + return self.typedefs + + def get_funcs(self, filename = None): + """ Return the array of function objects. """ + if filename is None: + return self.funcs + else: + # only return the functions in the specified file + res = [] + for func in self.funcs: + if func.get_file_name() == filename: + res.append(func) + return res + + def get_classes(self, filename = None): + """ Return the array of class objects. """ + if filename is None: + return self.classes + else: + # only return the classes in the specified file + res = [] + for cls in self.classes: + if cls.get_file_name() == filename: + res.append(cls) + return res + + def get_class(self, classname, defined_structs = None): + """ Return the specified class or None if not found. """ + for cls in self.classes: + if cls.get_name() == classname: + return cls + elif not defined_structs is None: + defined_structs.append(cls.get_capi_name()) + return None + + def get_class_names(self): + """ Returns the names of all classes in this object. """ + result = [] + for cls in self.classes: + result.append(cls.get_name()) + return result + + def get_types(self, list): + """ Return a dictionary mapping data types to analyzed values. """ + for cls in self.typedefs: + cls.get_types(list) + + for cls in self.classes: + cls.get_types(list) + + def get_alias_translation(self, alias): + """ Return a translation of alias to value based on typedef + statements. """ + for cls in self.typedefs: + if cls.alias == alias: + return cls.value + return None + + def get_analysis(self, value, named = True): + """ Return an analysis of the value based the header file context. """ + return obj_analysis([self], value, named) + + def get_defined_structs(self): + """ Return a list of names already defined structure names. """ + return ['cef_print_info_t', 'cef_window_info_t', 'cef_base_t'] + + def get_capi_translations(self): + """ Return a dictionary that maps C++ terminology to C API terminology. + """ + # strings that will be changed in C++ comments + map = { + 'class' : 'structure', + 'Class' : 'Structure', + 'interface' : 'structure', + 'Interface' : 'Structure', + 'true' : 'true (1)', + 'false' : 'false (0)', + 'empty' : 'NULL', + 'method' : 'function' + } + + # add mappings for all classes and functions + funcs = self.get_funcs() + for func in funcs: + map[func.get_name()+'()'] = func.get_capi_name()+'()' + + classes = self.get_classes() + for cls in classes: + map[cls.get_name()] = cls.get_capi_name() + + funcs = cls.get_virtual_funcs() + for func in funcs: + map[func.get_name()+'()'] = func.get_capi_name()+'()' + + funcs = cls.get_static_funcs() + for func in funcs: + map[func.get_name()+'()'] = func.get_capi_name()+'()' + + return map + + +class obj_class: + """ Class representing a C++ class. """ + + def __init__(self, parent, filename, attrib, name, body, comment, + includes, forward_declares): + if not isinstance(parent, obj_header): + raise Exception('Invalid parent object type') + + self.parent = parent + self.filename = filename + self.attribs = str_to_dict(attrib) + self.name = name + self.comment = comment + self.includes = includes + self.forward_declares = forward_declares + + # extract typedefs + p = re.compile('\n'+_cre_space+'typedef'+_cre_space+_cre_typedef+';', + re.MULTILINE | re.DOTALL) + list = p.findall(body) + + # build the typedef objects + self.typedefs = [] + for value in list: + pos = value.rfind(' ') + if pos < 0: + raise Exception('Invalid typedef: '+value) + alias = value[pos+1:] + value = value[:pos] + self.typedefs.append(obj_typedef(self, filename, value, alias)) + + # extract static functions + p = re.compile('\n'+_cre_space+_cre_attrib+'\n'+_cre_space+'static'+ + _cre_space+_cre_func+'\((.*?)\)', + re.MULTILINE | re.DOTALL) + list = p.findall(body) + + # build the static function objects + self.staticfuncs = [] + for attrib, retval, argval in list: + comment = get_comment(body, retval+'('+argval+')') + self.staticfuncs.append( + obj_function_static(self, attrib, retval, argval, comment)) + + # extract virtual functions + p = re.compile('\n'+_cre_space+_cre_attrib+'\n'+_cre_space+'virtual'+ + _cre_space+_cre_func+'\((.*?)\)'+_cre_space+_cre_vfmod, + re.MULTILINE | re.DOTALL) + list = p.findall(body) + + # build the virtual function objects + self.virtualfuncs = [] + for attrib, retval, argval, vfmod in list: + comment = get_comment(body, retval+'('+argval+')') + self.virtualfuncs.append( + obj_function_virtual(self, attrib, retval, argval, comment, + vfmod)) + + def __repr__(self): + result = '/* '+dict_to_str(self.attribs)+' */ class '+self.name+"\n{" + + if len(self.typedefs) > 0: + result += "\n\t" + strlist = [] + for cls in self.typedefs: + strlist.append(str(cls)) + result += string.join(strlist, "\n\t") + + if len(self.staticfuncs) > 0: + result += "\n\t" + strlist = [] + for cls in self.staticfuncs: + strlist.append(str(cls)) + result += string.join(strlist, "\n\t") + + if len(self.virtualfuncs) > 0: + result += "\n\t" + strlist = [] + for cls in self.virtualfuncs: + strlist.append(str(cls)) + result += string.join(strlist, "\n\t") + + result += "\n};\n" + return result + + def get_file_name(self): + """ Return the C++ header file name. """ + return self.filename + + def get_capi_file_name(self): + """ Return the CAPI header file name. """ + return get_capi_file_name(self.filename) + + def get_name(self): + """ Return the class name. """ + return self.name + + def get_capi_name(self): + """ Return the CAPI structure name for this class. """ + return get_capi_name(self.name, True) + + def get_comment(self): + """ Return the class comment as an array of lines. """ + return self.comment + + def get_includes(self): + """ Return the list of classes that are included from this class' + header file. """ + return self.includes + + def get_forward_declares(self): + """ Return the list of classes that are forward declared for this + class. """ + return self.forward_declares + + def get_attribs(self): + """ Return all attributes as a dictionary. """ + return self.attribs + + def has_attrib(self, name): + """ Return true if the specified attribute exists. """ + return name in self.attribs + + def get_attrib(self, name): + """ Return the first or only value for specified attribute. """ + if name in self.attribs: + if isinstance(self.attribs[name], list): + # the value is a list + return self.attribs[name][0] + else: + # the value is a string + return self.attribs[name] + return None + + def get_attrib_list(self, name): + """ Return all values for specified attribute as a list. """ + if name in self.attribs: + if isinstance(self.attribs[name], list): + # the value is already a list + return self.attribs[name] + else: + # convert the value to a list + return [self.attribs[name]] + return None + + def get_typedefs(self): + """ Return the array of typedef objects. """ + return self.typedefs + + def has_typedef_alias(self, alias): + """ Returns true if the specified typedef alias is defined in the scope + of this class declaration. """ + for typedef in self.typedefs: + if typedef.get_alias() == alias: + return True + return False + + def get_static_funcs(self): + """ Return the array of static function objects. """ + return self.staticfuncs + + def get_virtual_funcs(self): + """ Return the array of virtual function objects. """ + return self.virtualfuncs + + def get_types(self, list): + """ Return a dictionary mapping data types to analyzed values. """ + for cls in self.typedefs: + cls.get_types(list) + + for cls in self.staticfuncs: + cls.get_types(list) + + for cls in self.virtualfuncs: + cls.get_types(list) + + def get_alias_translation(self, alias): + for cls in self.typedefs: + if cls.alias == alias: + return cls.value + return None + + def get_analysis(self, value, named = True): + """ Return an analysis of the value based on the class definition + context. + """ + return obj_analysis([self, self.parent], value, named) + + def is_library_side(self): + """ Returns true if the class is implemented by the library. """ + return self.attribs['source'] == 'library' + + def is_client_side(self): + """ Returns true if the class is implemented by the client. """ + return self.attribs['source'] == 'client' + + +class obj_typedef: + """ Class representing a typedef statement. """ + + def __init__(self, parent, filename, value, alias): + if not isinstance(parent, obj_header) \ + and not isinstance(parent, obj_class): + raise Exception('Invalid parent object type') + + self.parent = parent + self.filename = filename + self.alias = alias + self.value = self.parent.get_analysis(value, False) + + def __repr__(self): + return 'typedef '+self.value.get_type()+' '+self.alias+';' + + def get_file_name(self): + """ Return the C++ header file name. """ + return self.filename + + def get_capi_file_name(self): + """ Return the CAPI header file name. """ + return get_capi_file_name(self.filename) + + def get_alias(self): + """ Return the alias. """ + return self.alias + + def get_value(self): + """ Return an analysis of the value based on the class or header file + definition context. + """ + return self.value + + def get_types(self, list): + """ Return a dictionary mapping data types to analyzed values. """ + name = self.value.get_type() + if not name in list: + list[name] = self.value + + +class obj_function: + """ Class representing a function. """ + + def __init__(self, parent, filename, attrib, retval, argval, comment): + self.parent = parent + self.filename = filename + self.attribs = str_to_dict(attrib) + self.retval = obj_argument(self, retval) + self.name = self.retval.remove_name() + self.comment = comment + + # build the argument objects + self.arguments = [] + arglist = string.split(argval, ',') + for arg in arglist: + arg = string.strip(arg) + if len(arg) > 0: + argument = obj_argument(self, arg) + if argument.needs_attrib_count_func() and \ + argument.get_attrib_count_func() is None: + raise Exception("A 'count_func' attribute is required "+ \ + "for the '"+argument.get_name()+ \ + "' parameter to "+self.get_qualified_name()) + self.arguments.append(argument) + + if self.retval.needs_attrib_default_retval() and \ + self.retval.get_attrib_default_retval() is None: + raise Exception("A 'default_retval' attribute is required for "+ \ + self.get_qualified_name()) + + def __repr__(self): + return '/* '+dict_to_str(self.attribs)+' */ '+self.get_cpp_proto() + + def get_file_name(self): + """ Return the C++ header file name. """ + return self.filename + + def get_capi_file_name(self): + """ Return the CAPI header file name. """ + return get_capi_file_name(self.filename) + + def get_name(self): + """ Return the function name. """ + return self.name + + def get_qualified_name(self): + """ Return the fully qualified function name. """ + if isinstance(self.parent, obj_header): + # global function + return self.name + else: + # member function + return self.parent.get_name()+'::'+self.name + + def get_capi_name(self, prefix = None): + """ Return the CAPI function name. """ + if 'capi_name' in self.attribs: + return self.attribs['capi_name'] + return get_capi_name(self.name, False, prefix) + + def get_comment(self): + """ Return the function comment as an array of lines. """ + return self.comment + + def get_attribs(self): + """ Return all attributes as a dictionary. """ + return self.attribs + + def has_attrib(self, name): + """ Return true if the specified attribute exists. """ + return name in self.attribs + + def get_attrib(self, name): + """ Return the first or only value for specified attribute. """ + if name in self.attribs: + if isinstance(self.attribs[name], list): + # the value is a list + return self.attribs[name][0] + else: + # the value is a string + return self.attribs[name] + return None + + def get_attrib_list(self, name): + """ Return all values for specified attribute as a list. """ + if name in self.attribs: + if isinstance(self.attribs[name], list): + # the value is already a list + return self.attribs[name] + else: + # convert the value to a list + return [self.attribs[name]] + return None + + def get_retval(self): + """ Return the return value object. """ + return self.retval + + def get_arguments(self): + """ Return the argument array. """ + return self.arguments + + def get_types(self, list): + """ Return a dictionary mapping data types to analyzed values. """ + for cls in self.arguments: + cls.get_types(list) + + def get_capi_parts(self, defined_structs = [], prefix = None): + """ Return the parts of the C API function definition. """ + retval = '' + dict = self.retval.get_type().get_capi(defined_structs) + if dict['format'] == 'single': + retval = dict['value'] + + name = self.get_capi_name(prefix) + args = [] + + if isinstance(self, obj_function_virtual): + # virtual functions get themselves as the first argument + str = 'struct _'+self.parent.get_capi_name()+'* self' + if isinstance(self, obj_function_virtual) and self.is_const(): + # const virtual functions get const self pointers + str = 'const '+str + args.append(str) + + if len(self.arguments) > 0: + for cls in self.arguments: + type = cls.get_type() + dict = type.get_capi(defined_structs) + if dict['format'] == 'single': + args.append(dict['value']) + elif dict['format'] == 'multi-arg': + # add an additional argument for the size of the array + type_name = type.get_name() + if type.is_const(): + # for const arrays pass the size argument by value + args.append('size_t '+type_name+'Count') + else: + # for non-const arrays pass the size argument by address + args.append('size_t* '+type_name+'Count') + args.append(dict['value']) + + return { 'retval' : retval, 'name' : name, 'args' : args } + + def get_capi_proto(self, defined_structs = [], prefix = None): + """ Return the prototype of the C API function. """ + parts = self.get_capi_parts(defined_structs, prefix) + result = parts['retval']+' '+parts['name']+ \ + '('+string.join(parts['args'], ', ')+')' + return result + + def get_cpp_parts(self, isimpl = False): + """ Return the parts of the C++ function definition. """ + retval = str(self.retval) + name = self.name + + args = [] + if len(self.arguments) > 0: + for cls in self.arguments: + args.append(str(cls)) + + if isimpl and isinstance(self, obj_function_virtual): + # enumeration return values must be qualified with the class name + # if the type is defined in the class declaration scope. + type = self.get_retval().get_type() + if type.is_result_struct() and type.is_result_struct_enum() and \ + self.parent.has_typedef_alias(retval): + retval = self.parent.get_name()+'::'+retval + + return { 'retval' : retval, 'name' : name, 'args' : args } + + def get_cpp_proto(self, classname = None): + """ Return the prototype of the C++ function. """ + parts = self.get_cpp_parts() + result = parts['retval']+' ' + if not classname is None: + result += classname+'::' + result += parts['name']+'('+string.join(parts['args'], ', ')+')' + if isinstance(self, obj_function_virtual) and self.is_const(): + result += ' const' + return result + + def is_same_side(self, other_class_name): + """ Returns true if this function is on the same side (library or + client) and the specified class. """ + if isinstance(self.parent, obj_class): + # this function is part of a class + this_is_library_side = self.parent.is_library_side() + header = self.parent.parent + else: + # this function is global + this_is_library_side = True + header = self.parent + + if other_class_name == 'CefBase': + other_is_library_side = False + else: + other_class = header.get_class(other_class_name) + if other_class is None: + raise Exception('Unknown class: '+other_class_name) + other_is_library_side = other_class.is_library_side() + + return other_is_library_side == this_is_library_side + + +class obj_function_static(obj_function): + """ Class representing a static function. """ + + def __init__(self, parent, attrib, retval, argval, comment): + if not isinstance(parent, obj_class): + raise Exception('Invalid parent object type') + obj_function.__init__(self, parent, parent.filename, attrib, retval, + argval, comment) + + def __repr__(self): + return 'static '+obj_function.__repr__(self)+';' + + def get_capi_name(self, prefix = None): + """ Return the CAPI function name. """ + if prefix is None: + # by default static functions are prefixed with the class name + prefix = get_capi_name(self.parent.get_name(), False) + return obj_function.get_capi_name(self, prefix) + +class obj_function_virtual(obj_function): + """ Class representing a virtual function. """ + + def __init__(self, parent, attrib, retval, argval, comment, vfmod): + if not isinstance(parent, obj_class): + raise Exception('Invalid parent object type') + obj_function.__init__(self, parent, parent.filename, attrib, retval, + argval, comment) + if vfmod == 'const': + self.isconst = True + else: + self.isconst = False + + def __repr__(self): + return 'virtual '+obj_function.__repr__(self)+';' + + def is_const(self): + """ Returns true if the method declaration is const. """ + return self.isconst + + +class obj_argument: + """ Class representing a function argument. """ + + def __init__(self, parent, argval): + if not isinstance(parent, obj_function): + raise Exception('Invalid parent object type') + + self.parent = parent + self.type = self.parent.parent.get_analysis(argval) + + def __repr__(self): + result = '' + if self.type.is_const(): + result += 'const ' + result += self.type.get_type() + if self.type.is_byref(): + result += '&' + elif self.type.is_byaddr(): + result += '*' + if self.type.has_name(): + result += ' '+self.type.get_name() + return result + + def get_name(self): + """ Return the name for this argument. """ + return self.type.get_name() + + def remove_name(self): + """ Remove and return the name value. """ + name = self.type.get_name() + self.type.name = None + return name + + def get_type(self): + """ Return an analysis of the argument type based on the class + definition context. + """ + return self.type + + def get_types(self, list): + """ Return a dictionary mapping data types to analyzed values. """ + name = self.type.get_type() + if not name in list: + list[name] = self.type + + def needs_attrib_count_func(self): + """ Returns true if this argument requires a 'count_func' attribute. """ + # A 'count_func' attribute is required for non-const non-string vector + # attribute types + return self.type.has_name() and \ + self.type.is_result_vector() and \ + not self.type.is_result_vector_string() and \ + not self.type.is_const() + + def get_attrib_count_func(self): + """ Returns the count function for this argument. """ + # The 'count_func' attribute value format is name:function + if not self.parent.has_attrib('count_func'): + return None + name = self.type.get_name() + vals = self.parent.get_attrib_list('count_func') + for val in vals: + parts = string.split(val, ':') + if len(parts) != 2: + raise Exception("Invalid 'count_func' attribute value for "+ \ + self.parent.get_qualified_name()+': '+val) + if string.strip(parts[0]) == name: + return string.strip(parts[1]) + return None + + def needs_attrib_default_retval(self): + """ Returns true if this argument requires a 'default_retval' attribute. + """ + # A 'default_retval' attribute is required for enumeration return value + # types. + return not self.type.has_name() and \ + self.type.is_result_struct() and \ + self.type.is_result_struct_enum() + + def get_attrib_default_retval(self): + """ Returns the defualt return value for this argument. """ + return self.parent.get_attrib('default_retval') + + def get_arg_type(self): + """ Returns the argument type as defined in translator.README.txt. """ + if not self.type.has_name(): + raise Exception('Cannot be called for retval types') + + # simple or enumeration type + if (self.type.is_result_simple() and \ + self.type.get_type() != 'bool') or \ + (self.type.is_result_struct() and \ + self.type.is_result_struct_enum()): + if self.type.is_byref(): + if self.type.is_const(): + return 'simple_byref_const' + return 'simple_byref' + elif self.type.is_byaddr(): + return 'simple_byaddr' + return 'simple_byval' + + # boolean type + if self.type.get_type() == 'bool': + if self.type.is_byref(): + return 'bool_byref' + elif self.type.is_byaddr(): + return 'bool_byaddr' + return 'bool_byval' + + # structure type + if self.type.is_result_struct() and self.type.is_byref(): + if self.type.is_const(): + return 'struct_byref_const' + return 'struct_byref' + + # string type + if self.type.is_result_string() and self.type.is_byref(): + if self.type.is_const(): + return 'string_byref_const' + return 'string_byref' + + # refptr type + if self.type.is_result_refptr(): + same_side = self.parent.is_same_side(self.type.get_refptr_type()) + if self.type.is_byref(): + if same_side: + return 'refptr_same_byref' + return 'refptr_diff_byref' + if same_side: + return 'refptr_same' + return 'refptr_diff' + + + if self.type.is_result_vector(): + # all vector types must be passed by reference + if not self.type.is_byref(): + return 'invalid' + + if self.type.is_result_vector_string(): + # string vector type + if self.type.is_const(): + return 'string_vec_byref_const' + return 'string_vec_byref' + + if self.type.is_result_vector_simple(): + if self.type.get_vector_type() != 'bool': + # simple/enumeration vector types + if self.type.is_const(): + return 'simple_vec_byref_const' + return 'simple_vec_byref' + + # boolean vector types + if self.type.is_const(): + return 'bool_vec_byref_const' + return 'bool_vec_byref' + + if self.type.is_result_vector_refptr(): + # refptr vector types + same_side = self.parent.is_same_side(self.type.get_refptr_type()) + if self.type.is_const(): + if same_side: + return 'refptr_vec_same_byref_const' + return 'refptr_vec_diff_byref_const' + if same_side: + return 'refptr_vec_same_byref' + return 'refptr_vec_diff_byref' + + + # string single map type + if self.type.is_result_map_single(): + if not self.type.is_byref(): + return 'invalid' + if self.type.is_const(): + return 'string_map_single_byref_const' + return 'string_map_single_byref' + + # string multi map type + if self.type.is_result_map_multi(): + if not self.type.is_byref(): + return 'invalid' + if self.type.is_const(): + return 'string_map_multi_byref_const' + return 'string_map_multi_byref' + + return 'invalid' + + def get_retval_type(self): + """ Returns the retval type as defined in translator.README.txt. """ + if self.type.has_name(): + raise Exception('Cannot be called for argument types') + + # unsupported modifiers + if self.type.is_const() or self.type.is_byref() or \ + self.type.is_byaddr(): + return 'invalid' + + # void types don't have a return value + if self.type.get_type() == 'void': + return 'none' + + if (self.type.is_result_simple() and \ + self.type.get_type() != 'bool') or \ + (self.type.is_result_struct() and self.type.is_result_struct_enum()): + return 'simple' + + if self.type.get_type() == 'bool': + return 'bool' + + if self.type.is_result_string(): + return 'string' + + if self.type.is_result_refptr(): + if self.parent.is_same_side(self.type.get_refptr_type()): + return 'refptr_same' + else: + return 'refptr_diff' + + return 'invalid' + + def get_retval_default(self, for_capi): + """ Returns the default return value based on the retval type. """ + # start with the default retval attribute, if any. + retval = self.get_attrib_default_retval() + if not retval is None: + if for_capi: + # apply any appropriate C API translations. + if retval == 'true': + return '1' + if retval == 'false': + return '0' + return retval + + # next look at the retval type value. + type = self.get_retval_type() + if type == 'simple': + return self.get_type().get_result_simple_default() + elif type == 'bool': + if for_capi: + return '0' + return 'false' + elif type == 'string': + if for_capi: + return 'NULL' + return 'CefString()' + elif type == 'refptr_same' or type == 'refptr_diff': + return 'NULL' + + return '' + +class obj_analysis: + """ Class representing an analysis of a data type value. """ + + def __init__(self, scopelist, value, named): + self.value = value + self.result_type = 'unknown' + self.result_value = None + self.result_default = None + self.refptr_type = None + + # parse the argument string + partlist = string.split(string.strip(value)) + + if named == True: + # extract the name value + self.name = partlist[-1] + del partlist[-1] + else: + self.name = None + + if len(partlist) == 0: + raise Exception('Invalid argument value: '+value) + + # check const status + if partlist[0] == 'const': + self.isconst = True + del partlist[0] + else: + self.isconst = False + + # combine the data type + self.type = string.join(partlist, ' ') + + # extract the last character of the data type + endchar = self.type[-1] + + # check if the value is passed by reference + if endchar == '&': + self.isbyref = True + self.type = self.type[:-1] + else: + self.isbyref = False + + # check if the value is passed by address + if endchar == '*': + self.isbyaddr = True + self.type = self.type[:-1] + else: + self.isbyaddr = False + + # see if the value is directly identifiable + if self._check_advanced(self.type) == True: + return + + # not identifiable, so look it up + translation = None + for scope in scopelist: + if not isinstance(scope, obj_header) \ + and not isinstance(scope, obj_class): + raise Exception('Invalid scope object type') + translation = scope.get_alias_translation(self.type) + if not translation is None: + break + + if translation is None: + raise Exception('Failed to translate type: '+self.type) + + # the translation succeeded so keep the result + self.result_type = translation.result_type + self.result_value = translation.result_value + + def _check_advanced(self, value): + # check for vectors + if value.find('std::vector') == 0: + self.result_type = 'vector' + val = string.strip(value[12:-1]) + self.result_value = [ + self._get_basic(val) + ] + self.result_value[0]['vector_type'] = val + return True + + # check for maps + if value.find('std::map') == 0: + self.result_type = 'map' + vals = string.split(value[9:-1], ',') + if len(vals) == 2: + self.result_value = [ + self._get_basic(string.strip(vals[0])), + self._get_basic(string.strip(vals[1])) + ] + return True + + # check for multimaps + if value.find('std::multimap') == 0: + self.result_type = 'multimap' + vals = string.split(value[14:-1], ',') + if len(vals) == 2: + self.result_value = [ + self._get_basic(string.strip(vals[0])), + self._get_basic(string.strip(vals[1])) + ] + return True + + # check for basic types + basic = self._get_basic(value) + if not basic is None: + self.result_type = basic['result_type'] + self.result_value = basic['result_value'] + if 'refptr_type' in basic: + self.refptr_type = basic['refptr_type'] + if 'result_default' in basic: + self.result_default = basic['result_default'] + return True + + return False + + def _get_basic(self, value): + # check for string values + if value == "CefString": + return { + 'result_type' : 'string', + 'result_value' : None + } + + # check for simple direct translations + if value in _simpletypes.keys(): + return { + 'result_type' : 'simple', + 'result_value' : _simpletypes[value][0], + 'result_default' : _simpletypes[value][1], + } + + # check if already a C API structure + if value[-2:] == '_t': + return { + 'result_type' : 'structure', + 'result_value' : value + } + + # check for CEF reference pointers + p = re.compile('^CefRefPtr<(.*?)>$', re.DOTALL) + list = p.findall(value) + if len(list) == 1: + return { + 'result_type' : 'refptr', + 'result_value' : get_capi_name(list[0], True)+'*', + 'refptr_type' : list[0] + } + + # check for CEF structure types + if value[0:3] == 'Cef' and value[-4:] != 'List': + return { + 'result_type' : 'structure', + 'result_value' : get_capi_name(value, True) + } + + return None + + def __repr__(self): + return '('+self.result_type+') '+str(self.result_value) + + def has_name(self): + """ Returns true if a name value exists. """ + return (not self.name is None) + + def get_name(self): + """ Return the name. """ + return self.name + + def get_value(self): + """ Return the C++ value (type + name). """ + return self.value + + def get_type(self): + """ Return the C++ type. """ + return self.type + + def get_refptr_type(self): + """ Return the C++ class type referenced by a CefRefPtr. """ + if self.is_result_vector() and self.is_result_vector_refptr(): + # return the vector RefPtr type + return self.result_value[0]['refptr_type'] + # return the basic RefPtr type + return self.refptr_type + + def get_vector_type(self): + """ Return the C++ class type referenced by a std::vector. """ + if self.is_result_vector(): + return self.result_value[0]['vector_type'] + return None + + def is_const(self): + """ Returns true if the argument value is constant. """ + return self.isconst + + def is_byref(self): + """ Returns true if the argument is passed by reference. """ + return self.isbyref + + def is_byaddr(self): + """ Returns true if the argument is passed by address. """ + return self.isbyaddr + + def is_result_simple(self): + """ Returns true if this is a simple argument type. """ + return (self.result_type == 'simple') + + def get_result_simple_type_root(self): + """ Return the simple structure or basic type name. """ + return self.result_value + + def get_result_simple_type(self): + """ Return the simple type. """ + result = '' + if self.is_const(): + result += 'const ' + result += self.result_value + if self.is_byaddr() or self.is_byref(): + result += '*' + return result + + def get_result_simple_default(self): + """ Return the default value fo the basic type. """ + return self.result_default + + def is_result_refptr(self): + """ Returns true if this is a reference pointer type. """ + return (self.result_type == 'refptr') + + def get_result_refptr_type_root(self): + """ Return the refptr type structure name. """ + return self.result_value[:-1] + + def get_result_refptr_type(self, defined_structs = []): + """ Return the refptr type. """ + result = '' + if not self.result_value[:-1] in defined_structs: + result += 'struct _' + result += self.result_value + if self.is_byref() or self.is_byaddr(): + result += '*' + return result + + def is_result_struct(self): + """ Returns true if this is a structure type. """ + return (self.result_type == 'structure') + + def is_result_struct_enum(self): + """ Returns true if this struct type is likely an enumeration. """ + # structure values that are passed by reference or address must be + # structures and not enumerations + if not self.is_byref() and not self.is_byaddr(): + return True + return False + + def get_result_struct_type(self, defined_structs = []): + """ Return the structure or enumeration type. """ + result = '' + is_enum = self.is_result_struct_enum() + if not is_enum: + if self.is_const(): + result += 'const ' + if not self.result_value in defined_structs: + result += 'struct _' + result += self.result_value + if not is_enum: + result += '*' + return result + + def is_result_string(self): + """ Returns true if this is a string type. """ + return (self.result_type == 'string') + + def get_result_string_type(self): + """ Return the string type. """ + if not self.has_name(): + # Return values are string structs that the user must free. Use + # the name of the structure as a hint. + return 'cef_string_userfree_t' + elif not self.is_const() and (self.is_byref() or self.is_byaddr()): + # Parameters passed by reference or address. Use the normal + # non-const string struct. + return 'cef_string_t*' + # Const parameters use the const string struct. + return 'const cef_string_t*' + + def is_result_vector(self): + """ Returns true if this is a vector type. """ + return (self.result_type == 'vector') + + def is_result_vector_string(self): + """ Returns true if this is a string vector. """ + return self.result_value[0]['result_type'] == 'string' + + def is_result_vector_simple(self): + """ Returns true if this is a string vector. """ + return self.result_value[0]['result_type'] == 'simple' + + def is_result_vector_refptr(self): + """ Returns true if this is a string vector. """ + return self.result_value[0]['result_type'] == 'refptr' + + def get_result_vector_type_root(self): + """ Return the vector structure or basic type name. """ + return self.result_value[0]['result_value'] + + def get_result_vector_type(self, defined_structs = []): + """ Return the vector type. """ + if not self.has_name(): + raise Exception('Cannot use vector as a return type') + + type = self.result_value[0]['result_type'] + value = self.result_value[0]['result_value'] + + result = {} + if type == 'string': + result['value'] = 'cef_string_list_t' + result['format'] = 'single' + return result + + if type == 'simple': + str = value + if self.is_const(): + str += ' const' + str += '*' + result['value'] = str + elif type == 'refptr': + str = '' + if not value[:-1] in defined_structs: + str += 'struct _' + str += value + if self.is_const(): + str += ' const' + str += '*' + result['value'] = str + else: + raise Exception('Unsupported vector type: '+type) + + # vector values must be passed as a value array parameter + # and a size parameter + result['format'] = 'multi-arg' + return result + + def is_result_map(self): + """ Returns true if this is a map type. """ + return (self.result_type == 'map' or self.result_type == 'multimap') + + def is_result_map_single(self): + """ Returns true if this is a single map type. """ + return (self.result_type == 'map') + + def is_result_map_multi(self): + """ Returns true if this is a multi map type. """ + return (self.result_type == 'multimap') + + def get_result_map_type(self, defined_structs = []): + """ Return the map type. """ + if not self.has_name(): + raise Exception('Cannot use map as a return type') + if self.result_value[0]['result_type'] == 'string' \ + and self.result_value[1]['result_type'] == 'string': + if self.result_type == 'map': + return { + 'value' : 'cef_string_map_t', + 'format' : 'single' + } + elif self.result_type == 'multimap': + return { + 'value' : 'cef_string_multimap_t', + 'format' : 'multi' + } + raise Exception('Only mappings of strings to strings are supported') + + def get_capi(self, defined_structs = []): + """ Format the value for the C API. """ + result = '' + format = 'single' + if self.is_result_simple(): + result += self.get_result_simple_type() + elif self.is_result_refptr(): + result += self.get_result_refptr_type(defined_structs) + elif self.is_result_struct(): + result += self.get_result_struct_type(defined_structs) + elif self.is_result_string(): + result += self.get_result_string_type() + elif self.is_result_map(): + resdict = self.get_result_map_type(defined_structs) + if resdict['format'] == 'single' or resdict['format'] == 'multi': + result += resdict['value'] + else: + raise Exception('Unsupported map type') + elif self.is_result_vector(): + resdict = self.get_result_vector_type(defined_structs) + if resdict['format'] != 'single': + format = resdict['format'] + result += resdict['value'] + + if self.has_name(): + result += ' '+self.get_name() + + return {'format' : format, 'value' : result} + + +# test the module +if __name__ == "__main__": + import pprint + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) != 2: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + pp = pprint.PrettyPrinter(indent=4) + + # create the header object + header = obj_header() + header.add_directory(sys.argv[1]) + + # output the type mapping + types = {} + header.get_types(types) + pp.pprint(types) + sys.stdout.write('\n') + + # output the parsed C++ data + sys.stdout.write(wrap_code(str(header), '\t')) + + # output the C API formatted data + defined_names = header.get_defined_structs() + result = '' + + # global functions + funcs = header.get_funcs() + if len(funcs) > 0: + for func in funcs: + result += func.get_capi_proto(defined_names)+';\n' + result += '\n' + + classes = header.get_classes() + for cls in classes: + # virtual functions are inside a structure + result += 'struct '+cls.get_capi_name()+'\n{\n' + funcs = cls.get_virtual_funcs() + if len(funcs) > 0: + for func in funcs: + result += '\t'+func.get_capi_proto(defined_names)+';\n' + result += '}\n\n' + + defined_names.append(cls.get_capi_name()) + + # static functions become global + funcs = cls.get_static_funcs() + if len(funcs) > 0: + for func in funcs: + result += func.get_capi_proto(defined_names)+';\n' + result += '\n' + sys.stdout.write(wrap_code(result, '\t')) diff --git a/tools/check_revision.py b/tools/check_revision.py new file mode 100644 index 000000000..ba4d495d4 --- /dev/null +++ b/tools/check_revision.py @@ -0,0 +1,92 @@ +# 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. + +from file_util import * +from optparse import OptionParser +from svn_util import * +import sys + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + + +# parse command-line options +disc = """ +This utility checks that the correct Chromium revision is being used. +""" + +parser = OptionParser(description=disc) +parser.add_option('-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# The CEF root directory is the parent directory of _this_ script. +cef_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) +src_dir = os.path.join(cef_dir, os.pardir) + +if not os.path.exists(os.path.join(cef_dir, '.svn')) or \ + not os.path.exists(os.path.join(src_dir, '.svn')): + sys.stdout.write("Not an SVN checkout.\n") + sys.exit(0) + +# Retrieve the CEF SVN info. +cef_info = get_svn_info(cef_dir) +if not options.quiet: + sys.stdout.write('Using CEF revision '+cef_info['revision']+' @ '+\ + cef_info['url']+"\n") + +# Retrieve the Chromium SVN info. +chromium_info = get_svn_info(src_dir) +if not options.quiet: + sys.stdout.write('Using Chromium revision '+chromium_info['revision']+' @ '+\ + chromium_info['url']+"\n") + +# Parse the compatibility file contents. +compat_file = os.path.join(cef_dir, 'CHROMIUM_BUILD_COMPATIBILITY.txt') +config = eval(read_file(compat_file), {'__builtins__': None}, None) + +error = False + +if 'release_url' in config: + current_release_url = None + path = os.path.join(os.path.join(src_dir, os.pardir), '.gclient') + if os.path.exists(path): + # read the .gclient file + fp = open(path, 'r') + data = fp.read() + fp.close() + + # Parse the contents + config_dict = {} + try: + exec(data, config_dict) + current_release_url = config_dict['solutions'][0]['url'] + except Exception, e: + sys.stderr.write('Failed to parse existing .glient file.\n') + raise + + if not options.quiet: + sys.stdout.write('Using Chromium release '+current_release_url+"\n") + + if current_release_url != config['release_url']: + error = True + sys.stderr.write("\nWARNING: Incorrect Chromium release URL; found "+\ + current_release_url+', expected '+config['release_url']+"\n") +else: + if chromium_info['url'] != config['chromium_url']: + error = True + sys.stderr.write("\nWARNING: Incorrect Chromium URL; found "+\ + chromium_info['url']+', expected '+config['chromium_url']+"\n") + + if chromium_info['revision'] != config['chromium_revision']: + error = True + sys.stderr.write("\nWARNING: Incorrect Chromium revision; found "+\ + chromium_info['revision']+', expected '+config['chromium_revision']+"\n") + +if error: + sys.stderr.write("\nPlease see CHROMIUM_BUILD_COMPATIBILITY.txt for "\ + "instructions.\n") diff --git a/tools/check_style.bat b/tools/check_style.bat new file mode 100644 index 000000000..8bd86b20c --- /dev/null +++ b/tools/check_style.bat @@ -0,0 +1,2 @@ +@echo off +python.bat check_style.py %* diff --git a/tools/check_style.py b/tools/check_style.py new file mode 100644 index 000000000..d734e76fb --- /dev/null +++ b/tools/check_style.py @@ -0,0 +1,129 @@ +# Copyright (c) 2012 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. + +import os, re, string, sys +from file_util import * +import git_util as git +import svn_util as svn + +# script directory +script_dir = os.path.dirname(__file__) + +# CEF root directory +cef_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) + +# Valid extensions for files we want to lint. +DEFAULT_LINT_WHITELIST_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)" +DEFAULT_LINT_BLACKLIST_REGEX = r"$^" + +try: + # depot_tools may already be in the import path. + import cpplint + import cpplint_chromium +except ImportError, e: + # Search the PATH environment variable to find the depot_tools folder. + depot_tools = None; + paths = os.environ.get('PATH').split(os.pathsep) + for path in paths: + if os.path.exists(os.path.join(path, 'cpplint_chromium.py')): + depot_tools = path + break + + if depot_tools is None: + print >> sys.stderr, 'Error: could not find depot_tools in PATH.' + sys.exit(2) + + # Add depot_tools to import path. + sys.path.append(depot_tools) + import cpplint + import cpplint_chromium + +# The default implementation of FileInfo.RepositoryName looks for the top-most +# directory that contains a .git or .svn folder. This is a problem for CEF +# because the CEF root folder (which may have an arbitrary name) lives inside +# the Chromium src folder. Reimplement in a dumb but sane way. +def patch_RepositoryName(self): + fullname = self.FullName() + project_dir = os.path.dirname(fullname) + if os.path.exists(fullname): + root_dir = project_dir + while os.path.basename(project_dir) != "src": + project_dir = os.path.dirname(project_dir) + prefix = os.path.commonprefix([root_dir, project_dir]) + components = fullname[len(prefix) + 1:].split('/') + return string.join(["cef"] + components[1:], '/') + return fullname + +def check_style(args, white_list = None, black_list = None): + """ Execute cpplint with the specified arguments. """ + + # Apply patches. + cpplint.FileInfo.RepositoryName = patch_RepositoryName + + # Process cpplint arguments. + filenames = cpplint.ParseArguments(args) + + if not white_list: + white_list = DEFAULT_LINT_WHITELIST_REGEX + white_regex = re.compile(white_list) + if not black_list: + black_list = DEFAULT_LINT_BLACKLIST_REGEX + black_regex = re.compile(black_list) + + extra_check_functions = [cpplint_chromium.CheckPointerDeclarationWhitespace] + + for filename in filenames: + if white_regex.match(filename): + if black_regex.match(filename): + print "Ignoring file %s" % filename + else: + cpplint.ProcessFile(filename, cpplint._cpplint_state.verbose_level, + extra_check_functions) + else: + print "Skipping file %s" % filename + + print "Total errors found: %d\n" % cpplint._cpplint_state.error_count + return 1 + +def get_changed_files(): + """ Retrieve the list of changed files. """ + try: + return svn.get_changed_files(cef_dir) + except: + return git.get_changed_files(cef_dir) + +if __name__ == "__main__": + # Start with the default parameters. + args = [ + # * Disable the 'build/class' test because it errors uselessly with C + # structure pointers and template declarations. + # * Disable the 'runtime/references' test because CEF allows non-const + # arguments passed by reference. + # * Disable the 'runtime/sizeof' test because it has a high number of + # false positives and adds marginal value. + '--filter=-build/class,-runtime/references,-runtime/sizeof', + ] + + # Add anything passed on the command-line. + args += sys.argv[1:] + + # Pre-process the arguments before passing to the linter. + new_args = [] + changed = [] + for arg in args: + if arg == '--changed': + # Add any changed files. + changed = get_changed_files() + elif arg[:2] == '--' or not os.path.isdir(arg): + # Pass argument unchanged. + new_args.append(arg) + else: + # Add all files in the directory. + new_args += get_files(os.path.join(arg, '*')) + + if len(changed) > 0: + new_args += changed + + check_style(new_args) diff --git a/tools/check_style.sh b/tools/check_style.sh new file mode 100755 index 000000000..3a38a6ab7 --- /dev/null +++ b/tools/check_style.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python check_style.py $@ diff --git a/tools/combine_libs.py b/tools/combine_libs.py new file mode 100644 index 000000000..8e78efa87 --- /dev/null +++ b/tools/combine_libs.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# 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. + +# TODO(slightlyoff): move to using shared version of this script. + +'''This script makes it easy to combine libs and object files to a new lib, +optionally removing some of the object files in the input libs by regular +expression matching. +For usage information, run the script with a --help argument. +''' +import optparse +import os +import re +import subprocess +import sys + + +def Shell(*args): + '''Runs the program and args in args, returns the output from the program.''' + process = subprocess.Popen(args, + stdin = None, + stdout = subprocess.PIPE, + stderr = subprocess.STDOUT) + output = process.stdout.readlines() + process.wait() + retcode = process.returncode + if retcode != 0: + raise RuntimeError('%s exited with status %d' % (args[0], retcode)) + return output + + +def CollectRemovals(remove_re, inputs): + '''Returns a list of all object files in inputs that match remove_re.''' + removals = [] + for input in inputs: + output = Shell('lib.exe', '/list', input) + + for line in output: + line = line.rstrip() + if remove_re.search(line): + removals.append(line) + + return removals + + +def CombineLibraries(output, remove_re, inputs): + '''Combines all the libraries and objects in inputs, while removing any + object files that match remove_re. + ''' + removals = [] + if remove_re: + removals = CollectRemovals(remove_re, inputs) + + if len(removals) > 0: + print 'Removals: ', removals + + args = ['lib.exe', '/out:%s' % output] + args += ['/remove:%s' % obj for obj in removals] + args += inputs + Shell(*args) + + +USAGE = '''usage: %prog [options] + + +Combines input libraries or objects into an output library, while removing +any object file (in the input libraries) that matches a given regular +expression. +''' + +def GetOptionParser(): + parser = optparse.OptionParser(USAGE) + parser.add_option('-o', '--output', dest = 'output', + help = 'write to this output library') + parser.add_option('-r', '--remove', dest = 'remove', + help = 'object files matching this regexp will be removed ' + 'from the output library') + return parser + + +def Main(): + '''Main function for this script''' + parser = GetOptionParser() + (opt, args) = parser.parse_args() + output = opt.output + remove = opt.remove + if not output: + parser.error('You must specify an output file') + + if not args: + parser.error('You must specify at least one object or library') + + output = output.strip() + if remove: + remove = remove.strip() + + if remove: + try: + remove_re = re.compile(opt.remove) + except: + parser.error('%s is not a valid regular expression' % opt.remove) + else: + remove_re = None + + if sys.platform != 'win32' and sys.platform != 'cygwin': + parser.error('this script only works on Windows for now') + + # If this is set, we can't capture lib.exe's output. + if 'VS_UNICODE_OUTPUT' in os.environ: + del os.environ['VS_UNICODE_OUTPUT'] + + CombineLibraries(output, remove_re, args) + return 0 + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/tools/date_util.py b/tools/date_util.py new file mode 100644 index 000000000..ca447f309 --- /dev/null +++ b/tools/date_util.py @@ -0,0 +1,13 @@ +# 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. + +import datetime + +def get_year(): + """ Returns the current year. """ + return str(datetime.datetime.now().year) + +def get_date(): + """ Returns the current date. """ + return datetime.datetime.now().strftime('%B %d, %Y') diff --git a/tools/distrib/README-TRANSFER.txt b/tools/distrib/README-TRANSFER.txt new file mode 100644 index 000000000..6843cc201 --- /dev/null +++ b/tools/distrib/README-TRANSFER.txt @@ -0,0 +1,5 @@ +Files in this directory have been copied from other locations in the Chromium +source tree. They have been modified only to the extent necessary to work in +the CEF Binary Distribution directory structure. Below is a listing of the +original file locations. + diff --git a/tools/distrib/README.client.txt b/tools/distrib/README.client.txt new file mode 100644 index 000000000..650c078a0 --- /dev/null +++ b/tools/distrib/README.client.txt @@ -0,0 +1,12 @@ +CONTENTS +-------- + +Release Contains a release build of the cefclient sample application. + + +USAGE +----- + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/README.footer.txt b/tools/distrib/README.footer.txt new file mode 100644 index 000000000..e57a66224 --- /dev/null +++ b/tools/distrib/README.footer.txt @@ -0,0 +1,8 @@ +LICENSING +--------- + +The CEF project is BSD licensed. Please read the LICENSE.txt file included with +this binary distribution for licensing terms and conditions. Other software +included in this distribution is provided under other licenses. Please visit +"about:credits" in a CEF-based application for complete Chromium and third-party +licensing information. diff --git a/tools/distrib/README.header.txt b/tools/distrib/README.header.txt new file mode 100644 index 000000000..4bcfc0911 --- /dev/null +++ b/tools/distrib/README.header.txt @@ -0,0 +1,14 @@ +Chromium Embedded Framework (CEF) $DISTRIB_TYPE$ Binary Distribution for $PLATFORM$ +------------------------------------------------------------------------------- + +Date: $DATE$ + +CEF Version: $CEF_VER$ +CEF URL: $CEF_URL$ + @$CEF_REV$ + +Chromium Verison: $CHROMIUM_VER$ +Chromium URL: $CHROMIUM_URL$ + @$CHROMIUM_REV$ + +$DISTRIB_DESC$ diff --git a/tools/distrib/cefclient.gyp b/tools/distrib/cefclient.gyp new file mode 100644 index 000000000..83f817bbf --- /dev/null +++ b/tools/distrib/cefclient.gyp @@ -0,0 +1,677 @@ +# 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. + +{ + 'variables': { + 'chromium_code': 1, + 'framework_name': 'Chromium Embedded Framework', + 'linux_use_gold_binary': 0, + 'linux_use_gold_flags': 0, + 'conditions': [ + [ 'OS=="mac"', { + # Don't use clang with CEF binary releases due to Chromium tree structure dependency. + 'clang': 0, + }], + ['sysroot!=""', { + 'pkg-config': './pkg-config-wrapper "<(sysroot)" "<(target_arch)"', + }, { + 'pkg-config': 'pkg-config' + }], + [ 'OS=="win"', { + 'multi_threaded_dll%': 0, + }], + ] + }, + 'includes': [ + # Bring in the source file lists for cefclient. + 'cef_paths2.gypi', + ], + 'targets': [ + { + 'target_name': 'cefclient', + 'type': 'executable', + 'mac_bundle': 1, + 'msvs_guid': '6617FED9-C5D4-4907-BF55-A90062A6683F', + 'dependencies': [ + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + '<@(includes_common)', + '<@(includes_wrapper)', + '<@(cefclient_sources_common)', + ], + 'mac_bundle_resources': [ + '<@(cefclient_bundle_resources_mac)', + ], + 'mac_bundle_resources!': [ + # TODO(mark): Come up with a fancier way to do this (mac_info_plist?) + # that automatically sets the correct INFOPLIST_FILE setting and adds + # the file to a source group. + 'cefclient/mac/Info.plist', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'cefclient/mac/Info.plist', + # Target build path. + 'SYMROOT': 'xcodebuild', + }, + 'conditions': [ + ['OS=="win"', { + 'variables': { + 'win_exe_compatibility_manifest': 'cefclient/compatibility.manifest', + }, + 'actions': [ + { + 'action_name': 'copy_resources', + 'msvs_cygwin_shell': 0, + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/copy_resources.stamp', + ], + 'action': [ + 'xcopy /efy', + 'Resources\*', + '$(OutDir)', + ], + }, + { + 'action_name': 'copy_libraries', + 'msvs_cygwin_shell': 0, + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/copy_resources.stamp', + ], + 'action': [ + 'xcopy /efy', + '$(ConfigurationName)\*.dll', + '$(OutDir)', + ], + }, + ], + 'msvs_settings': { + 'VCLinkerTool': { + # Set /SUBSYSTEM:WINDOWS. + 'SubSystem': '2', + }, + 'VCManifestTool': { + 'AdditionalManifestFiles': [ + 'cefclient/cefclient.exe.manifest', + ], + }, + }, + 'link_settings': { + 'libraries': [ + '-lcomctl32.lib', + '-lshlwapi.lib', + '-lrpcrt4.lib', + '-lopengl32.lib', + '-lglu32.lib', + '-l$(ConfigurationName)/libcef.lib', + ], + }, + 'library_dirs': [ + # Needed to find cef_sandbox.lib using #pragma comment(lib, ...). + '$(ConfigurationName)', + ], + 'sources': [ + '<@(includes_win)', + '<@(cefclient_sources_win)', + ], + }], + [ 'OS=="win" and multi_threaded_dll', { + 'configurations': { + 'Debug': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 3, + 'WarnAsError': 'false', + }, + }, + }, + 'Release': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 2, + 'WarnAsError': 'false', + }, + }, + } + } + }], + [ 'OS=="mac"', { + 'product_name': 'cefclient', + 'dependencies': [ + 'cefclient_helper_app', + ], + 'copies': [ + { + # Add libraries and helper app. + 'destination': '<(PRODUCT_DIR)/cefclient.app/Contents/Frameworks', + 'files': [ + '<(PRODUCT_DIR)/cefclient Helper.app', + ], + }, + ], + 'postbuilds': [ + { + 'postbuild_name': 'Add framework', + 'action': [ + 'cp', + '-Rf', + '${CONFIGURATION}/<(framework_name).framework', + '${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/Frameworks/' + ], + }, + { + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + { + # This postbuid step is responsible for creating the following + # helpers: + # + # cefclient Helper EH.app and cefclient Helper NP.app are created + # from cefclient Helper.app. + # + # The EH helper is marked for an executable heap. The NP helper + # is marked for no PIE (ASLR). + 'postbuild_name': 'Make More Helpers', + 'action': [ + 'tools/make_more_helpers.sh', + 'Frameworks', + 'cefclient', + ], + }, + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', + '$(CONFIGURATION)/<(framework_name).framework/<(framework_name)', + ], + }, + 'sources': [ + '<@(includes_mac)', + '<@(cefclient_sources_mac)', + ], + }], + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/files', + 'files': [ + '<@(cefclient_bundle_resources_linux)', + ], + }, + { + 'destination': '<(PRODUCT_DIR)/', + 'files': [ + 'Resources/cef.pak', + 'Resources/cef_100_percent.pak', + 'Resources/cef_200_percent.pak', + 'Resources/devtools_resources.pak', + 'Resources/icudtl.dat', + 'Resources/locales/', + '$(BUILDTYPE)/chrome-sandbox', + '$(BUILDTYPE)/libcef.so', + '$(BUILDTYPE)/libffmpegsumo.so', + '$(BUILDTYPE)/libpdf.so', + ], + }, + ], + 'dependencies': [ + 'gtk', + 'gtkglext', + ], + 'link_settings': { + 'ldflags': [ + # Look for libcef.so in the current directory. Path can also be + # specified using the LD_LIBRARY_PATH environment variable. + '-Wl,-rpath,.', + ], + 'libraries': [ + "$(BUILDTYPE)/libcef.so", + "-lX11", + ], + }, + 'sources': [ + '<@(includes_linux)', + '<@(cefclient_sources_linux)', + ], + }], + ], + }, + { + 'target_name': 'cefsimple', + 'type': 'executable', + 'mac_bundle': 1, + 'msvs_guid': '5390D142-473F-49A0-BC5E-5F6C609EEDB6', + 'dependencies': [ + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + '<@(includes_common)', + '<@(includes_wrapper)', + '<@(cefsimple_sources_common)', + ], + 'mac_bundle_resources': [ + '<@(cefsimple_bundle_resources_mac)', + ], + 'mac_bundle_resources!': [ + # TODO(mark): Come up with a fancier way to do this (mac_info_plist?) + # that automatically sets the correct INFOPLIST_FILE setting and adds + # the file to a source group. + 'cefsimple/mac/Info.plist', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'cefsimple/mac/Info.plist', + # Target build path. + 'SYMROOT': 'xcodebuild', + }, + 'conditions': [ + ['OS=="win"', { + 'variables': { + 'win_exe_compatibility_manifest': 'cefsimple/compatibility.manifest', + }, + 'actions': [ + { + 'action_name': 'copy_resources', + 'msvs_cygwin_shell': 0, + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/copy_resources.stamp', + ], + 'action': [ + 'xcopy /efy', + 'Resources\*', + '$(OutDir)', + ], + }, + { + 'action_name': 'copy_libraries', + 'msvs_cygwin_shell': 0, + 'inputs': [], + 'outputs': [ + '<(PRODUCT_DIR)/copy_resources.stamp', + ], + 'action': [ + 'xcopy /efy', + '$(ConfigurationName)\*.dll', + '$(OutDir)', + ], + }, + ], + 'msvs_settings': { + 'VCLinkerTool': { + # Set /SUBSYSTEM:WINDOWS. + 'SubSystem': '2', + }, + 'VCManifestTool': { + 'AdditionalManifestFiles': [ + 'cefsimple/cefsimple.exe.manifest', + ], + }, + }, + 'link_settings': { + 'libraries': [ + '-lcomctl32.lib', + '-lshlwapi.lib', + '-lrpcrt4.lib', + '-l$(ConfigurationName)/libcef.lib', + ], + }, + 'library_dirs': [ + # Needed to find cef_sandbox.lib using #pragma comment(lib, ...). + '$(ConfigurationName)', + ], + 'sources': [ + '<@(includes_win)', + '<@(cefsimple_sources_win)', + ], + }], + [ 'OS=="win" and multi_threaded_dll', { + 'configurations': { + 'Debug': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 3, + 'WarnAsError': 'false', + }, + }, + }, + 'Release': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 2, + 'WarnAsError': 'false', + }, + }, + } + } + }], + [ 'OS=="mac"', { + 'product_name': 'cefsimple', + 'dependencies': [ + 'cefsimple_helper_app', + ], + 'copies': [ + { + # Add libraries and helper app. + 'destination': '<(PRODUCT_DIR)/cefsimple.app/Contents/Frameworks', + 'files': [ + '<(PRODUCT_DIR)/cefsimple Helper.app', + ], + }, + ], + 'postbuilds': [ + { + 'postbuild_name': 'Add framework', + 'action': [ + 'cp', + '-Rf', + '${CONFIGURATION}/<(framework_name).framework', + '${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/Frameworks/' + ], + }, + { + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + { + # This postbuid step is responsible for creating the following + # helpers: + # + # cefsimple Helper EH.app and cefsimple Helper NP.app are created + # from cefsimple Helper.app. + # + # The EH helper is marked for an executable heap. The NP helper + # is marked for no PIE (ASLR). + 'postbuild_name': 'Make More Helpers', + 'action': [ + 'tools/make_more_helpers.sh', + 'Frameworks', + 'cefsimple', + ], + }, + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + '$(CONFIGURATION)/<(framework_name).framework/<(framework_name)', + ], + }, + 'sources': [ + '<@(includes_mac)', + '<@(cefsimple_sources_mac)', + ], + }], + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/', + 'files': [ + 'Resources/cef.pak', + 'Resources/cef_100_percent.pak', + 'Resources/cef_200_percent.pak', + 'Resources/devtools_resources.pak', + 'Resources/icudtl.dat', + 'Resources/locales/', + '$(BUILDTYPE)/chrome-sandbox', + '$(BUILDTYPE)/libcef.so', + '$(BUILDTYPE)/libffmpegsumo.so', + '$(BUILDTYPE)/libpdf.so', + ], + }, + ], + 'link_settings': { + 'ldflags': [ + # Look for libcef.so in the current directory. Path can also be + # specified using the LD_LIBRARY_PATH environment variable. + '-Wl,-rpath,.', + ], + 'libraries': [ + "$(BUILDTYPE)/libcef.so", + "-lX11", + ], + }, + 'sources': [ + '<@(includes_linux)', + '<@(cefsimple_sources_linux)', + ], + }], + ], + }, + { + 'target_name': 'libcef_dll_wrapper', + 'type': 'static_library', + 'msvs_guid': 'A9D6DC71-C0DC-4549-AEA0-3B15B44E86A9', + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'sources': [ + '<@(includes_common)', + '<@(includes_capi)', + '<@(includes_wrapper)', + '<@(libcef_dll_wrapper_sources_common)', + ], + 'xcode_settings': { + # Target build path. + 'SYMROOT': 'xcodebuild', + }, + 'conditions': [ + [ 'OS=="win" and multi_threaded_dll', { + 'configurations': { + 'Debug': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 3, + 'WarnAsError': 'false', + }, + }, + }, + 'Release': { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'RuntimeLibrary': 2, + 'WarnAsError': 'false', + }, + }, + } + } + }], + ], + }, + ], + 'conditions': [ + ['OS=="mac"', { + 'targets': [ + { + 'target_name': 'cefclient_helper_app', + 'type': 'executable', + 'variables': { 'enable_wexit_time_destructors': 1, }, + 'product_name': 'cefclient Helper', + 'mac_bundle': 1, + 'dependencies': [ + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + '$(CONFIGURATION)/<(framework_name).framework/<(framework_name)', + ], + }, + 'sources': [ + '<@(cefclient_sources_mac_helper)', + ], + # TODO(mark): Come up with a fancier way to do this. It should only + # be necessary to list helper-Info.plist once, not the three times it + # is listed here. + 'mac_bundle_resources!': [ + 'cefclient/mac/helper-Info.plist', + ], + # TODO(mark): For now, don't put any resources into this app. Its + # resources directory will be a symbolic link to the browser app's + # resources directory. + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'cefclient/mac/helper-Info.plist', + }, + 'postbuilds': [ + { + # The framework defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # cefclient_helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + ], + }, # target cefclient_helper_app + { + 'target_name': 'cefsimple_helper_app', + 'type': 'executable', + 'variables': { 'enable_wexit_time_destructors': 1, }, + 'product_name': 'cefsimple Helper', + 'mac_bundle': 1, + 'dependencies': [ + 'libcef_dll_wrapper', + ], + 'defines': [ + 'USING_CEF_SHARED', + ], + 'include_dirs': [ + '.', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + '$(CONFIGURATION)/<(framework_name).framework/<(framework_name)', + ], + }, + 'sources': [ + '<@(cefsimple_sources_mac_helper)', + ], + # TODO(mark): Come up with a fancier way to do this. It should only + # be necessary to list helper-Info.plist once, not the three times it + # is listed here. + 'mac_bundle_resources!': [ + 'cefsimple/mac/helper-Info.plist', + ], + # TODO(mark): For now, don't put any resources into this app. Its + # resources directory will be a symbolic link to the browser app's + # resources directory. + 'mac_bundle_resources/': [ + ['exclude', '.*'], + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'cefsimple/mac/helper-Info.plist', + }, + 'postbuilds': [ + { + # The framework defines its load-time path + # (DYLIB_INSTALL_NAME_BASE) relative to the main executable + # (chrome). A different relative path needs to be used in + # cefsimple_helper_app. + 'postbuild_name': 'Fix Framework Link', + 'action': [ + 'install_name_tool', + '-change', + '@executable_path/<(framework_name)', + '@executable_path/../../../../Frameworks/<(framework_name).framework/<(framework_name)', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}' + ], + }, + ], + }, # target cefsimple_helper_app + ], + }], # OS=="mac" + [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'targets': [ + { + 'target_name': 'gtk', + 'type': 'none', + 'variables': { + # gtk requires gmodule, but it does not list it as a dependency + # in some misconfigured systems. + 'gtk_packages': 'gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0', + }, + 'direct_dependent_settings': { + 'cflags': [ + '$(shell <(pkg-config) --cflags <(gtk_packages))', + ], + }, + 'link_settings': { + 'ldflags': [ + '$(shell <(pkg-config) --libs-only-L --libs-only-other <(gtk_packages))', + ], + 'libraries': [ + '$(shell <(pkg-config) --libs-only-l <(gtk_packages))', + ], + }, + }, + { + 'target_name': 'gtkglext', + 'type': 'none', + 'variables': { + # gtkglext is required by the cefclient OSR example. + 'gtk_packages': 'gtkglext-1.0', + }, + 'direct_dependent_settings': { + 'cflags': [ + '$(shell <(pkg-config) --cflags <(gtk_packages))', + ], + }, + 'link_settings': { + 'ldflags': [ + '$(shell <(pkg-config) --libs-only-L --libs-only-other <(gtk_packages))', + ], + 'libraries': [ + '$(shell <(pkg-config) --libs-only-l <(gtk_packages))', + ], + }, + }, + ], + }], # OS=="linux" or OS=="freebsd" or OS=="openbsd" + ], +} diff --git a/tools/distrib/linux/README.minimal.txt b/tools/distrib/linux/README.minimal.txt new file mode 100644 index 000000000..abe1d2224 --- /dev/null +++ b/tools/distrib/linux/README.minimal.txt @@ -0,0 +1,17 @@ +CONTENTS +-------- + +Release Contains libcef.so and other components required to run the release + version of CEF-based applications. By default these files should be + placed in the same directory as the executable. + +Resources Contains resources required by libcef.so. By default these files + should be placed in the same directory as libcef.so. + + +USAGE +----- + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/linux/README.redistrib.txt b/tools/distrib/linux/README.redistrib.txt new file mode 100644 index 000000000..2204202b5 --- /dev/null +++ b/tools/distrib/linux/README.redistrib.txt @@ -0,0 +1,43 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. Components listed under +the "required" section must be redistributed with all applications using CEF. +Components listed under the "optional" section may be excluded if the related +features will not be used. + +Required components: + +* CEF core library + libcef.so + +* Unicode support + icudtl.dat + +Optional components: + +* Localized resources + locales/ + Note: Contains localized strings for WebKit UI controls. A .pak file is loaded + from this folder based on the value of environment variables which are read + with the following precedence order: LANGUAGE, LC_ALL, LC_MESSAGES and LANG. + Only configured locales need to be distributed. If no locale is configured the + default locale of "en-US" will be used. Locale file loading can be disabled + completely using CefSettings.pack_loading_disabled. The locales folder path + can be customized using CefSettings.locales_dir_path. + +* Other resources + cef.pak + cef_100_percent.pak + cef_200_percent.pak + devtools_resources.pak + Note: Contains WebKit image and inspector resources. Pack file loading can be + disabled completely using CefSettings.pack_loading_disabled. The resources + directory path can be customized using CefSettings.resources_dir_path. + +* FFmpeg audio and video support + libffmpegsumo.so + Note: Without this component HTML5 audio and video will not function. + +* PDF support + libpdf.so diff --git a/tools/distrib/linux/README.standard.txt b/tools/distrib/linux/README.standard.txt new file mode 100644 index 000000000..34ffbcf33 --- /dev/null +++ b/tools/distrib/linux/README.standard.txt @@ -0,0 +1,39 @@ +CONTENTS +-------- + +cefclient Contains the cefclient sample application configured to build + using the files in this distribution. This application demonstrates + a wide range of CEF functionalities. + +cefsimple Contains the cefsimple sample application configured to build + using the files in this distribution. This application demonstrates + the minimal functionality required to create a browser window. + +Debug Contains libcef.so and other components required to run the debug + version of CEF-based applications. By default these files should be + placed in the same directory as the executable and will be copied + there as part of the build process. + +include Contains all required CEF header files. + +libcef_dll Contains the source code for the libcef_dll_wrapper static library + that all applications using the CEF C++ API must link against. + +Release Contains libcef.so and other components required to run the release + version of CEF-based applications. By default these files should be + placed in the same directory as the executable and will be copied + there as part of the build process. + +Resources Contains resources required by libcef.so. By default these files + should be placed in the same directory as libcef.so and will be + copied there as part of the build process. + + +USAGE +----- + +Run 'build.sh Debug' to build the cefclient target in Debug mode. + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/linux/build.sh b/tools/distrib/linux/build.sh new file mode 100755 index 000000000..08b4e49d8 --- /dev/null +++ b/tools/distrib/linux/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash +if [ -z "$1" ]; then + echo "ERROR: Please specify a build target: Debug or Release" +else + make -j8 cefclient cefsimple BUILDTYPE=$1 + if [ $? -eq 0 ]; then + echo "Giving SUID permissions to chrome-sandbox..." + echo "(using sudo so you may be asked for your password)" + sudo -- chown root:root "out/$1/chrome-sandbox" && + sudo -- chmod 4755 "out/$1/chrome-sandbox" + fi +fi diff --git a/tools/distrib/mac/README.minimal.txt b/tools/distrib/mac/README.minimal.txt new file mode 100644 index 000000000..0b276f8c1 --- /dev/null +++ b/tools/distrib/mac/README.minimal.txt @@ -0,0 +1,14 @@ +CONTENTS +-------- + +Release Contains the "Chromium Embedded Framework.framework" and other + components required to run the release version of CEF-based + applications. + + +USAGE +----- + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/mac/README.redistrib.txt b/tools/distrib/mac/README.redistrib.txt new file mode 100644 index 000000000..f2ff29222 --- /dev/null +++ b/tools/distrib/mac/README.redistrib.txt @@ -0,0 +1,108 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. Components listed under +the "required" section must be redistributed with all applications using CEF. +Components listed under the "optional" section may be excluded if the related +features will not be used. + +Applications using CEF on OS X must follow a specific app bundle structure. +Replace "cefclient" in the below example with your application name. + +cefclient.app/ + Contents/ + Frameworks/ + Chromium Embedded Framework.framework/ + Chromium Embedded Framework <= main application library + Libraries/ + ffmpegsumo.so <= HTML5 audio/video support library + PDF.plugin <= Pepper plugin for PDF support + Resources/ + cef.pak <= non-localized resources and strings + cef_100_percent.pak <====^ + cef_200_percent.pak <====^ + devtools_resources.pak <=^ + crash_inspector, crash_report_sender <= breakpad support + icudtl.dat <= unicode support + en.lproj/, ... <= locale-specific resources and strings + Info.plist + cefclient Helper.app/ + Contents/ + Info.plist + MacOS/ + cefclient Helper <= helper executable + Pkginfo + cefclient Helper EH.app/ + Contents/ + Info.plist + MacOS/ + cefclient Helper EH <= helper executable + Pkginfo + cefclient Helper NP.app/ + Contents/ + Info.plist + MacOS/ + cefclient Helper NP <= helper executable + Pkginfo + Info.plist + MacOS/ + cefclient <= cefclient application executable + Pkginfo + Resources/ + binding.html, ... <= cefclient application resources + +The "Chromium Embedded Framework.framework" is an unversioned framework that +contains CEF binaries and resources. Executables (cefclient, cefclient Helper, +etc) are linked to the "Chromium Embedded Framework" library using +install_name_tool and a path relative to @executable_path. + +The "cefclient Helper" apps are used for executing separate processes +(renderer, plugin, etc) with different characteristics. They need to have +separate app bundles and Info.plist files so that, among other things, they +don't show dock icons. The "EH" helper, which is used when launching plugin +processes, has the MH_NO_HEAP_EXECUTION bit cleared to allow an executable +heap. The "NP" helper, which is used when launching NaCl plugin processes +only, has the MH_PIE bit cleared to disable ASLR. This is set up as part of +the build process using scripts from the tools/ directory. Examine the Xcode +project included with the binary distribution or the originating cefclient.gyp +file for a better idea of the script dependencies. + +Required components: + +* CEF framework library + Chromium Embedded Framework.framework/Chromium Embedded Framework + +* Unicode support + Chromium Embedded Framework.framework/Resources/icudtl.dat + +Optional components: + +* Localized resources + Chromium Embedded Framework.framework/Resources/*.lproj/ + Note: Contains localized strings for WebKit UI controls. A .pak file is loaded + from this folder based on the CefSettings.locale value. Only configured + locales need to be distributed. If no locale is configured the default locale + of "en" will be used. Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. + +* Other resources + Chromium Embedded Framework.framework/Resources/cef.pak + Chromium Embedded Framework.framework/Resources/cef_100_percent.pak + Chromium Embedded Framework.framework/Resources/cef_200_percent.pak + Chromium Embedded Framework.framework/Resources/devtools_resources.pak + Note: Contains WebKit image and inspector resources. Pack file loading can be + disabled completely using CefSettings.pack_loading_disabled. The resources + directory path can be customized using CefSettings.resources_dir_path. + +* FFmpeg audio and video support + Chromium Embedded Framework.framework/Libraries/ffmpegsumo.so + Note: Without this component HTML5 audio and video will not function. + +* PDF support + Chromium Embedded Framework.framework/Libraries/PDF.plugin + +* Breakpad support + Chromium Embedded Framework.framework/Resources/crash_inspector + Chromium Embedded Framework.framework/Resources/crash_report_sender + Chromium Embedded Framework.framework/Resources/Info.plist + Note: Without these components breakpad support will not function. diff --git a/tools/distrib/mac/README.standard.txt b/tools/distrib/mac/README.standard.txt new file mode 100644 index 000000000..f7eb9891e --- /dev/null +++ b/tools/distrib/mac/README.standard.txt @@ -0,0 +1,35 @@ +CONTENTS +-------- + +cefclient Contains the cefclient sample application configured to build + using the files in this distribution. This application demonstrates + a wide range of CEF functionalities. + +cefsimple Contains the cefsimple sample application configured to build + using the files in this distribution. This application demonstrates + the minimal functionality required to create a browser window. + +Debug Contains the "Chromium Embedded Framework.framework" and other + components required to run the debug version of CEF-based + applications. + +include Contains all required CEF header files. + +libcef_dll Contains the source code for the libcef_dll_wrapper static library + that all applications using the CEF C++ API must link against. + +Release Contains the "Chromium Embedded Framework.framework" and other + components required to run the release version of CEF-based + applications. + +tools Scripts that perform post-processing on Mac release targets. + + +USAGE +----- + +Xcode 3 and 4: Open the cefclient.xcodeproj project and build. + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/mac/transfer.cfg b/tools/distrib/mac/transfer.cfg new file mode 100644 index 000000000..952c06166 --- /dev/null +++ b/tools/distrib/mac/transfer.cfg @@ -0,0 +1,33 @@ +# Additional handling of transfer files. +# target: Target location relative to the target release directory. This +# value is required. +# source: Source location relative to the CEF root directory. This value +# is optional. If specified the target will be copied to this location +# and a TRANSFER-README.txt file will be created. +# post-process: Post-processing operation to perform. This value is +# optional and may be any one of the following: +# 'normalize_headers': Replace fully-qualified project header paths with +# the optionally specified 'new_header_path' value. + +[ + { + 'source' : '../build/mac/change_mach_o_flags_from_xcode.sh', + 'target' : 'tools/change_mach_o_flags_from_xcode.sh', + }, + { + 'source' : '../build/mac/change_mach_o_flags.py', + 'target' : 'tools/change_mach_o_flags.py', + }, + { + 'source' : '../build/mac/strip_from_xcode', + 'target' : 'tools/strip_from_xcode', + }, + { + 'source' : '../build/mac/strip_save_dsym', + 'target' : 'tools/strip_save_dsym', + }, + { + 'source' : '../build/mac/make_more_helpers.sh', + 'target' : 'tools/make_more_helpers.sh', + }, +] diff --git a/tools/distrib/transfer.cfg b/tools/distrib/transfer.cfg new file mode 100644 index 000000000..a0e42dc57 --- /dev/null +++ b/tools/distrib/transfer.cfg @@ -0,0 +1,13 @@ +# Additional handling of transfer files. +# target: Target location relative to the target release directory. This +# value is required. +# source: Source location relative to the CEF root directory. This value +# is optional. If specified the target will be copied to this location +# and a TRANSFER-README.txt file will be created. +# post-process: Post-processing operation to perform. This value is +# optional and may be any one of the following: +# 'normalize_headers': Replace fully-qualified project header paths with +# the optionally specified 'new_header_path' value. + +[ +] \ No newline at end of file diff --git a/tools/distrib/win/README.minimal.txt b/tools/distrib/win/README.minimal.txt new file mode 100644 index 000000000..ac450fbd2 --- /dev/null +++ b/tools/distrib/win/README.minimal.txt @@ -0,0 +1,19 @@ +CONTENTS +-------- + +Release Contains libcef.dll, libcef.lib and other components required to + build and run the release version of CEF-based applications. By + default these files should be placed in the same directory as the + executable. + +Resources Contains resources required by libcef.dll. By default these files + should be placed in the same directory as libcef.dll. By default + these files should be placed in the same directory as libcef.dll. + + +USAGE +----- + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/win/README.redistrib.txt b/tools/distrib/win/README.redistrib.txt new file mode 100644 index 000000000..619c1476c --- /dev/null +++ b/tools/distrib/win/README.redistrib.txt @@ -0,0 +1,51 @@ +REDISTRIBUTION +-------------- + +This binary distribution contains the below components. Components listed under +the "required" section must be redistributed with all applications using CEF. +Components listed under the "optional" section may be excluded if the related +features will not be used. + +Required components: + +* CEF core library + libcef.dll + +* Unicode support + icudtl.dat + +Optional components: + +* Localized resources + locales/ + Note: Contains localized strings for WebKit UI controls. A .pak file is loaded + from this folder based on the CefSettings.locale value. Only configured + locales need to be distributed. If no locale is configured the default locale + of "en-US" will be used. Locale file loading can be disabled completely using + CefSettings.pack_loading_disabled. The locales folder path can be customized + using CefSettings.locales_dir_path. + +* Other resources + cef.pak + cef_100_percent.pak + cef_200_percent.pak + devtools_resources.pak + Note: Contains WebKit image and inspector resources. Pack file loading can be + disabled completely using CefSettings.pack_loading_disabled. The resources + directory path can be customized using CefSettings.resources_dir_path. + +* FFmpeg audio and video support + ffmpegsumo.dll + Note: Without this component HTML5 audio and video will not function. + +* PDF support + pdf.dll + Note: Without this component printing will not function. + +* Angle and Direct3D support + d3dcompiler_43.dll (required for Windows XP) + d3dcompiler_46.dll (required for Windows Vista and newer) + libEGL.dll + libGLESv2.dll + Note: Without these components HTML5 accelerated content like 2D canvas, 3D + CSS and WebGL will not function. diff --git a/tools/distrib/win/README.standard.txt b/tools/distrib/win/README.standard.txt new file mode 100644 index 000000000..03d2ffb87 --- /dev/null +++ b/tools/distrib/win/README.standard.txt @@ -0,0 +1,51 @@ +CONTENTS +-------- + +cefclient Contains the cefclient sample application configured to build + using the files in this distribution. This application demonstrates + a wide range of CEF functionalities. + +cefsimple Contains the cefsimple sample application configured to build + using the files in this distribution. This application demonstrates + the minimal functionality required to create a browser window. + +Debug Contains libcef.dll, libcef.lib and other components required to + build and run the debug version of CEF-based applications. By + default these files should be placed in the same directory as the + executable and will be copied there as part of the build process. + +include Contains all required CEF header files. + +libcef_dll Contains the source code for the libcef_dll_wrapper static library + that all applications using the CEF C++ API must link against. + +Release Contains libcef.dll, libcef.lib and other components required to + build and run the release version of CEF-based applications. By + default these files should be placed in the same directory as the + executable and will be copied there as part of the build process. + +Resources Contains resources required by libcef.dll. By default these files + should be placed in the same directory as libcef.dll. By default + these files should be placed in the same directory as libcef.dll + and will be copied there as part of the build process. + + +USAGE +----- + +Visual Studio 2012 and Visual Studio 2010: + Open the cefclient2010.sln solution in Visual Studio and build. + +Visual Studio 2008: + Open the cefclient2008.sln solution in Visual Studio and build. + +Visual Studio 2005: + 1. Open the cefclient.vcproj and libcef_dll_wrapper.vcproj files in a text + editor. Change Version="9.00" to Version="8.00". + 2. Open the cefclient2005.sln file in a text editor. Change "Version 9.00" to + "Version 8.00". + 3. Open the cefclient2005.sln solution in Visual Studio and build. + +Please visit the CEF Website for additional usage information. + +http://code.google.com/p/chromiumembedded diff --git a/tools/distrib/win/d3dcompiler_43.dll b/tools/distrib/win/d3dcompiler_43.dll new file mode 100644 index 0000000000000000000000000000000000000000..ab9616191fa73b5f624b85d430b3ee95d3e3c278 GIT binary patch literal 2106216 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

opkKgG?0H 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⁣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

IQ{+flxV&>Y-3RLd|51PS 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

)q-qrZC9o-JHS<*-3OqV`f*mtXPT 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⪚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

=PIn;pVSmOr?pz#>!KG=EUGvWtWB$#K=XV;7T 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 z

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 P7Bbj^zjM)+Hmew9qB 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 sys.stderr, 'Error: could not find depot_tools in PATH.' + sys.exit(2) + + # Add depot_tools to import path. + sys.path.append(depot_tools) + import gclient_utils + +# Copied from gclient.py python code. +def RunAction(dir, command): + """Runs the action.""" + if command[0] == 'python': + # If the hook specified "python" as the first item, the action is a + # Python script. Run it by starting a new copy of the same + # interpreter. + command[0] = sys.executable + + try: + gclient_utils.CheckCallAndFilterAndHeader( + command, cwd=dir, always=True) + except gclient_utils.Error, e: + # Use a discrete exit status code of 2 to indicate that a hook action + # failed. Users of this script may wish to treat hook action failures + # differently from VC failures. + print >> sys.stderr, 'Error: %s' % str(e) + sys.exit(2) diff --git a/tools/git_util.py b/tools/git_util.py new file mode 100644 index 000000000..62c9d6774 --- /dev/null +++ b/tools/git_util.py @@ -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 + +from exec_util import exec_cmd +import os + +def is_checkout(path): + """ Returns true if the path represents a git checkout. """ + return os.path.exists(os.path.join(path, '.git')) + +def get_hash(path = '.', branch = 'master'): + """ Returns the git hash for the specified branch/tag/hash. """ + cmd = "git rev-parse %s" % (branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_url(path = '.'): + """ Returns the origin url for the specified path. """ + cmd = "git config --get remote.origin.url" + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_svn_revision(path = '.', branch = 'master'): + """ Returns the SVN revision associated with the specified path and git + branch/tag/hash. """ + svn_rev = "None" + cmd = "git log --grep=^git-svn-id: -n 1 %s" % (branch) + result = exec_cmd(cmd, path) + if result['err'] == '': + for line in result['out'].split('\n'): + if line.find("git-svn-id") > 0: + svn_rev = line.split("@")[1].split()[0] + break + return svn_rev + +def get_changed_files(path = '.'): + """ Retrieves the list of changed files. """ + # not implemented + return [] diff --git a/tools/make_capi_header.py b/tools/make_capi_header.py new file mode 100644 index 000000000..8cf897773 --- /dev/null +++ b/tools/make_capi_header.py @@ -0,0 +1,202 @@ +# 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. + +from cef_parser import * +from date_util import * + +def make_capi_global_funcs(funcs, defined_names, translate_map, indent): + result = '' + first = True + for func in funcs: + comment = func.get_comment() + if first or len(comment) > 0: + result += '\n'+format_comment(comment, indent, translate_map); + if func.get_retval().get_type().is_result_string(): + result += indent+'// The resulting string must be freed by calling cef_string_userfree_free().\n' + result += wrap_code(indent+'CEF_EXPORT '+ + func.get_capi_proto(defined_names)+';') + if first: + first = False + return result + +def make_capi_member_funcs(funcs, defined_names, translate_map, indent): + result = '' + first = True + for func in funcs: + comment = func.get_comment() + if first or len(comment) > 0: + result += '\n'+format_comment(comment, indent, translate_map) + if func.get_retval().get_type().is_result_string(): + result += indent+'// The resulting string must be freed by calling cef_string_userfree_free().\n' + parts = func.get_capi_parts() + result += wrap_code(indent+parts['retval']+' (CEF_CALLBACK *'+ + parts['name']+')('+ + string.join(parts['args'], ', ')+');') + if first: + first = False + return result + +def make_capi_header(header, filename): + # structure names that have already been defined + defined_names = header.get_defined_structs() + + # map of strings that will be changed in C++ comments + translate_map = header.get_capi_translations() + + # header string + result = \ +"""// Copyright (c) $YEAR$ Marshall A. Greenblatt. 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 file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef $GUARD$ +#define $GUARD$ +#pragma once + +""" + classes = header.get_classes(filename) + + # identify all includes and forward declarations + all_includes = set([]) + all_declares = set([]) + for cls in classes: + includes = cls.get_includes() + for include in includes: + all_includes.add(include) + declares = cls.get_forward_declares() + for declare in declares: + all_declares.add(header.get_class(declare).get_capi_name()) + + # output includes + if len(all_includes) > 0: + sorted_includes = sorted(all_includes) + for include in sorted_includes: + result += '#include "include/capi/' + include + '_capi.h"\n' + else: + result += '#include "include/capi/cef_base_capi.h"\n' + + result += \ +""" +#ifdef __cplusplus +extern "C" { +#endif + +""" + + # output forward declarations + if len(all_declares) > 0: + sorted_declares = sorted(all_declares) + for declare in sorted_declares: + result += 'struct _' + declare + ';\n' + + # output classes + for cls in classes: + # virtual functions are inside the structure + classname = cls.get_capi_name() + result += '\n'+format_comment(cls.get_comment(), '', translate_map); + result += 'typedef struct _'+classname+ \ + ' {\n ///\n // Base structure.\n ///\n cef_base_t base;\n' + funcs = cls.get_virtual_funcs() + result += make_capi_member_funcs(funcs, defined_names, + translate_map, ' ') + result += '} '+classname+';\n\n' + + defined_names.append(cls.get_capi_name()) + + # static functions become global + funcs = cls.get_static_funcs() + if len(funcs) > 0: + result += make_capi_global_funcs(funcs, defined_names, + translate_map, '')+'\n' + + # output global functions + funcs = header.get_funcs(filename) + if len(funcs) > 0: + result += make_capi_global_funcs(funcs, defined_names, translate_map, '') + + # footer string + result += \ +""" +#ifdef __cplusplus +} +#endif + +#endif // $GUARD$ +""" + + # add the copyright year + result = result.replace('$YEAR$', get_year()) + # add the guard string + guard = 'CEF_INCLUDE_CAPI_'+string.upper(filename.replace('.', '_capi_'))+'_' + result = result.replace('$GUARD$', guard) + + return result + + +def write_capi_header(header, filepath, backup): + capi_path = get_capi_file_name(filepath) + if path_exists(capi_path): + oldcontents = read_file(capi_path) + else: + oldcontents = '' + + filename = os.path.split(filepath)[1] + newcontents = make_capi_header(header, filename) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(capi_path) + write_file(capi_path, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 2: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # dump the result to stdout + filename = os.path.split(sys.argv[1])[1] + sys.stdout.write(make_capi_header(header, filename)) diff --git a/tools/make_cppdocs.bat b/tools/make_cppdocs.bat new file mode 100644 index 000000000..279436074 --- /dev/null +++ b/tools/make_cppdocs.bat @@ -0,0 +1,18 @@ +@echo off +setlocal + +if "%1"=="" ( +set CPPDOC_EXE="C:\Program Files (x86)\richfeit\CppDoc\CppDoc.exe" +set CPPDOC_REV="XXX" +) else ( +set CPPDOC_EXE="C:\Program Files (x86)\richfeit\CppDoc\cppdoc_cmd.exe" +set CPPDOC_REV="%1" +) + +if not exist %CPPDOC_EXE% ( +echo ERROR: Please install CppDoc from http://www.cppdoc.com/ +) else ( +%CPPDOC_EXE% -overwrite -title="CEF3 C++ API Docs - Revision %CPPDOC_REV%" -footer="

Chromium Embedded Framework (CEF) Copyright © 2012 Marshall A. Greenblatt
" -namespace-as-project -comment-format="///;//;///" -classdir=projects -module="cppdoc-standard" -extensions=h -languages="c=cpp,cc=cpp,cpp=cpp,cs=csharp,cxx=cpp,h=cpp,hpp=cpp,hxx=cpp,java=java" -D"OS_WIN" -D"USING_CEF_SHARED" -D"__cplusplus" -D"CEF_STRING_TYPE_UTF16" -enable-author=false -enable-deprecations=true -enable-since=true -enable-version=false -file-links-for-globals=false -generate-deprecations-list=false -generate-hierarchy=true -header-background-dark="#ccccff" -header-background-light="#eeeeff" -include-private=false -include-protected=true -index-file-base=index -overview-html=overview.html -reduce-summary-font=true -selected-text-background=navy -selected-text-foreground=white -separate-index-pages=false -show-cppdoc-version=false -show-timestamp=false -summary-html=project.html -suppress-details=false -suppress-frames-links=false -table-background=white -wrap-long-lines=false ..\include #cef_runnable.h #cef_tuple.h #capi "..\docs\index.html" +) + +endlocal \ No newline at end of file diff --git a/tools/make_cpptoc_header.py b/tools/make_cpptoc_header.py new file mode 100644 index 000000000..4f930e224 --- /dev/null +++ b/tools/make_cpptoc_header.py @@ -0,0 +1,106 @@ +# 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. + +from cef_parser import * + +def make_cpptoc_header(header, clsname): + cls = header.get_class(clsname) + if cls is None: + raise Exception('Class does not exist: '+clsname) + + dllside = cls.is_library_side() + defname = string.upper(get_capi_name(clsname[3:], False)) + capiname = cls.get_capi_name() + + result = get_copyright() + + result += '#ifndef CEF_LIBCEF_DLL_CPPTOC_'+defname+'_CPPTOC_H_\n'+ \ + '#define CEF_LIBCEF_DLL_CPPTOC_'+defname+'_CPPTOC_H_\n' + \ + '#pragma once\n' + + if dllside: + result += """ +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED +""" + else: + result += """ +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED +""" + + # include the headers for this class + result += '\n#include "include/'+cls.get_file_name()+'"\n' \ + '#include "include/capi/'+cls.get_capi_file_name()+'"\n' + + # include headers for any forward declared classes that are not in the same file + declares = cls.get_forward_declares() + for declare in declares: + dcls = header.get_class(declare) + if dcls.get_file_name() != cls.get_file_name(): + result += '#include "include/'+dcls.get_file_name()+'"\n' \ + '#include "include/capi/'+dcls.get_capi_file_name()+'"\n' + + result += """#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +""" + + if dllside: + result += '// This class may be instantiated and accessed DLL-side only.\n' + else: + result += '// This class may be instantiated and accessed wrapper-side only.\n' + + result += 'class '+clsname+'CppToC\n'+ \ + ' : public CefCppToC<'+clsname+'CppToC, '+clsname+', '+capiname+'> {\n'+ \ + ' public:\n'+ \ + ' explicit '+clsname+'CppToC('+clsname+'* cls);\n'+ \ + ' virtual ~'+clsname+'CppToC() {}\n'+ \ + '};\n\n' + + if dllside: + result += '#endif // BUILDING_CEF_SHARED\n' + else: + result += '#endif // USING_CEF_SHARED\n' + + result += '#endif // CEF_LIBCEF_DLL_CPPTOC_'+defname+'_CPPTOC_H_\n' + + return wrap_code(result) + + +def write_cpptoc_header(header, clsname, dir, backup): + file = dir+os.sep+get_capi_name(clsname[3:], False)+'_cpptoc.h' + + if path_exists(file): + oldcontents = read_file(file) + else: + oldcontents = '' + + newcontents = make_cpptoc_header(header, clsname) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(file) + write_file(file, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 3: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # dump the result to stdout + sys.stdout.write(make_cpptoc_header(header, sys.argv[2])) diff --git a/tools/make_cpptoc_impl.py b/tools/make_cpptoc_impl.py new file mode 100644 index 000000000..7d7f0aedb --- /dev/null +++ b/tools/make_cpptoc_impl.py @@ -0,0 +1,571 @@ +# 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. + +from cef_parser import * + +def make_cpptoc_impl_proto(name, func, parts): + if isinstance(func, obj_function_virtual): + proto = parts['retval']+' CEF_CALLBACK' + else: + proto = 'CEF_EXPORT '+parts['retval'] + + proto += ' '+name+'('+string.join(parts['args'], ', ')+')' + return proto + +def make_cpptoc_function_impl_existing(name, func, impl, defined_names): + notify(name+' has manual edits') + + # retrieve the C API prototype parts + parts = func.get_capi_parts(defined_names) + + changes = format_translation_changes(impl, parts) + if len(changes) > 0: + notify(name+' prototype changed') + + return wrap_code(make_cpptoc_impl_proto(name, func, parts))+'{'+ \ + changes+impl['body']+'\n}\n' + return result + +def make_cpptoc_function_impl_new(name, func, defined_names): + # retrieve the C API prototype parts + parts = func.get_capi_parts(defined_names) + result = make_cpptoc_impl_proto(name, func, parts)+' {' + + invalid = [] + + # retrieve the function arguments + args = func.get_arguments() + + # determine the argument types + for arg in args: + if arg.get_arg_type() == 'invalid': + invalid.append(arg.get_name()) + + # retrieve the function return value + retval = func.get_retval() + retval_type = retval.get_retval_type() + if retval_type == 'invalid': + invalid.append('(return value)') + retval_default = '' + else: + retval_default = retval.get_retval_default(True) + if len(retval_default) > 0: + retval_default = ' '+retval_default; + + if len(invalid) > 0: + notify(name+' could not be autogenerated') + # code could not be auto-generated + result += '\n // BEGIN DELETE BEFORE MODIFYING' + result += '\n // AUTO-GENERATED CONTENT' + result += '\n // COULD NOT IMPLEMENT DUE TO: '+string.join(invalid, ', ') + result += '\n #pragma message("Warning: "__FILE__": '+name+' is not implemented")' + result += '\n // END DELETE BEFORE MODIFYING' + result += '\n}\n\n' + return wrap_code(result) + + result += '\n // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING\n' + + result_len = len(result) + + optional = [] + + # parameter verification + if isinstance(func, obj_function_virtual): + result += '\n DCHECK(self);'\ + '\n if (!self)'\ + '\n return'+retval_default+';' + + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + # skip optional params + optional_params = arg.parent.get_attrib_list('optional_param') + if not optional_params is None and arg_name in optional_params: + optional.append(arg_name) + continue + + comment = '\n // Verify param: '+arg_name+'; type: '+arg_type + + if arg_type == 'simple_byref' or arg_type == 'simple_byref_const' or \ + arg_type == 'simple_byaddr' or arg_type == 'bool_byref' or arg_type == 'bool_byaddr' or \ + arg_type == 'struct_byref_const' or arg_type == 'struct_byref' or \ + arg_type == 'string_byref_const' or arg_type == 'string_byref' or \ + arg_type == 'refptr_same' or arg_type == 'refptr_same_byref' or \ + arg_type == 'refptr_diff' or arg_type == 'refptr_diff_byref' or \ + arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const' or \ + arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const' or \ + arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const': + result += comment+\ + '\n DCHECK('+arg_name+');'\ + '\n if (!'+arg_name+')'\ + '\n return'+retval_default+';' + elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ + arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': + result += comment+\ + '\n DCHECK('+arg_name+'Count && (*'+arg_name+'Count == 0 || '+arg_name+'));'\ + '\n if (!'+arg_name+'Count || (*'+arg_name+'Count > 0 && !'+arg_name+'))'\ + '\n return'+retval_default+';' + elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ + arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const': + result += comment+\ + '\n DCHECK('+arg_name+'Count == 0 || '+arg_name+');'\ + '\n if ('+arg_name+'Count > 0 && !'+arg_name+')'\ + '\n return'+retval_default+';' + + # check index params + index_params = arg.parent.get_attrib_list('index_param') + if not index_params is None and arg_name in index_params: + result += comment+\ + '\n DCHECK_GE('+arg_name+', 0);'\ + '\n if ('+arg_name+' < 0)'\ + '\n return'+retval_default+';' + + if len(optional) > 0: + # Wrap the comment at 80 characters. + str = '\n // Unverified params: ' + optional[0] + for name in optional[1:]: + str += ',' + if len(str) + len(name) + 1 > 80: + result += str + str = '\n //' + str += ' ' + name + result += str + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # parameter translation + params = [] + + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + comment = '\n // Translate param: '+arg_name+'; type: '+arg_type + + if arg_type == 'simple_byval' or arg_type == 'simple_byaddr': + params.append(arg_name) + elif arg_type == 'simple_byref' or arg_type == 'simple_byref_const': + data_type = arg.get_type().get_type() + default = arg.get_type().get_result_simple_default() + result += comment+\ + '\n '+data_type+' '+arg_name+'Val = '+arg_name+'?*'+arg_name+':'+default+';' + params.append(arg_name+'Val') + elif arg_type == 'bool_byval': + params.append(arg_name+'?true:false') + elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr': + result += comment+\ + '\n bool '+arg_name+'Bool = ('+arg_name+' && *'+arg_name+')?true:false;' + if arg_type == 'bool_byref': + params.append(arg_name+'Bool') + else: + params.append('&'+arg_name+'Bool') + elif arg_type == 'struct_byref_const': + struct_type = arg.get_type().get_type() + result += comment+\ + '\n '+struct_type+' '+arg_name+'Obj;'\ + '\n if ('+arg_name+')'\ + '\n '+arg_name+'Obj.Set(*'+arg_name+', false);' + params.append(arg_name+'Obj') + elif arg_type == 'struct_byref': + struct_type = arg.get_type().get_type() + result += comment+\ + '\n '+struct_type+' '+arg_name+'Obj;'\ + '\n if ('+arg_name+')'\ + '\n '+arg_name+'Obj.AttachTo(*'+arg_name+');' + params.append(arg_name+'Obj') + elif arg_type == 'string_byref_const': + params.append('CefString('+arg_name+')') + elif arg_type == 'string_byref': + result += comment+\ + '\n CefString '+arg_name+'Str('+arg_name+');' + params.append(arg_name+'Str') + elif arg_type == 'refptr_same' or arg_type == 'refptr_diff': + refptr_class = arg.get_type().get_refptr_type() + if arg_type == 'refptr_same': + params.append(refptr_class+'CppToC::Unwrap('+arg_name+')') + else: + params.append(refptr_class+'CToCpp::Wrap('+arg_name+')') + elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + if arg_type == 'refptr_same_byref': + assign = refptr_class+'CppToC::Unwrap(*'+arg_name+')' + else: + assign = refptr_class+'CToCpp::Wrap(*'+arg_name+')' + result += comment+\ + '\n CefRefPtr<'+refptr_class+'> '+arg_name+'Ptr;'\ + '\n if ('+arg_name+' && *'+arg_name+')'\ + '\n '+arg_name+'Ptr = '+assign+';'\ + '\n '+refptr_class+'* '+arg_name+'Orig = '+arg_name+'Ptr.get();' + params.append(arg_name+'Ptr') + elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const': + result += comment+\ + '\n std::vector '+arg_name+'List;'\ + '\n transfer_string_list_contents('+arg_name+', '+arg_name+'List);' + params.append(arg_name+'List') + elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const': + result += comment+\ + '\n std::map '+arg_name+'Map;'\ + '\n transfer_string_map_contents('+arg_name+', '+arg_name+'Map);' + params.append(arg_name+'Map') + elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const': + result += comment+\ + '\n std::multimap '+arg_name+'Multimap;'\ + '\n transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);' + params.append(arg_name+'Multimap') + elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ + arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': + vec_type = arg.get_type().get_vector_type() + if arg_type == 'simple_vec_byref': + assign = arg_name+'[i]' + elif arg_type == 'bool_vec_byref': + assign = arg_name+'[i]?true:false' + elif arg_type == 'refptr_vec_same_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Unwrap('+arg_name+'[i])' + elif arg_type == 'refptr_vec_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Wrap('+arg_name+'[i])' + result += comment+\ + '\n std::vector<'+vec_type+' > '+arg_name+'List;'\ + '\n if ('+arg_name+'Count && *'+arg_name+'Count > 0 && '+arg_name+') {'\ + '\n for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\ + '\n '+arg_name+'List.push_back('+assign+');'\ + '\n }'\ + '\n }' + params.append(arg_name+'List') + elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ + arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const': + vec_type = arg.get_type().get_vector_type() + if arg_type == 'simple_vec_byref_const': + assign = arg_name+'[i]' + elif arg_type == 'bool_vec_byref_const': + assign = arg_name+'[i]?true:false' + elif arg_type == 'refptr_vec_same_byref_const': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Unwrap('+arg_name+'[i])' + elif arg_type == 'refptr_vec_diff_byref_const': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Wrap('+arg_name+'[i])' + result += comment+\ + '\n std::vector<'+vec_type+' > '+arg_name+'List;'\ + '\n if ('+arg_name+'Count > 0) {'\ + '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ + '\n '+arg_name+'List.push_back('+assign+');'\ + '\n }'\ + '\n }' + params.append(arg_name+'List') + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # execution + result += '\n // Execute\n ' + + if retval_type != 'none': + # has a return value + if retval_type == 'simple': + result += retval.get_type().get_result_simple_type() + else: + result += retval.get_type().get_type() + result += ' _retval = ' + + if isinstance(func.parent, obj_class): + # virtual and static class methods + if isinstance(func, obj_function_virtual): + result += func.parent.get_name()+'CppToC::Get(self)->' + else: + result += func.parent.get_name()+'::' + result += func.get_name()+'(' + + if len(params) > 0: + result += '\n '+string.join(params,',\n ') + + result += ');\n' + + result_len = len(result) + + # parameter restoration + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + comment = '\n // Restore param: '+arg_name+'; type: '+arg_type + + if arg_type == 'simple_byref': + result += comment+\ + '\n if ('+arg_name+')'\ + '\n *'+arg_name+' = '+arg_name+'Val;' + elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr': + result += comment+\ + '\n if ('+arg_name+')'\ + '\n *'+arg_name+' = '+arg_name+'Bool?true:false;' + elif arg_type == 'struct_byref': + result += comment+\ + '\n if ('+arg_name+')'\ + '\n '+arg_name+'Obj.DetachTo(*'+arg_name+');' + elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + if arg_type == 'refptr_same_byref': + assign = refptr_class+'CppToC::Wrap('+arg_name+'Ptr)' + else: + assign = refptr_class+'CToCpp::Unwrap('+arg_name+'Ptr)' + result += comment+\ + '\n if ('+arg_name+') {'\ + '\n if ('+arg_name+'Ptr.get()) {'\ + '\n if ('+arg_name+'Ptr.get() != '+arg_name+'Orig) {'\ + '\n *'+arg_name+' = '+assign+';'\ + '\n }'\ + '\n } else {'\ + '\n *'+arg_name+' = NULL;'\ + '\n }'\ + '\n }' + elif arg_type == 'string_vec_byref': + result += comment+\ + '\n cef_string_list_clear('+arg_name+');'\ + '\n transfer_string_list_contents('+arg_name+'List, '+arg_name+');' + elif arg_type == 'string_map_single_byref': + result += comment+\ + '\n cef_string_map_clear('+arg_name+');'\ + '\n transfer_string_map_contents('+arg_name+'Map, '+arg_name+');' + elif arg_type == 'string_map_multi_byref': + result += comment+\ + '\n cef_string_multimap_clear('+arg_name+');'\ + '\n transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');' + elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ + arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': + if arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref': + assign = arg_name+'List[i]' + elif arg_type == 'refptr_vec_same_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Wrap('+arg_name+'List[i])' + elif arg_type == 'refptr_vec_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Unwrap('+arg_name+'List[i])' + result += comment+\ + '\n if ('+arg_name+'Count && '+arg_name+') {'\ + '\n *'+arg_name+'Count = std::min('+arg_name+'List.size(), *'+arg_name+'Count);'\ + '\n if (*'+arg_name+'Count > 0) {'\ + '\n for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\ + '\n '+arg_name+'[i] = '+assign+';'\ + '\n }'\ + '\n }'\ + '\n }' + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # special handling for the global cef_shutdown function + if name == 'cef_shutdown' and isinstance(func.parent, obj_header): + classes = func.parent.get_classes() + + names = [] + for cls in classes: + if cls.has_attrib('no_debugct_check'): + continue; + + if cls.is_library_side(): + names.append(cls.get_name()+'CppToC') + else: + names.append(cls.get_name()+'CToCpp') + + if len(names) > 0: + names = sorted(names) + result += '\n#ifndef NDEBUG'\ + '\n // Check that all wrapper objects have been destroyed' + for name in names: + result += '\n DCHECK(base::AtomicRefCountIsZero(&'+name+'::DebugObjCt));'; + result += '\n#endif // !NDEBUG' + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # return translation + if retval_type != 'none': + # has a return value + result += '\n // Return type: '+retval_type + if retval_type == 'simple' or retval_type == 'bool': + result += '\n return _retval;' + elif retval_type == 'string': + result += '\n return _retval.DetachToUserFree();' + elif retval_type == 'refptr_same': + refptr_class = retval.get_type().get_refptr_type() + result += '\n return '+refptr_class+'CppToC::Wrap(_retval);' + elif retval_type == 'refptr_diff': + refptr_class = retval.get_type().get_refptr_type() + result += '\n return '+refptr_class+'CToCpp::Unwrap(_retval);' + + if len(result) != result_len: + result += '\n' + + result += '}\n' + return wrap_code(result) + +def make_cpptoc_function_impl(funcs, existing, prefixname, defined_names): + impl = '' + + for func in funcs: + if not prefixname is None: + name = prefixname+'_'+func.get_capi_name() + else: + name = func.get_capi_name() + value = get_next_function_impl(existing, name) + if not value is None \ + and value['body'].find('// AUTO-GENERATED CONTENT') < 0: + # an implementation exists that was not auto-generated + impl += make_cpptoc_function_impl_existing(name, func, value, defined_names) + else: + impl += make_cpptoc_function_impl_new(name, func, defined_names) + + return impl + +def make_cpptoc_class_impl(header, clsname, impl): + # structure names that have already been defined + defined_names = header.get_defined_structs() + + # retrieve the class and populate the defined names + cls = header.get_class(clsname, defined_names) + if cls is None: + raise Exception('Class does not exist: '+clsname) + + capiname = cls.get_capi_name() + prefixname = get_capi_name(clsname[3:], False) + + # retrieve the existing virtual function implementations + existing = get_function_impls(impl, 'CEF_CALLBACK') + + # generate virtual functions + virtualimpl = make_cpptoc_function_impl(cls.get_virtual_funcs(), existing, prefixname, defined_names) + if len(virtualimpl) > 0: + virtualimpl = '\n// MEMBER FUNCTIONS - Body may be edited by hand.\n\n'+virtualimpl + + # the current class is already defined for static functions + defined_names.append(cls.get_capi_name()) + + # retrieve the existing static function implementations + existing = get_function_impls(impl, 'CEF_EXPORT') + + # generate static functions + staticimpl = make_cpptoc_function_impl(cls.get_static_funcs(), existing, None, defined_names) + if len(staticimpl) > 0: + staticimpl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n'+staticimpl + + resultingimpl = staticimpl + virtualimpl + + # determine what includes are required by identifying what translation + # classes are being used + includes = format_translation_includes(resultingimpl) + + # build the final output + result = get_copyright() + + result += includes+'\n'+resultingimpl+'\n' + + const = '// CONSTRUCTOR - Do not edit by hand.\n\n'+ \ + clsname+'CppToC::'+clsname+'CppToC('+clsname+'* cls)\n'+ \ + ' : CefCppToC<'+clsname+'CppToC, '+clsname+', '+capiname+'>(cls) '+ \ + '{\n'; + + funcs = cls.get_virtual_funcs() + for func in funcs: + name = func.get_capi_name() + const += ' struct_.struct_.'+name+' = '+prefixname+'_'+name+';\n' + + const += '}\n\n'+ \ + '#ifndef NDEBUG\n'+ \ + 'template<> base::AtomicRefCount CefCppToC<'+clsname+'CppToC, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ + '#endif\n' + result += wrap_code(const) + + return result + +def make_cpptoc_global_impl(header, impl): + # structure names that have already been defined + defined_names = header.get_defined_structs() + + # retrieve the existing global function implementations + existing = get_function_impls(impl, 'CEF_EXPORT') + + # generate global functions + impl = make_cpptoc_function_impl(header.get_funcs(), existing, None, defined_names) + if len(impl) > 0: + impl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n'+impl + + includes = '' + + # include required headers for global functions + filenames = [] + for func in header.get_funcs(): + filename = func.get_file_name() + if not filename in filenames: + includes += '#include "include/'+func.get_file_name()+'"\n' \ + '#include "include/capi/'+func.get_capi_file_name()+'"\n' + filenames.append(filename) + + # determine what includes are required by identifying what translation + # classes are being used + includes += format_translation_includes(impl) + + # build the final output + result = get_copyright() + + result += includes+'\n'+impl + + return result + +def write_cpptoc_impl(header, clsname, dir, backup): + if clsname is None: + # global file + file = dir + else: + # class file + file = dir+os.sep+get_capi_name(clsname[3:], False)+'_cpptoc.cc' + + if path_exists(file): + oldcontents = read_file(file) + else: + oldcontents = '' + + if clsname is None: + newcontents = make_cpptoc_global_impl(header, oldcontents) + else: + newcontents = make_cpptoc_class_impl(header, clsname, oldcontents) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(file) + write_file(file, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 4: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # read the existing implementation file into memory + try: + f = open(sys.argv[3], 'r') + data = f.read() + except IOError, (errno, strerror): + raise Exception('Failed to read file '+sys.argv[3]+': '+strerror) + else: + f.close() + + # dump the result to stdout + sys.stdout.write(make_cpptoc_class_impl(header, sys.argv[2], data)) diff --git a/tools/make_ctocpp_header.py b/tools/make_ctocpp_header.py new file mode 100644 index 000000000..027ac8a14 --- /dev/null +++ b/tools/make_ctocpp_header.py @@ -0,0 +1,122 @@ +# 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. + +from cef_parser import * + +def make_ctocpp_header(header, clsname): + cls = header.get_class(clsname) + if cls is None: + raise Exception('Class does not exist: '+clsname) + + clientside = cls.is_client_side() + defname = string.upper(get_capi_name(clsname[3:], False)) + capiname = cls.get_capi_name() + + result = get_copyright() + + result += '#ifndef CEF_LIBCEF_DLL_CTOCPP_'+defname+'_CTOCPP_H_\n'+ \ + '#define CEF_LIBCEF_DLL_CTOCPP_'+defname+'_CTOCPP_H_\n' + \ + '#pragma once\n' + + if clientside: + result += """ +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED +""" + else: + result += """ +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED +""" + + # build the function body + func_body = '' + funcs = cls.get_virtual_funcs() + for func in funcs: + func_body += ' virtual '+func.get_cpp_proto()+' OVERRIDE;\n' + + # include standard headers + if func_body.find('std::map') > 0 or func_body.find('std::multimap') > 0: + result += '\n#include ' + if func_body.find('std::vector') > 0: + result += '\n#include ' + + # include the headers for this class + result += '\n#include "include/'+cls.get_file_name()+'"'+ \ + '\n#include "include/capi/'+cls.get_capi_file_name()+'"\n' + + # include headers for any forward declared classes that are not in the same file + declares = cls.get_forward_declares() + for declare in declares: + dcls = header.get_class(declare) + if dcls.get_file_name() != cls.get_file_name(): + result += '#include "include/'+dcls.get_file_name()+'"\n' \ + '#include "include/capi/'+dcls.get_capi_file_name()+'"\n' + + result += """#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +""" + + if clientside: + result += '// This class may be instantiated and accessed DLL-side only.\n' + else: + result += '// This class may be instantiated and accessed wrapper-side only.\n' + + result += 'class '+clsname+'CToCpp\n'+ \ + ' : public CefCToCpp<'+clsname+'CToCpp, '+clsname+', '+capiname+'> {\n'+ \ + ' public:\n'+ \ + ' explicit '+clsname+'CToCpp('+capiname+'* str)\n'+ \ + ' : CefCToCpp<'+clsname+'CToCpp, '+clsname+', '+capiname+'>(str) {}\n'+ \ + ' virtual ~'+clsname+'CToCpp() {}\n\n'+ \ + ' // '+clsname+' methods\n'; + + result += func_body + result += '};\n\n' + + if clientside: + result += '#endif // BUILDING_CEF_SHARED\n' + else: + result += '#endif // USING_CEF_SHARED\n' + + result += '#endif // CEF_LIBCEF_DLL_CTOCPP_'+defname+'_CTOCPP_H_\n' + + return wrap_code(result) + + +def write_ctocpp_header(header, clsname, dir, backup): + file = dir+os.sep+get_capi_name(clsname[3:], False)+'_ctocpp.h' + + if path_exists(file): + oldcontents = read_file(file) + else: + oldcontents = '' + + newcontents = make_ctocpp_header(header, clsname) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(file) + write_file(file, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 3: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # dump the result to stdout + sys.stdout.write(make_ctocpp_header(header, sys.argv[2])) diff --git a/tools/make_ctocpp_impl.py b/tools/make_ctocpp_impl.py new file mode 100644 index 000000000..1d109fb7c --- /dev/null +++ b/tools/make_ctocpp_impl.py @@ -0,0 +1,584 @@ +# 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. + +from cef_parser import * + +def make_ctocpp_impl_proto(clsname, name, func, parts): + const = '' + + if clsname is None: + proto = 'CEF_GLOBAL '+parts['retval']+' ' + else: + proto = parts['retval']+' '+clsname + if isinstance(func, obj_function_virtual): + proto += 'CToCpp' + if func.is_const(): + const = ' const' + + proto += '::' + + proto += name+'('+string.join(parts['args'], ', ')+')'+const + return proto + +def make_ctocpp_function_impl_existing(clsname, name, func, impl): + notify(name+' has manual edits') + + # retrieve the C++ prototype parts + parts = func.get_cpp_parts(True) + + changes = format_translation_changes(impl, parts) + if len(changes) > 0: + notify(name+' prototype changed') + + return wrap_code(make_ctocpp_impl_proto(clsname, name, func, parts))+'{'+ \ + changes+impl['body']+'\n}\n' + +def make_ctocpp_function_impl_new(clsname, name, func): + # build the C++ prototype + parts = func.get_cpp_parts(True) + result = make_ctocpp_impl_proto(clsname, name, func, parts)+' {' + + invalid = [] + + # retrieve the function arguments + args = func.get_arguments() + + # determine the argument types + for arg in args: + if arg.get_arg_type() == 'invalid': + invalid.append(arg.get_name()) + + # retrieve the function return value + retval = func.get_retval() + retval_type = retval.get_retval_type() + if retval_type == 'invalid': + invalid.append('(return value)') + retval_default = '' + else: + retval_default = retval.get_retval_default(False) + if len(retval_default) > 0: + retval_default = ' '+retval_default; + + # add API hash check + if func.has_attrib('api_hash_check'): + result += '\n const char* api_hash = cef_api_hash(0);'\ + '\n if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {'\ + '\n // The libcef API hash does not match the current header API hash.'\ + '\n NOTREACHED();'\ + '\n return'+retval_default+';'\ + '\n }\n' + + if isinstance(func, obj_function_virtual): + # add the structure size check + result += '\n if (CEF_MEMBER_MISSING(struct_, '+func.get_capi_name()+'))' + result += '\n return'+retval_default+';\n' + + if len(invalid) > 0: + notify(name+' could not be autogenerated') + # code could not be auto-generated + result += '\n // BEGIN DELETE BEFORE MODIFYING' + result += '\n // AUTO-GENERATED CONTENT' + result += '\n // COULD NOT IMPLEMENT DUE TO: '+string.join(invalid, ', ') + result += '\n #pragma message("Warning: "__FILE__": '+name+' is not implemented")' + result += '\n // END DELETE BEFORE MODIFYING' + result += '\n}\n\n' + return wrap_code(result) + + result += '\n // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING\n' + + result_len = len(result) + + optional = [] + + # parameter verification + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + # skip optional params + optional_params = arg.parent.get_attrib_list('optional_param') + if not optional_params is None and arg_name in optional_params: + optional.append(arg_name) + continue + + comment = '\n // Verify param: '+arg_name+'; type: '+arg_type + + if arg_type == 'simple_byaddr' or arg_type == 'bool_byaddr': + result += comment+\ + '\n DCHECK('+arg_name+');'\ + '\n if (!'+arg_name+')'\ + '\n return'+retval_default+';' + elif arg_type == 'refptr_same' or arg_type == 'refptr_diff': + result += comment+\ + '\n DCHECK('+arg_name+'.get());'\ + '\n if (!'+arg_name+'.get())'\ + '\n return'+retval_default+';' + elif arg_type == 'string_byref_const': + result += comment+\ + '\n DCHECK(!'+arg_name+'.empty());'\ + '\n if ('+arg_name+'.empty())'\ + '\n return'+retval_default+';' + + # check index params + index_params = arg.parent.get_attrib_list('index_param') + if not index_params is None and arg_name in index_params: + result += comment+\ + '\n DCHECK_GE('+arg_name+', 0);'\ + '\n if ('+arg_name+' < 0)'\ + '\n return'+retval_default+';' + + if len(optional) > 0: + # Wrap the comment at 80 characters. + str = '\n // Unverified params: ' + optional[0] + for name in optional[1:]: + str += ',' + if len(str) + len(name) + 1 > 80: + result += str + str = '\n //' + str += ' ' + name + result += str + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # parameter translation + params = [] + if isinstance(func, obj_function_virtual): + params.append('struct_') + + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + comment = '\n // Translate param: '+arg_name+'; type: '+arg_type + + if arg_type == 'simple_byval' or arg_type == 'simple_byaddr' or \ + arg_type == 'bool_byval': + params.append(arg_name) + elif arg_type == 'simple_byref' or arg_type == 'simple_byref_const' or \ + arg_type == 'struct_byref_const' or arg_type == 'struct_byref': + params.append('&'+arg_name) + elif arg_type == 'bool_byref': + result += comment+\ + '\n int '+arg_name+'Int = '+arg_name+';' + params.append('&'+arg_name+'Int') + elif arg_type == 'bool_byaddr': + result += comment+\ + '\n int '+arg_name+'Int = '+arg_name+'?*'+arg_name+':0;' + params.append('&'+arg_name+'Int') + elif arg_type == 'string_byref_const': + params.append(arg_name+'.GetStruct()') + elif arg_type == 'string_byref': + params.append(arg_name+'.GetWritableStruct()') + elif arg_type == 'refptr_same': + refptr_class = arg.get_type().get_refptr_type() + params.append(refptr_class+'CToCpp::Unwrap('+arg_name+')') + elif arg_type == 'refptr_diff': + refptr_class = arg.get_type().get_refptr_type() + params.append(refptr_class+'CppToC::Wrap('+arg_name+')') + elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + refptr_struct = arg.get_type().get_result_refptr_type_root() + if arg_type == 'refptr_same_byref': + assign = refptr_class+'CToCpp::Unwrap('+arg_name+')' + else: + assign = refptr_class+'CppToC::Wrap('+arg_name+')' + result += comment+\ + '\n '+refptr_struct+'* '+arg_name+'Struct = NULL;'\ + '\n if ('+arg_name+'.get())'\ + '\n '+arg_name+'Struct = '+assign+';'\ + '\n '+refptr_struct+'* '+arg_name+'Orig = '+arg_name+'Struct;' + params.append('&'+arg_name+'Struct') + elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const': + result += comment+\ + '\n cef_string_list_t '+arg_name+'List = cef_string_list_alloc();'\ + '\n DCHECK('+arg_name+'List);'\ + '\n if ('+arg_name+'List)'\ + '\n transfer_string_list_contents('+arg_name+', '+arg_name+'List);' + params.append(arg_name+'List') + elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const': + result += comment+\ + '\n cef_string_map_t '+arg_name+'Map = cef_string_map_alloc();'\ + '\n DCHECK('+arg_name+'Map);'\ + '\n if ('+arg_name+'Map)'\ + '\n transfer_string_map_contents('+arg_name+', '+arg_name+'Map);' + params.append(arg_name+'Map') + elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const': + result += comment+\ + '\n cef_string_multimap_t '+arg_name+'Multimap = cef_string_multimap_alloc();'\ + '\n DCHECK('+arg_name+'Multimap);'\ + '\n if ('+arg_name+'Multimap)'\ + '\n transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);' + params.append(arg_name+'Multimap') + elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ + arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': + count_func = arg.get_attrib_count_func() + vec_type = arg.get_type().get_result_vector_type_root() + if arg_type == 'refptr_vec_same_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Unwrap('+arg_name+'[i])' + elif arg_type == 'refptr_vec_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Wrap('+arg_name+'[i])' + else: + assign = arg_name+'[i]' + result += comment+\ + '\n size_t '+arg_name+'Size = '+arg_name+'.size();'\ + '\n size_t '+arg_name+'Count = std::max('+count_func+'(), '+arg_name+'Size);'\ + '\n '+vec_type+'* '+arg_name+'List = NULL;'\ + '\n if ('+arg_name+'Count > 0) {'\ + '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ + '\n DCHECK('+arg_name+'List);'\ + '\n if ('+arg_name+'List) {'\ + '\n memset('+arg_name+'List, 0, sizeof('+vec_type+')*'+arg_name+'Count);'\ + '\n }'\ + '\n if ('+arg_name+'List && '+arg_name+'Size > 0) {'\ + '\n for (size_t i = 0; i < '+arg_name+'Size; ++i) {'\ + '\n '+arg_name+'List[i] = '+assign+';'\ + '\n }'\ + '\n }'\ + '\n }' + params.append('&'+arg_name+'Count') + params.append(arg_name+'List') + elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ + arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const': + count_func = arg.get_attrib_count_func() + vec_type = arg.get_type().get_result_vector_type_root() + if arg_type == 'refptr_vec_same_byref_const': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Unwrap('+arg_name+'[i])' + elif arg_type == 'refptr_vec_diff_byref_const': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Wrap('+arg_name+'[i])' + else: + assign = arg_name+'[i]' + result += comment+\ + '\n const size_t '+arg_name+'Count = '+arg_name+'.size();'\ + '\n '+vec_type+'* '+arg_name+'List = NULL;'\ + '\n if ('+arg_name+'Count > 0) {'\ + '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ + '\n DCHECK('+arg_name+'List);'\ + '\n if ('+arg_name+'List) {'\ + '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ + '\n '+arg_name+'List[i] = '+assign+';'\ + '\n }'\ + '\n }'\ + '\n }' + params.append(arg_name+'Count') + params.append(arg_name+'List') + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # execution + result += '\n // Execute\n ' + + if retval_type != 'none': + # has a return value + if retval_type == 'simple' or retval_type == 'bool': + result += retval.get_type().get_result_simple_type_root() + elif retval_type == 'string': + result += 'cef_string_userfree_t' + elif retval_type == 'refptr_same' or retval_type == 'refptr_diff': + refptr_struct = retval.get_type().get_result_refptr_type_root() + result += refptr_struct+'*' + + result += ' _retval = ' + + if isinstance(func, obj_function_virtual): + result += 'struct_->' + result += func.get_capi_name()+'(' + + if len(params) > 0: + if not isinstance(func, obj_function_virtual): + result += '\n ' + result += string.join(params,',\n ') + + result += ');\n' + + result_len = len(result) + + # parameter restoration + for arg in args: + arg_type = arg.get_arg_type() + arg_name = arg.get_type().get_name() + + comment = '\n // Restore param:'+arg_name+'; type: '+arg_type + + if arg_type == 'bool_byref': + result += comment+\ + '\n '+arg_name+' = '+arg_name+'Int?true:false;' + elif arg_type == 'bool_byaddr': + result += comment+\ + '\n if ('+arg_name+')'\ + '\n *'+arg_name+' = '+arg_name+'Int?true:false;' + elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + refptr_struct = arg.get_type().get_result_refptr_type_root() + if arg_type == 'refptr_same_byref': + assign = refptr_class+'CToCpp::Wrap('+arg_name+'Struct)' + else: + assign = refptr_class+'CppToC::Unwrap('+arg_name+'Struct)' + result += comment+\ + '\n if ('+arg_name+'Struct) {'\ + '\n if ('+arg_name+'Struct != '+arg_name+'Orig) {'\ + '\n '+arg_name+' = '+assign+';'\ + '\n }'\ + '\n } else {'\ + '\n '+arg_name+' = NULL;'\ + '\n }' + elif arg_type == 'string_vec_byref': + result += comment+\ + '\n if ('+arg_name+'List) {'\ + '\n '+arg_name+'.clear();'\ + '\n transfer_string_list_contents('+arg_name+'List, '+arg_name+');'\ + '\n cef_string_list_free('+arg_name+'List);'\ + '\n }' + elif arg_type == 'string_vec_byref_const': + result += comment+\ + '\n if ('+arg_name+'List)'\ + '\n cef_string_list_free('+arg_name+'List);' + elif arg_type == 'string_map_single_byref': + result += comment+\ + '\n if ('+arg_name+'Map) {'\ + '\n '+arg_name+'.clear();'\ + '\n transfer_string_map_contents('+arg_name+'Map, '+arg_name+');'\ + '\n cef_string_map_free('+arg_name+'Map);'\ + '\n }' + elif arg_type == 'string_map_single_byref_const': + result += comment+\ + '\n if ('+arg_name+'Map)'\ + '\n cef_string_map_free('+arg_name+'Map);' + elif arg_type == 'string_map_multi_byref': + result += comment+\ + '\n if ('+arg_name+'Multimap) {'\ + '\n '+arg_name+'.clear();'\ + '\n transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');'\ + '\n cef_string_multimap_free('+arg_name+'Multimap);'\ + '\n }' + elif arg_type == 'string_map_multi_byref_const': + result += comment+\ + '\n if ('+arg_name+'Multimap)'\ + '\n cef_string_multimap_free('+arg_name+'Multimap);' + elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \ + arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref': + count_func = arg.get_attrib_count_func() + vec_type = arg.get_type().get_result_vector_type_root() + if arg_type == 'refptr_vec_same_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CToCpp::Wrap('+arg_name+'List[i])' + elif arg_type == 'refptr_vec_diff_byref': + refptr_class = arg.get_type().get_refptr_type() + assign = refptr_class+'CppToC::Unwrap('+arg_name+'List[i])' + elif arg_type == 'bool_vec_byref': + assign = arg_name+'List[i]?true:false' + else: + assign = arg_name+'List[i]' + result += comment+\ + '\n '+arg_name+'.clear();'\ + '\n if ('+arg_name+'Count > 0 && '+arg_name+'List) {'\ + '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ + '\n '+arg_name+'.push_back('+assign+');'\ + '\n }'\ + '\n delete [] '+arg_name+'List;'\ + '\n }' + elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \ + arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const': + result += comment+\ + '\n if ('+arg_name+'List)'\ + '\n delete [] '+arg_name+'List;' + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # special handling for the global CefShutdown function + if name == 'CefShutdown' and isinstance(func.parent, obj_header): + classes = func.parent.get_classes() + + names = [] + for cls in classes: + if cls.has_attrib('no_debugct_check'): + continue; + + if cls.is_library_side(): + names.append(cls.get_name()+'CToCpp') + else: + names.append(cls.get_name()+'CppToC') + + if len(names) > 0: + names = sorted(names) + result += '\n#ifndef NDEBUG'\ + '\n // Check that all wrapper objects have been destroyed' + for name in names: + result += '\n DCHECK(base::AtomicRefCountIsZero(&'+name+'::DebugObjCt));'; + result += '\n#endif // !NDEBUG' + + if len(result) != result_len: + result += '\n' + result_len = len(result) + + # return translation + if retval_type != 'none': + # has a return value + result += '\n // Return type: '+retval_type + if retval_type == 'simple': + result += '\n return _retval;' + elif retval_type == 'bool': + result += '\n return _retval?true:false;' + elif retval_type == 'string': + result += '\n CefString _retvalStr;'\ + '\n _retvalStr.AttachToUserFree(_retval);'\ + '\n return _retvalStr;' + elif retval_type == 'refptr_same': + refptr_class = retval.get_type().get_refptr_type() + result += '\n return '+refptr_class+'CToCpp::Wrap(_retval);' + elif retval_type == 'refptr_diff': + refptr_class = retval.get_type().get_refptr_type() + result += '\n return '+refptr_class+'CppToC::Unwrap(_retval);' + + if len(result) != result_len: + result += '\n' + + result += '}\n' + return wrap_code(result) + +def make_ctocpp_function_impl(clsname, funcs, existing): + impl = '' + + for func in funcs: + name = func.get_name() + value = get_next_function_impl(existing, name) + if not value is None \ + and value['body'].find('// AUTO-GENERATED CONTENT') < 0: + # an implementation exists that was not auto-generated + impl += make_ctocpp_function_impl_existing(clsname, name, func, value) + else: + impl += make_ctocpp_function_impl_new(clsname, name, func) + + return impl + +def make_ctocpp_class_impl(header, clsname, impl): + cls = header.get_class(clsname) + if cls is None: + raise Exception('Class does not exist: '+clsname) + + capiname = cls.get_capi_name() + + # retrieve the existing virtual function implementations + existing = get_function_impls(impl, clsname+'CToCpp::') + + # generate virtual functions + virtualimpl = make_ctocpp_function_impl(clsname, cls.get_virtual_funcs(), existing) + if len(virtualimpl) > 0: + virtualimpl = '\n// VIRTUAL METHODS - Body may be edited by hand.\n\n'+virtualimpl + + # retrieve the existing static function implementations + existing = get_function_impls(impl, clsname+'::') + + # generate static functions + staticimpl = make_ctocpp_function_impl(clsname, cls.get_static_funcs(), existing) + if len(staticimpl) > 0: + staticimpl = '\n// STATIC METHODS - Body may be edited by hand.\n\n'+staticimpl + + resultingimpl = staticimpl + virtualimpl + + # determine what includes are required by identifying what translation + # classes are being used + includes = format_translation_includes(resultingimpl) + + # build the final output + result = get_copyright() + + result += includes+'\n'+resultingimpl+'\n' + + result += wrap_code('#ifndef NDEBUG\n'+ \ + 'template<> base::AtomicRefCount CefCToCpp<'+clsname+'CToCpp, '+clsname+', '+capiname+'>::DebugObjCt = 0;\n'+ \ + '#endif\n') + + return result + +def make_ctocpp_global_impl(header, impl): + # retrieve the existing global function implementations + existing = get_function_impls(impl, 'CEF_GLOBAL') + + # generate static functions + impl = make_ctocpp_function_impl(None, header.get_funcs(), existing) + if len(impl) > 0: + impl = '\n// GLOBAL METHODS - Body may be edited by hand.\n\n'+impl + + includes = '' + + # include required headers for global functions + filenames = [] + for func in header.get_funcs(): + filename = func.get_file_name() + if not filename in filenames: + includes += '#include "include/'+func.get_file_name()+'"\n' \ + '#include "include/capi/'+func.get_capi_file_name()+'"\n' + filenames.append(filename) + + # determine what includes are required by identifying what translation + # classes are being used + includes += format_translation_includes(impl) + + # build the final output + result = get_copyright() + + result += includes+'\n// Define used to facilitate parsing.\n#define CEF_GLOBAL\n\n'+impl + + return result + +def write_ctocpp_impl(header, clsname, dir, backup): + if clsname is None: + # global file + file = dir + else: + # class file + file = dir+os.sep+get_capi_name(clsname[3:], False)+'_ctocpp.cc' + + if path_exists(file): + oldcontents = read_file(file) + else: + oldcontents = '' + + if clsname is None: + newcontents = make_ctocpp_global_impl(header, oldcontents) + else: + newcontents = make_ctocpp_class_impl(header, clsname, oldcontents) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(file) + write_file(file, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 4: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # read the existing implementation file into memory + try: + f = open(sys.argv[3], 'r') + data = f.read() + except IOError, (errno, strerror): + raise Exception('Failed to read file '+sys.argv[3]+': '+strerror) + else: + f.close() + + # dump the result to stdout + sys.stdout.write(make_ctocpp_class_impl(header, sys.argv[2], data)) diff --git a/tools/make_distrib.bat b/tools/make_distrib.bat new file mode 100644 index 000000000..c92dc7a46 --- /dev/null +++ b/tools/make_distrib.bat @@ -0,0 +1,2 @@ +@echo off +python.bat make_distrib.py --output-dir ..\binary_distrib\ %* diff --git a/tools/make_distrib.py b/tools/make_distrib.py new file mode 100644 index 000000000..225812367 --- /dev/null +++ b/tools/make_distrib.py @@ -0,0 +1,813 @@ +# 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. + +from date_util import * +from file_util import * +from gclient_util import * +from optparse import OptionParser +import os +import re +import shlex +import subprocess +import svn_util as svn +import git_util as git +import sys +import zipfile + +def create_archive(input_dir, zip_file): + """ Creates a zip archive of the specified input directory. """ + zf = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) + def addDir(dir): + for f in os.listdir(dir): + full_path = os.path.join(dir, f) + if os.path.isdir(full_path): + addDir(full_path) + else: + zf.write(full_path, os.path.relpath(full_path, \ + os.path.join(input_dir, os.pardir))) + addDir(input_dir) + zf.close() + +def create_7z_archive(input_dir, zip_file): + """ Creates a 7z archive of the specified input directory. """ + command = os.environ['CEF_COMMAND_7ZIP'] + run('"' + command + '" a -y ' + zip_file + ' ' + input_dir, os.path.split(zip_file)[0]) + +def create_output_dir(name, parent_dir): + """ Creates an output directory and adds the path to the archive list. """ + output_dir = os.path.abspath(os.path.join(parent_dir, name)) + remove_dir(output_dir, options.quiet) + make_dir(output_dir, options.quiet) + archive_dirs.append(output_dir) + return output_dir + +def get_readme_component(name): + """ Loads a README file component. """ + paths = [] + # platform directory + if platform == 'windows': + platform_cmp = 'win' + elif platform == 'macosx': + platform_cmp = 'mac' + elif platform == 'linux': + platform_cmp = 'linux' + paths.append(os.path.join(script_dir, 'distrib', platform_cmp)) + + # shared directory + paths.append(os.path.join(script_dir, 'distrib')) + + # load the file if it exists + for path in paths: + file = os.path.join(path, 'README.' +name + '.txt') + if path_exists(file): + return read_file(file) + + raise Exception('Readme component not found: ' + name) + +def create_readme(): + """ Creates the README.TXT file. """ + # gather the components + header_data = get_readme_component('header') + mode_data = get_readme_component(mode) + redistrib_data = get_readme_component('redistrib') + footer_data = get_readme_component('footer') + + # format the file + data = header_data + '\n\n' + mode_data + '\n\n' + redistrib_data + '\n\n' + footer_data + data = data.replace('$CEF_URL$', cef_url) + data = data.replace('$CEF_REV$', cef_rev) + data = data.replace('$CEF_VER$', cef_ver) + data = data.replace('$CHROMIUM_URL$', chromium_url) + data = data.replace('$CHROMIUM_REV$', chromium_rev) + data = data.replace('$CHROMIUM_VER$', chromium_ver) + data = data.replace('$DATE$', date) + + if platform == 'windows': + platform_str = 'Windows' + elif platform == 'macosx': + platform_str = 'Mac OS-X' + elif platform == 'linux': + platform_str = 'Linux' + + data = data.replace('$PLATFORM$', platform_str) + + if mode == 'standard': + distrib_type = 'Standard' + distrib_desc = 'This distribution contains all components necessary to build and distribute an\n' \ + 'application using CEF on the ' + platform_str + ' platform. Please see the LICENSING\n' \ + 'section of this document for licensing terms and conditions.' + elif mode == 'minimal': + distrib_type = 'Minimal' + distrib_desc = 'This distribution contains only the components required to distribute an\n' \ + 'application using CEF on the ' + platform_str + ' platform. Please see the LICENSING\n' \ + 'section of this document for licensing terms and conditions.' + elif mode == 'client': + distrib_type = 'Client' + distrib_desc = 'This distribution contains a release build of the cefclient sample application\n' \ + 'for the ' + platform_str + ' platform. Please see the LICENSING section of this document for\n' \ + 'licensing terms and conditions.' + + data = data.replace('$DISTRIB_TYPE$', distrib_type) + data = data.replace('$DISTRIB_DESC$', distrib_desc) + + write_file(os.path.join(output_dir, 'README.txt'), data) + if not options.quiet: + sys.stdout.write('Creating README.TXT file.\n') + +def eval_file(src): + """ Loads and evaluates the contents of the specified file. """ + return eval(read_file(src), {'__builtins__': None}, None) + +def transfer_gypi_files(src_dir, gypi_paths, gypi_path_prefix, dst_dir, quiet): + """ Transfer files from one location to another. """ + for path in gypi_paths: + # skip gyp includes + if path[:2] == '<@': + continue + src = os.path.join(src_dir, path) + dst = os.path.join(dst_dir, path.replace(gypi_path_prefix, '')) + dst_path = os.path.dirname(dst) + make_dir(dst_path, quiet) + copy_file(src, dst, quiet) + +def normalize_headers(file, new_path = ''): + """ Normalize headers post-processing. Remove the path component from any + project include directives. """ + data = read_file(file) + data = re.sub(r'''#include \"(?!include\/)[a-zA-Z0-9_\/]+\/+([a-zA-Z0-9_\.]+)\"''', \ + "// Include path modified for CEF Binary Distribution.\n#include \""+new_path+"\\1\"", data) + write_file(file, data) + +def transfer_files(cef_dir, script_dir, transfer_cfg, output_dir, quiet): + """ Transfer files based on the specified configuration. """ + if not path_exists(transfer_cfg): + return + + configs = eval_file(transfer_cfg) + for cfg in configs: + dst = os.path.join(output_dir, cfg['target']) + + # perform a copy if source is specified + if not cfg['source'] is None: + src = os.path.join(cef_dir, cfg['source']) + dst_path = os.path.dirname(dst) + make_dir(dst_path, quiet) + copy_file(src, dst, quiet) + + # place a readme file in the destination directory + readme = os.path.join(dst_path, 'README-TRANSFER.txt') + if not path_exists(readme): + copy_file(os.path.join(script_dir, 'distrib/README-TRANSFER.txt'), readme) + open(readme, 'ab').write(cfg['source']+"\n") + + # perform any required post-processing + if 'post-process' in cfg: + post = cfg['post-process'] + if post == 'normalize_headers': + new_path = '' + if cfg.has_key('new_header_path'): + new_path = cfg['new_header_path'] + normalize_headers(dst, new_path) + +def combine_libs(build_dir, libs, dest_lib): + """ Combine multiple static libraries into a single static library. """ + cmdline = 'msvs_env.bat python combine_libs.py -o "%s"' % dest_lib + for lib in libs: + lib_path = os.path.join(build_dir, lib) + if not path_exists(lib_path): + raise Exception('Library not found: ' + lib_path) + cmdline = cmdline + ' "%s"' % lib_path + run(cmdline, os.path.join(cef_dir, 'tools')) + +def generate_msvs_projects(version): + """ Generate MSVS projects for the specified version. """ + sys.stdout.write('Generating '+version+' project files...') + os.environ['GYP_GENERATORS'] = 'msvs' + os.environ['GYP_MSVS_VERSION'] = version + # Don't use the bundled toolchain because it will cause the above values to + # be ignored. + os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0' + gyper = [ 'python', '../build/gyp_chromium', + os.path.relpath(os.path.join(output_dir, 'cefclient.gyp'), cef_dir) ] + RunAction(cef_dir, gyper); + move_file(os.path.relpath(os.path.join(output_dir, 'cefclient.sln')), \ + os.path.relpath(os.path.join(output_dir, 'cefclient'+version+'.sln'))) + +def create_msvs_projects(): + """ Create MSVS project files. """ + if not options.x64build: + generate_msvs_projects('2005'); + generate_msvs_projects('2008'); + generate_msvs_projects('2010'); + + # Fix the output directory path in all .vcproj and .vcxproj files. + files = [] + for file in get_files(os.path.join(output_dir, '*.vcproj')): + files.append(file) + for file in get_files(os.path.join(output_dir, '*.vcxproj')): + files.append(file) + for file in files: + data = read_file(file) + # fix the build directory path + data = data.replace('../../..\\build\\', 'out\\') + data = data.replace('..\\..\\..\\build\\', 'out\\') + # fix xcopy arguments + data = data.replace('xcopy \\', 'xcopy /') + if options.x64build: + # fix machine type + data = data.replace('MachineX86', 'MachineX64') + write_file(file, data) + +def create_xcode_projects(): + """ Create Xcode project files. """ + sys.stdout.write('Generating Xcode project files...') + os.environ['GYP_GENERATORS'] = 'xcode' + gyper = [ 'python', '../build/gyp_chromium', + os.path.relpath(os.path.join(output_dir, 'cefclient.gyp'), cef_dir) ] + RunAction(cef_dir, gyper); + + # Post-process the Xcode project file. + src_file = os.path.join(output_dir, 'cefclient.xcodeproj/project.pbxproj') + data = read_file(src_file) + + # Fix file paths. + data = data.replace('../../../build/mac/', 'tools/') + data = data.replace('../../../build', 'build') + data = data.replace('../../../xcodebuild', 'xcodebuild') + + # Fix framework type. + data = data.replace('lastKnownFileType = text; name = "Chromium Embedded Framework";', \ + 'explicitFileType = "compiled.mach-o.dylib"; name = "Chromium Embedded Framework";') + + # Fix target compiler. + data = data.replace('GCC_VERSION = 4.2;', 'GCC_VERSION = com.apple.compilers.llvm.clang.1_0;') + + write_file(src_file, data) + +def create_make_projects(): + """ Create make project files. """ + makefile = os.path.join(src_dir, 'Makefile') + makefile_tmp = '' + if path_exists(makefile): + # Back up the existing Makefile + makefile_tmp = makefile + '.cef_bak' + copy_file(makefile, makefile_tmp, options.quiet) + + # Generate make project files + sys.stdout.write('Generating make project files...') + os.environ['GYP_GENERATORS'] = 'make' + gyper = [ 'python', '../build/gyp_chromium', + os.path.relpath(os.path.join(output_dir, 'cefclient.gyp'), cef_dir) ] + RunAction(cef_dir, gyper); + + # Copy the resulting Makefile to the destination directory + copy_file(makefile, output_dir, options.quiet) + + remove_file(makefile, options.quiet) + if makefile_tmp != '': + # Restore the original Makefile + move_file(makefile_tmp, makefile, options.quiet) + + # Fix the output directory path in Makefile and all .mk files. + find = os.path.relpath(output_dir, src_dir) + files = [os.path.join(output_dir, 'Makefile')] + for file in get_files(os.path.join(output_dir, '*.mk')): + files.append(file) + for file in files: + data = read_file(file) + data = data.replace(find, '.') + data = data.replace('/./', '/') + if os.path.basename(file) == 'Makefile': + # remove the quiet_cmd_regen_makefile section + pos = str.find(data, 'quiet_cmd_regen_makefile') + if pos >= 0: + epos = str.find(data, '#', pos) + if epos >= 0: + data = data[0:pos] + data[epos:] + write_file(file, data) + +def run(command_line, working_dir): + """ Run a command. """ + sys.stdout.write('-------- Running "'+command_line+'" in "'+\ + working_dir+'"...'+"\n") + args = shlex.split(command_line.replace('\\', '\\\\')) + return subprocess.check_call(args, cwd=working_dir, env=os.environ, + shell=(sys.platform == 'win32')) + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# parse command-line options +disc = """ +This utility builds the CEF Binary Distribution. +""" + +parser = OptionParser(description=disc) +parser.add_option('--output-dir', dest='outputdir', metavar='DIR', + help='output directory [required]') +parser.add_option('--allow-partial', + action='store_true', dest='allowpartial', default=False, + help='allow creation of partial distributions') +parser.add_option('--no-symbols', + action='store_true', dest='nosymbols', default=False, + help='don\'t create symbol files') +parser.add_option('--no-docs', + action='store_true', dest='nodocs', default=False, + help='don\'t create documentation') +parser.add_option('--no-archive', + action='store_true', dest='noarchive', default=False, + help='don\'t create archives for output directories') +parser.add_option('--ninja-build', + action='store_true', dest='ninjabuild', default=False, + help='build was created using ninja') +parser.add_option('--x64-build', + action='store_true', dest='x64build', default=False, + help='build was created for 64-bit systems') +parser.add_option('--minimal', + action='store_true', dest='minimal', default=False, + help='include only release build binary files') +parser.add_option('--client', + action='store_true', dest='client', default=False, + help='include only the cefclient application') +parser.add_option('-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# Test the operating system. +platform = ''; +if sys.platform == 'win32': + platform = 'windows' +elif sys.platform == 'darwin': + platform = 'macosx' +elif sys.platform.startswith('linux'): + platform = 'linux' + +# the outputdir option is required +if options.outputdir is None: + parser.print_help(sys.stderr) + sys.exit() + +if options.minimal and options.client: + print 'Invalid combination of options' + parser.print_help(sys.stderr) + sys.exit() + +if platform == 'windows' and options.x64build and not options.ninjabuild: + print 'x64 build on Windows requires ninja' + sys.exit() + +# script directory +script_dir = os.path.dirname(__file__) + +# CEF root directory +cef_dir = os.path.abspath(os.path.join(script_dir, os.pardir)) + +# src directory +src_dir = os.path.abspath(os.path.join(cef_dir, os.pardir)) + +# retrieve url and revision information for CEF +if svn.is_checkout(cef_dir): + cef_info = svn.get_svn_info(cef_dir) + cef_url = cef_info['url'] + cef_rev = cef_info['revision'] +elif git.is_checkout(cef_dir): + cef_url = git.get_url(cef_dir) + cef_rev = git.get_svn_revision(cef_dir) +else: + raise Exception('Not a valid checkout: %s' % (cef_dir)) + +# retrieve url and revision information for Chromium +if svn.is_checkout(src_dir): + chromium_info = svn.get_svn_info(src_dir) + chromium_url = chromium_info['url'] + chromium_rev = chromium_info['revision'] +elif git.is_checkout(src_dir): + chromium_url = git.get_url(src_dir) + chromium_rev = git.get_hash(src_dir, 'HEAD') +else: + raise Exception('Not a valid checkout: %s' % (src_dir)) + +date = get_date() + +# Read and parse the version file (key=value pairs, one per line) +args = {} +read_version_file(os.path.join(cef_dir, 'VERSION'), args) +read_version_file(os.path.join(cef_dir, '../chrome/VERSION'), args) + +cef_ver = args['CEF_MAJOR']+'.'+args['BUILD']+'.'+cef_rev +chromium_ver = args['MAJOR']+'.'+args['MINOR']+'.'+args['BUILD']+'.'+args['PATCH'] + +# list of output directories to be archived +archive_dirs = [] + +platform_arch = '32' +if options.x64build: + platform_arch = '64' + +if platform == 'linux': + platform_arch = '' + lib_dir_name = 'lib.target' + if options.ninjabuild: + lib_dir_name = 'lib' + release_libcef_path = os.path.join(src_dir, 'out', 'Release', lib_dir_name, 'libcef.so'); + debug_libcef_path = os.path.join(src_dir, 'out', 'Debug', lib_dir_name, 'libcef.so'); + file_desc = '' + output = subprocess.check_output('file ' + release_libcef_path + ' ' + debug_libcef_path + '; exit 0', + env=os.environ, stderr=subprocess.STDOUT, shell=True) + if output.find('32-bit') != -1: + platform_arch = '32' + if output.find('64-bit') != -1: + platform_arch = '64' + +# output directory +output_dir_base = 'cef_binary_' + cef_ver +output_dir_name = output_dir_base + '_' + platform + platform_arch + +if options.minimal: + mode = 'minimal' + output_dir_name = output_dir_name + '_minimal' +elif options.client: + mode = 'client' + output_dir_name = output_dir_name + '_client' +else: + mode = 'standard' + +output_dir = create_output_dir(output_dir_name, options.outputdir) + +# create the README.TXT file +create_readme() + +# transfer the LICENSE.txt file +copy_file(os.path.join(cef_dir, 'LICENSE.txt'), output_dir, options.quiet) + +# read the variables list from the autogenerated cef_paths.gypi file +cef_paths = eval_file(os.path.join(cef_dir, 'cef_paths.gypi')) +cef_paths = cef_paths['variables'] + +# read the variables list from the manually edited cef_paths2.gypi file +cef_paths2 = eval_file(os.path.join(cef_dir, 'cef_paths2.gypi')) +cef_paths2 = cef_paths2['variables'] + +if mode == 'standard': + # create the include directory + include_dir = os.path.join(output_dir, 'include') + make_dir(include_dir, options.quiet) + + # create the cefclient directory + cefclient_dir = os.path.join(output_dir, 'cefclient') + make_dir(cefclient_dir, options.quiet) + + # create the cefsimple directory + cefsimple_dir = os.path.join(output_dir, 'cefsimple') + make_dir(cefsimple_dir, options.quiet) + + # create the libcef_dll_wrapper directory + wrapper_dir = os.path.join(output_dir, 'libcef_dll') + make_dir(wrapper_dir, options.quiet) + + # transfer common include files + transfer_gypi_files(cef_dir, cef_paths2['includes_common'], \ + 'include/', include_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['includes_capi'], \ + 'include/', include_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['includes_wrapper'], \ + 'include/', include_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths['autogen_cpp_includes'], \ + 'include/', include_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths['autogen_capi_includes'], \ + 'include/', include_dir, options.quiet) + + # transfer common cefclient files + transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_common'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefclient_bundle_resources_common'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + + # transfer common cefsimple files + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_common'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + + # transfer common libcef_dll_wrapper files + transfer_gypi_files(cef_dir, cef_paths2['libcef_dll_wrapper_sources_common'], \ + 'libcef_dll/', wrapper_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths['autogen_client_side'], \ + 'libcef_dll/', wrapper_dir, options.quiet) + + # transfer gyp files + copy_file(os.path.join(script_dir, 'distrib/cefclient.gyp'), output_dir, options.quiet) + paths_gypi = os.path.join(cef_dir, 'cef_paths2.gypi') + data = read_file(paths_gypi) + data = data.replace('tests/cefclient/', 'cefclient/') + data = data.replace('tests/cefsimple/', 'cefsimple/') + write_file(os.path.join(output_dir, 'cef_paths2.gypi'), data) + copy_file(os.path.join(cef_dir, 'cef_paths.gypi'), \ + os.path.join(output_dir, 'cef_paths.gypi'), options.quiet) + + # transfer additional files + transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib/transfer.cfg'), \ + output_dir, options.quiet) + +if platform == 'windows': + binaries = [ + 'd3dcompiler_46.dll', + 'ffmpegsumo.dll', + 'libcef.dll', + 'libEGL.dll', + 'libGLESv2.dll', + 'pdf.dll', + ] + + if options.ninjabuild: + out_dir = os.path.join(src_dir, 'out') + libcef_dll_file = 'libcef.dll.lib' + sandbox_libs = [ + 'obj\\base\\base.lib', + 'obj\\base\\base_static.lib', + 'obj\\cef\\cef_sandbox.lib', + 'obj\\base\\third_party\\dynamic_annotations\\dynamic_annotations.lib', + 'obj\\sandbox\\sandbox.lib', + ] + else: + out_dir = os.path.join(src_dir, 'build') + libcef_dll_file = 'lib/libcef.lib' + sandbox_libs = [ + 'lib\\base.lib', + 'lib\\base_static.lib', + 'lib\\cef_sandbox.lib', + 'lib\\dynamic_annotations.lib', + 'lib\\sandbox.lib', + ] + + valid_build_dir = None + + build_dir_suffix = '' + if options.x64build: + build_dir_suffix = '_x64' + + if mode == 'standard': + # transfer Debug files + build_dir = os.path.join(out_dir, 'Debug' + build_dir_suffix); + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient.exe')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Debug') + make_dir(dst_dir, options.quiet) + copy_files(os.path.join(script_dir, 'distrib/win/*.dll'), dst_dir, options.quiet) + for binary in binaries: + copy_file(os.path.join(build_dir, binary), os.path.join(dst_dir, binary), options.quiet) + copy_file(os.path.join(build_dir, libcef_dll_file), os.path.join(dst_dir, 'libcef.lib'), \ + options.quiet) + combine_libs(build_dir, sandbox_libs, os.path.join(dst_dir, 'cef_sandbox.lib')); + + if not options.nosymbols: + # create the symbol output directory + symbol_output_dir = create_output_dir(output_dir_name + '_debug_symbols', options.outputdir) + # transfer contents + copy_file(os.path.join(build_dir, 'libcef.dll.pdb'), symbol_output_dir, options.quiet) + else: + sys.stderr.write("No Debug build files.\n") + + # transfer Release files + build_dir = os.path.join(out_dir, 'Release' + build_dir_suffix); + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient.exe')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Release') + make_dir(dst_dir, options.quiet) + copy_files(os.path.join(script_dir, 'distrib/win/*.dll'), dst_dir, options.quiet) + for binary in binaries: + copy_file(os.path.join(build_dir, binary), os.path.join(dst_dir, binary), options.quiet) + + if mode != 'client': + copy_file(os.path.join(build_dir, libcef_dll_file), os.path.join(dst_dir, 'libcef.lib'), \ + options.quiet) + combine_libs(build_dir, sandbox_libs, os.path.join(dst_dir, 'cef_sandbox.lib')); + else: + copy_file(os.path.join(build_dir, 'cefclient.exe'), dst_dir, options.quiet) + + if not options.nosymbols: + # create the symbol output directory + symbol_output_dir = create_output_dir(output_dir_name + '_release_symbols', options.outputdir) + # transfer contents + copy_file(os.path.join(build_dir, 'libcef.dll.pdb'), symbol_output_dir, options.quiet) + else: + sys.stderr.write("No Release build files.\n") + + if not valid_build_dir is None: + # transfer resource files + build_dir = valid_build_dir + if mode == 'client': + dst_dir = os.path.join(output_dir, 'Release') + else: + dst_dir = os.path.join(output_dir, 'Resources') + make_dir(dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef_100_percent.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef_200_percent.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'devtools_resources.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'icudtl.dat'), dst_dir, options.quiet) + copy_dir(os.path.join(build_dir, 'locales'), os.path.join(dst_dir, 'locales'), options.quiet) + + if mode == 'standard': + # transfer include files + transfer_gypi_files(cef_dir, cef_paths2['includes_win'], \ + 'include/', include_dir, options.quiet) + + # transfer cefclient files + transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_win'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + + # transfer cefsimple files + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_win'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + + # transfer additional files, if any + transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib/win/transfer.cfg'), \ + output_dir, options.quiet) + + create_msvs_projects() + + if not options.nodocs: + # generate doc files + os.popen('make_cppdocs.bat '+cef_rev) + + src_dir = os.path.join(cef_dir, 'docs') + if path_exists(src_dir): + # create the docs output directory + docs_output_dir = create_output_dir(output_dir_base + '_docs', options.outputdir) + # transfer contents + copy_dir(src_dir, docs_output_dir, options.quiet) + +elif platform == 'macosx': + if options.ninjabuild: + out_dir = os.path.join(src_dir, 'out') + else: + out_dir = os.path.join(src_dir, 'xcodebuild') + + valid_build_dir = None + framework_name = 'Chromium Embedded Framework' + + if mode == 'standard': + # transfer Debug files + build_dir = os.path.join(out_dir, 'Debug') + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient.app')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Debug') + make_dir(dst_dir, options.quiet) + copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \ + os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet) + + # transfer Release files + build_dir = os.path.join(out_dir, 'Release') + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient.app')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Release') + make_dir(dst_dir, options.quiet) + if mode != 'client': + copy_dir(os.path.join(build_dir, 'cefclient.app/Contents/Frameworks/%s.framework' % framework_name), \ + os.path.join(dst_dir, '%s.framework' % framework_name), options.quiet) + else: + copy_dir(os.path.join(build_dir, 'cefclient.app'), os.path.join(dst_dir, 'cefclient.app'), options.quiet) + + if not options.nosymbols: + # create the symbol output directory + symbol_output_dir = create_output_dir(output_dir_name + '_release_symbols', options.outputdir) + + # create the real dSYM file from the "fake" dSYM file + sys.stdout.write("Creating the real dSYM file...\n") + src_path = os.path.join(build_dir, \ + '%s.framework.dSYM/Contents/Resources/DWARF/%s' % (framework_name, framework_name)) + dst_path = os.path.join(symbol_output_dir, '%s.dSYM' % framework_name) + run('dsymutil "%s" -o "%s"' % (src_path, dst_path), cef_dir) + + if mode == 'standard': + # transfer include files + transfer_gypi_files(cef_dir, cef_paths2['includes_mac'], \ + 'include/', include_dir, options.quiet) + + # transfer cefclient files + transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_mac'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_mac_helper'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefclient_bundle_resources_mac'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + + # transfer cefclient/mac files + copy_dir(os.path.join(cef_dir, 'tests/cefclient/mac/'), os.path.join(output_dir, 'cefclient/mac/'), \ + options.quiet) + + # transfer cefsimple files + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_mac'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_mac_helper'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_bundle_resources_mac'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + + # transfer cefsimple/mac files + copy_dir(os.path.join(cef_dir, 'tests/cefsimple/mac/'), os.path.join(output_dir, 'cefsimple/mac/'), \ + options.quiet) + + # transfer additional files, if any + transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib/mac/transfer.cfg'), \ + output_dir, options.quiet) + + create_xcode_projects() + +elif platform == 'linux': + out_dir = os.path.join(src_dir, 'out') + if options.ninjabuild: + lib_dir_name = 'lib' + else: + lib_dir_name = 'lib.target' + + valid_build_dir = None + + if mode == 'standard': + # transfer Debug files + build_dir = os.path.join(out_dir, 'Debug'); + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Debug') + make_dir(dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet) + copy_file(os.path.join(build_dir, lib_dir_name, 'libcef.so'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'libffmpegsumo.so'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'libpdf.so'), dst_dir, options.quiet) + else: + sys.stderr.write("No Debug build files.\n") + + # transfer Release files + build_dir = os.path.join(out_dir, 'Release'); + if not options.allowpartial or path_exists(os.path.join(build_dir, 'cefclient')): + valid_build_dir = build_dir + dst_dir = os.path.join(output_dir, 'Release') + make_dir(dst_dir, options.quiet) + + if mode == 'client': + lib_dst_dir = os.path.join(dst_dir, lib_dir_name) + make_dir(lib_dst_dir, options.quiet) + copy_file(os.path.join(build_dir, lib_dir_name, 'libcef.so'), lib_dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cefclient'), dst_dir, options.quiet) + else: + copy_file(os.path.join(build_dir, lib_dir_name, 'libcef.so'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet) + copy_file(os.path.join(build_dir, 'libffmpegsumo.so'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'libpdf.so'), dst_dir, options.quiet) + else: + sys.stderr.write("No Release build files.\n") + + if not valid_build_dir is None: + # transfer resource files + build_dir = valid_build_dir + if mode == 'client': + dst_dir = os.path.join(output_dir, 'Release') + copy_dir(os.path.join(build_dir, 'files'), os.path.join(dst_dir, 'files'), options.quiet) + else: + dst_dir = os.path.join(output_dir, 'Resources') + make_dir(dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef_100_percent.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'cef_200_percent.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'devtools_resources.pak'), dst_dir, options.quiet) + copy_file(os.path.join(build_dir, 'icudtl.dat'), dst_dir, options.quiet) + copy_dir(os.path.join(build_dir, 'locales'), os.path.join(dst_dir, 'locales'), options.quiet) + + if mode == 'standard': + # transfer include files + transfer_gypi_files(cef_dir, cef_paths2['includes_linux'], \ + 'include/', include_dir, options.quiet) + + # transfer cefclient files + transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_linux'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + transfer_gypi_files(cef_dir, cef_paths2['cefclient_bundle_resources_linux'], \ + 'tests/cefclient/', cefclient_dir, options.quiet) + + # transfer cefsimple files + transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_linux'], \ + 'tests/cefsimple/', cefsimple_dir, options.quiet) + + # transfer additional files, if any + copy_file(os.path.join(script_dir, 'distrib/linux/build.sh'), output_dir, options.quiet) + transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib/linux/transfer.cfg'), \ + output_dir, options.quiet) + + create_make_projects() + +if not options.noarchive: + # create an archive for each output directory + archive_extenstion = '.zip' + if os.getenv('CEF_COMMAND_7ZIP', '') != '': + archive_extenstion = '.7z' + for dir in archive_dirs: + zip_file = os.path.split(dir)[1] + archive_extenstion + if not options.quiet: + sys.stdout.write('Creating '+zip_file+"...\n") + if archive_extenstion == '.zip': + create_archive(dir, os.path.join(dir, os.pardir, zip_file)) + else: + create_7z_archive(dir, os.path.join(dir, os.pardir, zip_file)) diff --git a/tools/make_distrib.sh b/tools/make_distrib.sh new file mode 100755 index 000000000..273a3e16b --- /dev/null +++ b/tools/make_distrib.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python make_distrib.py --output-dir ../binary_distrib/ $@ diff --git a/tools/make_gypi_file.py b/tools/make_gypi_file.py new file mode 100644 index 000000000..e5cefd7a9 --- /dev/null +++ b/tools/make_gypi_file.py @@ -0,0 +1,108 @@ +# 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. + +from cef_parser import * + +def make_gypi_file(header): + # header string + result = \ +"""# Copyright (c) $YEAR$ 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. +# +# --------------------------------------------------------------------------- +# +# This file was generated by the CEF translator tool and should not edited +# by hand. See the translator.README.txt file in the tools directory for +# more information. +# + +{ + 'variables': { +""" + + filenames = sorted(header.get_file_names()) + + # cpp includes + result += " 'autogen_cpp_includes': [\n" + for filename in filenames: + result += " 'include/"+filename+"',\n" + result += " ],\n" + + # capi includes + result += " 'autogen_capi_includes': [\n" + for filename in filenames: + result += " 'include/capi/"+get_capi_file_name(filename)+"',\n" + result += " ],\n" + + classes = sorted(header.get_class_names()) + + # library side includes + result += " 'autogen_library_side': [\n" + for clsname in classes: + cls = header.get_class(clsname) + filename = get_capi_name(clsname[3:], False) + if cls.is_library_side(): + result += " 'libcef_dll/cpptoc/"+filename+"_cpptoc.cc',\n" \ + " 'libcef_dll/cpptoc/"+filename+"_cpptoc.h',\n" + else: + result += " 'libcef_dll/ctocpp/"+filename+"_ctocpp.cc',\n" \ + " 'libcef_dll/ctocpp/"+filename+"_ctocpp.h',\n" + result += " ],\n" + + # client side includes + result += " 'autogen_client_side': [\n" + for clsname in classes: + cls = header.get_class(clsname) + filename = get_capi_name(clsname[3:], False) + if cls.is_library_side(): + result += " 'libcef_dll/ctocpp/"+filename+"_ctocpp.cc',\n" \ + " 'libcef_dll/ctocpp/"+filename+"_ctocpp.h',\n" + else: + result += " 'libcef_dll/cpptoc/"+filename+"_cpptoc.cc',\n" \ + " 'libcef_dll/cpptoc/"+filename+"_cpptoc.h',\n" + result += " ],\n" + + # footer string + result += \ +""" }, +} +""" + + # add the copyright year + result = result.replace('$YEAR$', get_year()) + + return result + +def write_gypi_file(header, file, backup): + if path_exists(file): + oldcontents = read_file(file) + else: + oldcontents = '' + + newcontents = make_gypi_file(header) + if newcontents != oldcontents: + if backup and oldcontents != '': + backup_file(file) + write_file(file, newcontents) + return True + + return False + + +# test the module +if __name__ == "__main__": + import sys + + # verify that the correct number of command-line arguments are provided + if len(sys.argv) < 2: + sys.stderr.write('Usage: '+sys.argv[0]+' ') + sys.exit() + + # create the header object + header = obj_header() + header.add_file(sys.argv[1]) + + # dump the result to stdout + sys.stdout.write(make_gypi_file(header)) diff --git a/tools/make_pack_header.py b/tools/make_pack_header.py new file mode 100644 index 000000000..0b4cb2e04 --- /dev/null +++ b/tools/make_pack_header.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# 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. + +""" +A simple utility function to merge pack resource files into a single resource file. +""" + +from date_util import * +from file_util import * +import os +import re +import string +import sys + + +def MakeFileSegment(input): + result = """ + +// --------------------------------------------------------------------------- +// From $FILE$: +""" + + filename = os.path.split(input)[1] + result = result.replace('$FILE$', filename) + + contents = read_file(input) + + # identify the defines in the file + p = re.compile('#define\s([A-Za-z0-9_]{1,})\s([0-9]{1,})') + list = p.findall(contents) + for name, id in list: + result += "\n#define %s %s" % (name, id) + + return result + + +def MakeFile(output, input): + # header string + result = \ +"""// Copyright (c) $YEAR$ Marshall A. Greenblatt. 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 file is generated by the make_pack_header.py tool. +// + +#ifndef $GUARD$ +#define $GUARD$ +#pragma once""" + + # sort the input files by name + input = sorted(input, key=lambda path: os.path.split(path)[1]) + + # generate the file segments + for file in input: + result += MakeFileSegment(file) + + # footer string + result += \ +""" + +#endif // $GUARD$ +""" + + # add the copyright year + result = result.replace('$YEAR$', get_year()) + # add the guard string + filename = os.path.split(output)[1] + guard = 'CEF_INCLUDE_'+string.upper(filename.replace('.', '_'))+'_' + result = result.replace('$GUARD$', guard) + + if path_exists(output): + old_contents = read_file(output) + else: + old_contents = '' + + if (result != old_contents): + write_file(output, result) + sys.stdout.write('File '+output+' updated.\n') + else: + sys.stdout.write('File '+output+' is already up to date.\n') + +def main(argv): + if len(argv) < 3: + print ("Usage:\n %s [input_file2] ... " % + argv[0]) + sys.exit(-1) + MakeFile(argv[1], argv[2:]) + + +if '__main__' == __name__: + main(sys.argv) diff --git a/tools/make_version_header.bat b/tools/make_version_header.bat new file mode 100644 index 000000000..86e3094f8 --- /dev/null +++ b/tools/make_version_header.bat @@ -0,0 +1,2 @@ +@echo off +python.bat tools\make_version_header.py --header include\cef_version.h --cef_version VERSION --chrome_version ../chrome/VERSION --cpp_header_dir include diff --git a/tools/make_version_header.py b/tools/make_version_header.py new file mode 100644 index 000000000..84d49f52a --- /dev/null +++ b/tools/make_version_header.py @@ -0,0 +1,176 @@ +# 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. + +from date_util import * +from file_util import * +from optparse import OptionParser +from cef_api_hash import cef_api_hash +import svn_util as svn +import git_util as git +import sys + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + + +# parse command-line options +disc = """ +This utility creates the version header file. +""" + +parser = OptionParser(description=disc) +parser.add_option('--header', dest='header', metavar='FILE', + help='output version header file [required]') +parser.add_option('--cef_version', dest='cef_version', metavar='FILE', + help='input CEF version config file [required]') +parser.add_option('--chrome_version', dest='chrome_version', metavar='FILE', + help='input Chrome version config file [required]') +parser.add_option('--cpp_header_dir', dest='cpp_header_dir', metavar='DIR', + help='input directory for C++ header files [required]') +parser.add_option('-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# the header option is required +if options.header is None or options.cef_version is None or options.chrome_version is None or options.cpp_header_dir is None: + parser.print_help(sys.stdout) + sys.exit() + +def write_svn_header(header, chrome_version, cef_version, cpp_header_dir): + """ Creates the header file for the current revision and Chrome version information + if the information has changed or if the file doesn't already exist. """ + + if not path_exists(chrome_version): + raise Exception('Chrome version file '+chrome_version+' does not exist.') + if not path_exists(cef_version): + raise Exception('CEF version file '+cef_version+' does not exist.') + + args = {} + read_version_file(chrome_version, args) + read_version_file(cef_version, args) + + if path_exists(header): + oldcontents = read_file(header) + else: + oldcontents = '' + + year = get_year() + + if svn.is_checkout('.'): + revision = svn.get_revision() + elif git.is_checkout('.'): + revision = git.get_svn_revision() + else: + raise Exception('Not a valid checkout') + + # calculate api hashes + api_hash_calculator = cef_api_hash(cpp_header_dir, verbose = False) + api_hashes = api_hash_calculator.calculate() + + newcontents = '// Copyright (c) '+year+' Marshall A. Greenblatt. All rights reserved.\n'+\ + '//\n'+\ + '// Redistribution and use in source and binary forms, with or without\n'+\ + '// modification, are permitted provided that the following conditions are\n'+\ + '// met:\n'+\ + '//\n'+\ + '// * Redistributions of source code must retain the above copyright\n'+\ + '// notice, this list of conditions and the following disclaimer.\n'+\ + '// * Redistributions in binary form must reproduce the above\n'+\ + '// copyright notice, this list of conditions and the following disclaimer\n'+\ + '// in the documentation and/or other materials provided with the\n'+\ + '// distribution.\n'+\ + '// * Neither the name of Google Inc. nor the name Chromium Embedded\n'+\ + '// Framework nor the names of its contributors may be used to endorse\n'+\ + '// or promote products derived from this software without specific prior\n'+\ + '// written permission.\n'+\ + '//\n'+\ + '// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n'+\ + '// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n'+\ + '// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n'+\ + '// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n'+\ + '// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n'+\ + '// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n'+\ + '// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n'+\ + '// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n'+\ + '// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n'+\ + '// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n'+\ + '// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n'+\ + '//\n'+\ + '// ---------------------------------------------------------------------------\n'+\ + '//\n'+\ + '// This file is generated by the make_version_header.py tool.\n'+\ + '//\n\n'+\ + '#ifndef CEF_INCLUDE_CEF_VERSION_H_\n'+\ + '#define CEF_INCLUDE_CEF_VERSION_H_\n\n'+\ + '#define CEF_VERSION_MAJOR ' + args['CEF_MAJOR'] + '\n'+\ + '#define CEF_REVISION ' + revision + '\n'+\ + '#define COPYRIGHT_YEAR ' + year + '\n\n'+\ + '#define CHROME_VERSION_MAJOR ' + args['MAJOR'] + '\n'+\ + '#define CHROME_VERSION_MINOR ' + args['MINOR'] + '\n'+\ + '#define CHROME_VERSION_BUILD ' + args['BUILD'] + '\n'+\ + '#define CHROME_VERSION_PATCH ' + args['PATCH'] + '\n\n'+\ + '#define DO_MAKE_STRING(p) #p\n'+\ + '#define MAKE_STRING(p) DO_MAKE_STRING(p)\n\n'+\ + '#ifndef APSTUDIO_HIDDEN_SYMBOLS\n\n'\ + '#include "include/internal/cef_export.h"\n\n'+\ + '#ifdef __cplusplus\n'+\ + 'extern "C" {\n'+\ + '#endif\n\n'+\ + '// The API hash is created by analyzing CEF header files for C API type\n'+\ + '// definitions. The hash value will change when header files are modified\n'+\ + '// in a way that may cause binary incompatibility with other builds. The\n'+\ + '// universal hash value will change if any platform is affected whereas the\n'+\ + '// platform hash values will change only if that particular platform is\n'+\ + '// affected.\n'+\ + '#define CEF_API_HASH_UNIVERSAL "' + api_hashes['universal'] + '"\n'+\ + '#if defined(OS_WIN)\n'+\ + '#define CEF_API_HASH_PLATFORM "' + api_hashes['windows'] + '"\n'+\ + '#elif defined(OS_MACOSX)\n'+\ + '#define CEF_API_HASH_PLATFORM "' + api_hashes['macosx'] + '"\n'+\ + '#elif defined(OS_LINUX)\n'+\ + '#define CEF_API_HASH_PLATFORM "' + api_hashes['linux'] + '"\n'+\ + '#endif\n\n'+\ + '///\n'+\ + '// Returns the CEF build revision for the libcef library.\n'+\ + '///\n'+\ + 'CEF_EXPORT int cef_build_revision();\n\n'+\ + '///\n'+\ + '// Returns CEF version information for the libcef library. The |entry|\n'+\ + '// parameter describes which version component will be returned:\n'+\ + '// 0 - CEF_VERSION_MAJOR\n'+\ + '// 1 - CEF_REVISION\n'+\ + '// 2 - CHROME_VERSION_MAJOR\n'+\ + '// 3 - CHROME_VERSION_MINOR\n'+\ + '// 4 - CHROME_VERSION_BUILD\n'+\ + '// 5 - CHROME_VERSION_PATCH\n'+\ + '///\n'+\ + 'CEF_EXPORT int cef_version_info(int entry);\n\n'+\ + '///\n'+\ + '// Returns CEF API hashes for the libcef library. The returned string is owned\n'+\ + '// by the library and should not be freed. The |entry| parameter describes which\n'+\ + '// hash value will be returned:\n'+\ + '// 0 - CEF_API_HASH_PLATFORM\n'+\ + '// 1 - CEF_API_HASH_UNIVERSAL\n'+\ + '///\n'+\ + 'CEF_EXPORT const char* cef_api_hash(int entry);\n\n'+\ + '#ifdef __cplusplus\n'+\ + '}\n'+\ + '#endif\n\n'+\ + '#endif // APSTUDIO_HIDDEN_SYMBOLS\n\n'+\ + '#endif // CEF_INCLUDE_CEF_VERSION_H_\n' + if newcontents != oldcontents: + write_file(header, newcontents) + return True + + return False + +written = write_svn_header(options.header, options.chrome_version, options.cef_version, options.cpp_header_dir) +if not options.quiet: + if written: + sys.stdout.write('File '+options.header+' updated.\n') + else: + sys.stdout.write('File '+options.header+' is already up to date.\n') diff --git a/tools/make_version_header.sh b/tools/make_version_header.sh new file mode 100755 index 000000000..4cac35f4a --- /dev/null +++ b/tools/make_version_header.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python tools/make_version_header.py --header include/cef_version.h --cef_version VERSION --chrome_version ../chrome/VERSION --cpp_header_dir include diff --git a/tools/msvs_env.bat b/tools/msvs_env.bat new file mode 100644 index 000000000..07b440691 --- /dev/null +++ b/tools/msvs_env.bat @@ -0,0 +1,60 @@ +@echo off +:: 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. + +:: Set up the environment for use with MSVS tools and then execute whatever +:: was specified on the command-line. + +set RC= +setlocal + +:: In case it's already provided via the environment. +set vcvars="%CEF_VCVARS%" +if exist %vcvars% goto found_vcvars + +:: Hardcoded list of MSVS paths. +:: Alternatively we could 'reg query' this key: +:: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS;ProductDir +set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +:: VS 2008 vcvars isn't standalone, it needs this env var. +set VS90COMNTOOLS=%PROGRAMFILES(X86)%\Microsoft Visual Studio 9.0\Common7\Tools\ +set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars +set VS90COMNTOOLS=%PROGRAMFILES%\Microsoft Visual Studio 9.0\Common7\Tools\ +set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" +if exist %vcvars% goto found_vcvars + +set RC=1 +echo Failed to find vcvars +goto end + +:found_vcvars +echo vcvars: +echo %vcvars% +call %vcvars% + +echo PATH: +echo %PATH% +%* + +:end +endlocal & set RC=%ERRORLEVEL% +goto omega + +:returncode +exit /B %RC% + +:omega +call :returncode %RC% diff --git a/tools/patch.bat b/tools/patch.bat new file mode 100644 index 000000000..0b68f6193 --- /dev/null +++ b/tools/patch.bat @@ -0,0 +1,2 @@ +@echo off +python.bat tools\patcher.py --patch-config patch/patch.cfg \ No newline at end of file diff --git a/tools/patch.sh b/tools/patch.sh new file mode 100755 index 000000000..b9dde9bc0 --- /dev/null +++ b/tools/patch.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python tools/patcher.py --patch-config patch/patch.cfg diff --git a/tools/patch_updater.py b/tools/patch_updater.py new file mode 100644 index 000000000..595d76a64 --- /dev/null +++ b/tools/patch_updater.py @@ -0,0 +1,130 @@ +# 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. + +from optparse import OptionParser +import os +import re +import sys +from exec_util import exec_cmd +import svn_util as svn +import git_util as git + +def msg(message): + """ Output a message. """ + sys.stdout.write('--> ' + message + "\n") + +def warn(message): + """ Output a warning. """ + sys.stdout.write('-' * 80 + "\n") + sys.stdout.write('!!!! WARNING: ' + message + "\n") + sys.stdout.write('-' * 80 + "\n") + +def extract_paths(file): + """ Extract the list of modified paths from the patch file. """ + paths = [] + fp = open(file) + for line in fp: + if line[:4] != '+++ ': + continue + match = re.match('^([^\t]+)', line[4:]) + if not match: + continue + paths.append(match.group(1).strip()) + return paths + +# Cannot be loaded as a module. +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# Parse command-line options. +disc = """ +This utility updates existing patch files. +""" + +parser = OptionParser(description=disc) +parser.add_option('--resave', + action='store_true', dest='resave', default=False, + help='re-save existing patch files to pick up manual changes') +(options, args) = parser.parse_args() + +# The CEF root directory is the parent directory of _this_ script. +cef_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) +src_dir = os.path.join(cef_dir, os.pardir) + +# Determine the type of Chromium checkout. +if svn.is_checkout(src_dir): + src_is_git = False +elif git.is_checkout(src_dir): + src_is_git = True +else: + raise Exception('Not a valid checkout: %s' % src_dir) + +patch_dir = os.path.join(cef_dir, 'patch') +patch_cfg = os.path.join(patch_dir, 'patch.cfg') +if not os.path.isfile(patch_cfg): + raise Exception('File does not exist: %s' % patch_cfg) + +# Read the patch configuration file. +msg('Reading patch config %s' % patch_cfg) +scope = {} +execfile(patch_cfg, scope) +patches = scope["patches"] + +# Read each individual patch file. +patches_dir = os.path.join(patch_dir, 'patches') +for patch in patches: + sys.stdout.write('\n') + patch_file = os.path.join(patches_dir, patch['name']+'.patch') + + if os.path.isfile(patch_file): + msg('Reading patch file %s' % patch_file) + patch_root = patch['path'] + patch_root_abs = os.path.abspath(os.path.join(cef_dir, patch_root)) + + # Retrieve the list of paths modified by the patch file. + patch_paths = extract_paths(patch_file) + + if not options.resave: + # Revert any changes to existing files in the patch. + for patch_path in patch_paths: + patch_path_abs = os.path.abspath(os.path.join(patch_root_abs, \ + patch_path)) + msg('Reverting changes to %s' % patch_path_abs) + if src_is_git: + cmd = 'git checkout -- %s' % (patch_path_abs) + else: + cmd = 'svn revert %s' % (patch_path_abs) + result = exec_cmd(cmd, patch_root_abs) + if result['err'] != '': + raise Exception('Failed to revert file: %s' % result['err']) + if result['out'] != '': + sys.stdout.write(result['out']) + + # Apply the patch file. + msg('Applying patch to %s' % patch_root_abs) + result = exec_cmd('patch -p0', patch_root_abs, patch_file) + if result['err'] != '': + raise Exception('Failed to apply patch file: %s' % result['err']) + sys.stdout.write(result['out']) + if result['out'].find('FAILED') != -1: + warn('Failed to apply %s, fix manually and run with --resave' % \ + patch['name']) + continue + + # Re-create the patch file. + msg('Saving changes to %s' % patch_file) + patch_paths_str = ' '.join(patch_paths) + if src_is_git: + cmd = 'git diff --no-prefix --relative %s' % patch_paths_str + else: + cmd = 'svn diff %s' % patch_paths_str + result = exec_cmd(cmd, patch_root_abs) + if result['err'] != '' and result['err'].find('warning:') != 0: + raise Exception('Failed to create patch file: %s' % result['err']) + f = open(patch_file, 'wb') + f.write(result['out']) + f.close() + else: + raise Exception('Patch file does not exist: %s' % patch_file) diff --git a/tools/patch_util.py b/tools/patch_util.py new file mode 100644 index 000000000..700884bc0 --- /dev/null +++ b/tools/patch_util.py @@ -0,0 +1,593 @@ +""" Patch utility to apply unified diffs """ +""" Brute-force line-by-line parsing + + Project home: http://code.google.com/p/python-patch/ + + This file is subject to the MIT license available here: + http://www.opensource.org/licenses/mit-license.php + + CEF Changes + ----------- + + 2013/01/03 + - Add support for patches containing new files + + 2009/07/22 + - Add a 'root_directory' argument to PatchInfo::apply + - Fix a Python 2.4 compile error in PatchInfo::parse_stream + +""" + +__author__ = "techtonik.rainforce.org" +__version__ = "8.12-1" + +import copy +import logging +import os +import re +from stat import * +# cStringIO doesn't support unicode in 2.5 +from StringIO import StringIO +from logging import debug, info, warning + +from os.path import exists, isfile +from os import unlink + +debugmode = False + + +def from_file(filename): + """ read and parse patch file + return PatchInfo() object + """ + + info("reading patch from file %s" % filename) + fp = open(filename, "rb") + patch = PatchInfo(fp) + fp.close() + return patch + + +def from_string(s): + """ parse text string and return PatchInfo() object """ + return PatchInfo( + StringIO.StringIO(s) + ) + + +class HunkInfo(object): + """ parsed hunk data (hunk starts with @@ -R +R @@) """ + + def __init__(self): + # define HunkInfo data members + self.startsrc=None + self.linessrc=None + self.starttgt=None + self.linestgt=None + self.invalid=False + self.text=[] + + def copy(self): + return copy.copy(self) + +# def apply(self, estream): +# """ write hunk data into enumerable stream +# return strings one by one until hunk is +# over +# +# enumerable stream are tuples (lineno, line) +# where lineno starts with 0 +# """ +# pass + + + + +class PatchInfo(object): + """ patch information container """ + + def __init__(self, stream=None): + """ parse incoming stream """ + + # define PatchInfo data members + # table with a row for every source file + + #: list of source filenames + self.source=None + self.target=None + #: list of lists of hunks + self.hunks=None + #: file endings statistics for every hunk + self.hunkends=None + + if stream: + self.parse_stream(stream) + + def copy(self): + return copy.copy(self) + + def parse_stream(self, stream): + """ parse unified diff """ + self.source = [] + self.target = [] + self.hunks = [] + self.hunkends = [] + + # define possible file regions that will direct the parser flow + header = False # comments before the patch body + filenames = False # lines starting with --- and +++ + + hunkhead = False # @@ -R +R @@ sequence + hunkbody = False # + hunkskip = False # skipping invalid hunk mode + + header = True + lineends = dict(lf=0, crlf=0, cr=0) + nextfileno = 0 + nexthunkno = 0 #: even if index starts with 0 user messages number hunks from 1 + + # hunkinfo holds parsed values, hunkactual - calculated + hunkinfo = HunkInfo() + hunkactual = dict(linessrc=None, linestgt=None) + + fe = enumerate(stream) + for lineno, line in fe: + + # analyze state + if header and line.startswith("--- "): + header = False + # switch to filenames state + filenames = True + #: skip hunkskip and hunkbody code until you read definition of hunkhead + if hunkbody: + # process line first + if re.match(r"^[- \+\\]", line): + # gather stats about line endings + if line.endswith("\r\n"): + self.hunkends[nextfileno-1]["crlf"] += 1 + elif line.endswith("\n"): + self.hunkends[nextfileno-1]["lf"] += 1 + elif line.endswith("\r"): + self.hunkends[nextfileno-1]["cr"] += 1 + + if line.startswith("-"): + hunkactual["linessrc"] += 1 + elif line.startswith("+"): + hunkactual["linestgt"] += 1 + elif not line.startswith("\\"): + hunkactual["linessrc"] += 1 + hunkactual["linestgt"] += 1 + hunkinfo.text.append(line) + # todo: handle \ No newline cases + else: + warning("invalid hunk no.%d at %d for target file %s" % (nexthunkno, lineno+1, self.target[nextfileno-1])) + # add hunk status node + self.hunks[nextfileno-1].append(hunkinfo.copy()) + self.hunks[nextfileno-1][nexthunkno-1]["invalid"] = True + # switch to hunkskip state + hunkbody = False + hunkskip = True + + # check exit conditions + if hunkactual["linessrc"] > hunkinfo.linessrc or hunkactual["linestgt"] > hunkinfo.linestgt: + warning("extra hunk no.%d lines at %d for target %s" % (nexthunkno, lineno+1, self.target[nextfileno-1])) + # add hunk status node + self.hunks[nextfileno-1].append(hunkinfo.copy()) + self.hunks[nextfileno-1][nexthunkno-1]["invalid"] = True + # switch to hunkskip state + hunkbody = False + hunkskip = True + elif hunkinfo.linessrc == hunkactual["linessrc"] and hunkinfo.linestgt == hunkactual["linestgt"]: + self.hunks[nextfileno-1].append(hunkinfo.copy()) + # switch to hunkskip state + hunkbody = False + hunkskip = True + + # detect mixed window/unix line ends + ends = self.hunkends[nextfileno-1] + if ((ends["cr"]!=0) + (ends["crlf"]!=0) + (ends["lf"]!=0)) > 1: + warning("inconsistent line ends in patch hunks for %s" % self.source[nextfileno-1]) + if debugmode: + debuglines = dict(ends) + debuglines.update(file=self.target[nextfileno-1], hunk=nexthunkno) + debug("crlf: %(crlf)d lf: %(lf)d cr: %(cr)d\t - file: %(file)s hunk: %(hunk)d" % debuglines) + + if hunkskip: + match = re.match("^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?", line) + if match: + # switch to hunkhead state + hunkskip = False + hunkhead = True + elif line.startswith("--- "): + # switch to filenames state + hunkskip = False + filenames = True + if debugmode and len(self.source) > 0: + debug("- %2d hunks for %s" % (len(self.hunks[nextfileno-1]), self.source[nextfileno-1])) + + if filenames: + if line.startswith("--- "): + if nextfileno in self.source: + warning("skipping invalid patch for %s" % self.source[nextfileno]) + del self.source[nextfileno] + # double source filename line is encountered + # attempt to restart from this second line + re_filename = "^--- ([^\t]+)" + match = re.match(re_filename, line) + if not match: + warning("skipping invalid filename at line %d" % lineno) + # switch back to header state + filenames = False + header = True + else: + self.source.append(match.group(1).strip()) + elif not line.startswith("+++ "): + if nextfileno in self.source: + warning("skipping invalid patch with no target for %s" % self.source[nextfileno]) + del self.source[nextfileno] + else: + # this should be unreachable + warning("skipping invalid target patch") + filenames = False + header = True + else: + if nextfileno in self.target: + warning("skipping invalid patch - double target at line %d" % lineno) + del self.source[nextfileno] + del self.target[nextfileno] + nextfileno -= 1 + # double target filename line is encountered + # switch back to header state + filenames = False + header = True + else: + re_filename = "^\+\+\+ ([^\t]+)" + match = re.match(re_filename, line) + if not match: + warning("skipping invalid patch - no target filename at line %d" % lineno) + # switch back to header state + filenames = False + header = True + else: + self.target.append(match.group(1)) + nextfileno += 1 + # switch to hunkhead state + filenames = False + hunkhead = True + nexthunkno = 0 + self.hunks.append([]) + self.hunkends.append(lineends.copy()) + continue + + + if hunkhead: + match = re.match("^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))?", line) + if not match: + if nextfileno-1 not in self.hunks: + warning("skipping invalid patch with no hunks for file %s" % self.target[nextfileno-1]) + # switch to header state + hunkhead = False + header = True + continue + else: + # switch to header state + hunkhead = False + header = True + else: + hunkinfo.startsrc = int(match.group(1)) + if match.group(3): + hunkinfo.linessrc = int(match.group(3)) + else: + hunkinfo.linessrc = 1 + hunkinfo.starttgt = int(match.group(4)) + if match.group(6): + hunkinfo.linestgt = int(match.group(6)) + else: + hunkinfo.linestgt = 1 + hunkinfo.invalid = False + hunkinfo.text = [] + + hunkactual["linessrc"] = hunkactual["linestgt"] = 0 + + # switch to hunkbody state + hunkhead = False + hunkbody = True + nexthunkno += 1 + continue + else: + if not hunkskip: + warning("patch file incomplete - %s" % filename) + # sys.exit(?) + else: + # duplicated message when an eof is reached + if debugmode and len(self.source) > 0: + debug("- %2d hunks for %s" % (len(self.hunks[nextfileno-1]), self.source[nextfileno-1])) + + info("total files: %d total hunks: %d" % (len(self.source), sum(len(hset) for hset in self.hunks))) + + def apply(self, root_directory = None): + """ apply parsed patch """ + + total = len(self.source) + for fileno, filename in enumerate(self.source): + + f2patch = filename + if not root_directory is None: + f2patch = root_directory + f2patch + if not exists(f2patch): + # if the patch contains a single hunk at position 0 consider it a new file + if len(self.hunks[fileno]) == 1 and self.hunks[fileno][0].startsrc == 0: + hunklines = [x[1:].rstrip("\r\n") for x in self.hunks[fileno][0].text if x[0] in " +"] + if len(hunklines) > 0: + warning("creating file %s" % (f2patch)) + f = open(f2patch, "wb") + for line in hunklines: + f.write(line + "\n") + f.close() + continue + + f2patch = self.target[fileno] + if not exists(f2patch): + warning("source/target file does not exist\n--- %s\n+++ %s" % (filename, f2patch)) + continue + if not isfile(f2patch): + warning("not a file - %s" % f2patch) + continue + filename = f2patch + + info("processing %d/%d:\t %s" % (fileno+1, total, filename)) + + # validate before patching + f2fp = open(filename) + hunkno = 0 + hunk = self.hunks[fileno][hunkno] + hunkfind = [] + hunkreplace = [] + validhunks = 0 + canpatch = False + for lineno, line in enumerate(f2fp): + if lineno+1 < hunk.startsrc: + continue + elif lineno+1 == hunk.startsrc: + hunkfind = [x[1:].rstrip("\r\n") for x in hunk.text if x[0] in " -"] + hunkreplace = [x[1:].rstrip("\r\n") for x in hunk.text if x[0] in " +"] + #pprint(hunkreplace) + hunklineno = 0 + + # todo \ No newline at end of file + + # check hunks in source file + if lineno+1 < hunk.startsrc+len(hunkfind)-1: + if line.rstrip("\r\n") == hunkfind[hunklineno]: + hunklineno+=1 + else: + debug("hunk no.%d doesn't match source file %s" % (hunkno+1, filename)) + # file may be already patched, but we will check other hunks anyway + hunkno += 1 + if hunkno < len(self.hunks[fileno]): + hunk = self.hunks[fileno][hunkno] + continue + else: + break + + # check if processed line is the last line + if lineno+1 == hunk.startsrc+len(hunkfind)-1: + debug("file %s hunk no.%d -- is ready to be patched" % (filename, hunkno+1)) + hunkno+=1 + validhunks+=1 + if hunkno < len(self.hunks[fileno]): + hunk = self.hunks[fileno][hunkno] + else: + if validhunks == len(self.hunks[fileno]): + # patch file + canpatch = True + break + else: + if hunkno < len(self.hunks[fileno]) and \ + (len(self.hunks[fileno]) != 1 or self.hunks[fileno][0].startsrc != 0): + warning("premature end of source file %s at hunk %d" % (filename, hunkno+1)) + + f2fp.close() + + if validhunks < len(self.hunks[fileno]): + if check_patched(filename, self.hunks[fileno]): + warning("already patched %s" % filename) + else: + warning("source file is different - %s" % filename) + if canpatch: + backupname = filename+".orig" + if exists(backupname): + warning("can't backup original file to %s - aborting" % backupname) + else: + import shutil + shutil.move(filename, backupname) + if patch_hunks(backupname, filename, self.hunks[fileno]): + warning("successfully patched %s" % filename) + unlink(backupname) + else: + warning("error patching file %s" % filename) + shutil.copy(filename, filename+".invalid") + warning("invalid version is saved to %s" % filename+".invalid") + # todo: proper rejects + shutil.move(backupname, filename) + + # todo: check for premature eof + + + +def check_patched(filename, hunks): + matched = True + fp = open(filename) + + class NoMatch(Exception): + pass + + # special case for new files + try: + if len(hunks) == 1 and hunks[0].startsrc == 0: + hunklines = [x[1:].rstrip("\r\n") for x in hunks[0].text if x[0] in " +"] + if len(hunklines) > 0: + for line in hunklines: + srcline = fp.readline() + if not len(srcline) or srcline.rstrip("\r\n") != line: + raise NoMatch + srcline = fp.readline() + if len(srcline): + raise NoMatch + fp.close() + return True + except NoMatch: + fp.close() + fp = open(filename) + + lineno = 1 + line = fp.readline() + hno = None + try: + if not len(line): + raise NoMatch + for hno, h in enumerate(hunks): + # skip to line just before hunk starts + while lineno < h.starttgt-1: + line = fp.readline() + lineno += 1 + if not len(line): + raise NoMatch + for hline in h.text: + # todo: \ No newline at the end of file + if not hline.startswith("-") and not hline.startswith("\\"): + line = fp.readline() + lineno += 1 + if not len(line): + raise NoMatch + if line.rstrip("\r\n") != hline[1:].rstrip("\r\n"): + warning("file is not patched - failed hunk: %d" % (hno+1)) + raise NoMatch + except NoMatch: + matched = False + # todo: display failed hunk, i.e. expected/found + + fp.close() + return matched + + + +def patch_stream(instream, hunks): + """ given a source stream and hunks iterable, yield patched stream + + converts lineends in hunk lines to the best suitable format + autodetected from input + """ + + # todo: At the moment substituted lineends may not be the same + # at the start and at the end of patching. Also issue a + # warning/throw about mixed lineends (is it really needed?) + + hunks = iter(hunks) + + srclineno = 1 + + lineends = {'\n':0, '\r\n':0, '\r':0} + def get_line(): + """ + local utility function - return line from source stream + collecting line end statistics on the way + """ + line = instream.readline() + # 'U' mode works only with text files + if line.endswith("\r\n"): + lineends["\r\n"] += 1 + elif line.endswith("\n"): + lineends["\n"] += 1 + elif line.endswith("\r"): + lineends["\r"] += 1 + return line + + + for hno, h in enumerate(hunks): + debug("hunk %d" % (hno+1)) + # skip to line just before hunk starts + while srclineno < h.startsrc: + yield get_line() + srclineno += 1 + + for hline in h.text: + # todo: check \ No newline at the end of file + if hline.startswith("-") or hline.startswith("\\"): + get_line() + srclineno += 1 + continue + else: + if not hline.startswith("+"): + get_line() + srclineno += 1 + line2write = hline[1:] + # detect if line ends are consistent in source file + if sum([bool(lineends[x]) for x in lineends]) == 1: + newline = [x for x in lineends if lineends[x] != 0][0] + yield line2write.rstrip("\r\n")+newline + else: # newlines are mixed + yield line2write + + for line in instream: + yield line + + + +def patch_hunks(srcname, tgtname, hunks): + # get the current file mode + mode = os.stat(srcname)[ST_MODE] + + src = open(srcname, "rb") + tgt = open(tgtname, "wb") + + debug("processing target file %s" % tgtname) + + tgt.writelines(patch_stream(src, hunks)) + + tgt.close() + src.close() + + # restore the file mode + os.chmod(tgtname, mode) + + return True + + + + + + +from optparse import OptionParser +from os.path import exists +import sys + +if __name__ == "__main__": + opt = OptionParser(usage="%prog [options] unipatch-file", version="python-patch %s" % __version__) + opt.add_option("-d", action="store_true", dest="debugmode", help="debug mode") + (options, args) = opt.parse_args() + + if not args: + opt.print_version() + print("") + opt.print_help() + sys.exit() + debugmode = options.debugmode + patchfile = args[0] + if not exists(patchfile) or not isfile(patchfile): + sys.exit("patch file does not exist - %s" % patchfile) + + + if debugmode: + logging.basicConfig(level=logging.DEBUG, format="%(levelname)8s %(message)s") + else: + logging.basicConfig(level=logging.INFO, format="%(message)s") + + + + patch = from_file(patchfile) + #pprint(patch) + patch.apply() + + # todo: document and test line ends handling logic - patch.py detects proper line-endings + # for inserted hunks and issues a warning if patched file has incosistent line ends diff --git a/tools/patcher.README.txt b/tools/patcher.README.txt new file mode 100644 index 000000000..2078770a4 --- /dev/null +++ b/tools/patcher.README.txt @@ -0,0 +1,32 @@ +Chromium Embedded Framework (CEF) Patch Application Tool -- patcher.py +------------------------------------------------------------------------------- + +Document Last Updated: July 23, 2009 + + +OVERVIEW +-------- + +The CEF patch application tool is used by the patch project to apply patches +to the Chromium and WebKit code bases. Currently only unified diff format is +supported. See the README.txt file in the patch directory for information on +how the patch project uses this tool. + +The 'patcher.bat' file can be used to run the patch application tool with +command-line arguments that match the default CEF directory structure and +output options. Run 'patcher.py -h' for a complete list of available command- +line arguments. + + +CREDITS +------- + +Thanks go to techtonik for developing the python-patch script. The +patch_util.py file is a slightly modified version of the original script which +can be found here: http://code.google.com/p/python-patch/ + + +WORK REMAINING +-------------- + +o Add support for the GIT patch format. diff --git a/tools/patcher.py b/tools/patcher.py new file mode 100644 index 000000000..09cb9c5fa --- /dev/null +++ b/tools/patcher.py @@ -0,0 +1,103 @@ +# 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. + +import pickle +from optparse import OptionParser +import os +import sys +from file_util import * +from patch_util import * + + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + + +# parse command-line options +disc = """ +This utility applies patch files. +""" + +parser = OptionParser(description=disc) +parser.add_option('--patch-config', dest='patchconfig', metavar='DIR', + help='patch configuration file') +(options, args) = parser.parse_args() + +# the patchconfig option is required +if options.patchconfig is None: + parser.print_help(sys.stdout) + sys.exit() + +# normalize the patch directory value +patchdir = os.path.dirname(os.path.abspath(options.patchconfig)).replace('\\', '/') +if patchdir[-1] != '/': + patchdir += '/' + +# check if the patching should be skipped +if os.path.isfile(patchdir + 'NOPATCH'): + nopatch = True + sys.stdout.write('NOPATCH exists -- files have not been patched.\n') +else: + nopatch = False + # locate the patch configuration file + if not os.path.isfile(options.patchconfig): + sys.stderr.write('File '+options.patchconfig+' does not exist.\n') + sys.exit() + + scope = {} + execfile(options.patchconfig, scope) + patches = scope["patches"] + + for patch in patches: + file = patchdir+'patches/'+patch['name']+'.patch' + dopatch = True + + if 'condition' in patch: + # Check that the environment variable is set. + if patch['condition'] not in os.environ: + sys.stderr.write('Skipping patch file '+file+'\n') + dopatch = False + + if dopatch: + if not os.path.isfile(file): + sys.stderr.write('Patch file '+file+' does not exist.\n') + else: + sys.stderr.write('Reading patch file '+file+'\n') + dir = patch['path'] + patchObj = from_file(file) + patchObj.apply(dir) + if 'note' in patch: + separator = '-' * 79 + '\n' + sys.stderr.write(separator) + sys.stderr.write('NOTE: '+patch['note']+'\n') + sys.stderr.write(separator) + +# read the current include file, if any +incfile = patchdir + 'patch_state.h' +if nopatch: + incnew = """// This file is generated by the patch tool and should not be edited manually. +#ifndef _PATCH_STATE_H +#define _PATCH_STATE_H +// No patches have been applied to the Chromium/WebKit source base. +#define CEF_PATCHES_APPLIED 0 +#endif // _PATCH_STATE_H +""" +else: + incnew = """// This file is generated by the patch tool and should not be edited manually. +#ifndef _PATCH_STATE_H +#define _PATCH_STATE_H +// Patches have been applied to the Chromium/WebKit source base. +#define CEF_PATCHES_APPLIED 1 +#endif // _PATCH_STATE_H +""" + +inccur = '' +if os.path.isfile(incfile): + inccur = read_file(incfile) + +if inccur != incnew: + sys.stdout.write('Writing file '+incfile+'.\n') + write_file(incfile, incnew) \ No newline at end of file diff --git a/tools/repack_locales.py b/tools/repack_locales.py new file mode 100644 index 000000000..890400035 --- /dev/null +++ b/tools/repack_locales.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# 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. + +"""Helper script to repack paks for a list of locales. + +Gyp doesn't have any built-in looping capability, so this just provides a way to +loop over a list of locales when repacking pak files, thus avoiding a +proliferation of mostly duplicate, cut-n-paste gyp actions. +""" + +import getopt +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', + 'tools', 'grit')) +from grit.format import data_pack + +# Some build paths defined by gyp. +GRIT_DIR = None +SHARE_INT_DIR = None +INT_DIR = None + + +class Usage(Exception): + def __init__(self, msg): + self.msg = msg + + +def calc_output(locale, create_dir): + """Determine the file that will be generated for the given locale.""" + #e.g. '<(INTERMEDIATE_DIR)/da.pak', + # For Fake Bidi, generate it at a fixed path so that tests can safely + # reference it. + if locale == 'fake-bidi': + return '%s/%s.pak' % (INT_DIR, locale) + if sys.platform in ('darwin',): + # For Cocoa to find the locale at runtime, it needs to use '_' instead + # of '-' (http://crbug.com/20441). Also, 'en-US' should be represented + # simply as 'en' (http://crbug.com/19165, http://crbug.com/25578). + if locale == 'en-US': + locale = 'en' + dir = '%s/%s.lproj' % (INT_DIR, locale.replace('-', '_')) + if create_dir and not os.path.exists(dir): + os.makedirs(dir) + return dir + '/locale.pak' + else: + return os.path.join(INT_DIR, locale + '.pak') + + +def calc_inputs(locale): + """Determine the files that need processing for the given locale.""" + inputs = [] + + #e.g. '<(grit_out_dir)/generated_resources_da.pak' + #inputs.append(os.path.join(GRIT_DIR, 'generated_resources_%s.pak' % locale)) + + #e.g. '<(grit_out_dir)/locale_settings_da.pak' + #inputs.append(os.path.join(GRIT_DIR, 'locale_settings_%s.pak' % locale)) + + #e.g. '<(grit_out_dir)/platform_locale_settings_da.pak' + #inputs.append(os.path.join(GRIT_DIR, + # 'platform_locale_settings_%s.pak' % locale)) + + #e.g. '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_da.pak' + inputs.append(os.path.join(SHARE_INT_DIR, 'webkit', + 'webkit_strings_%s.pak' % locale)) + + #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings_da.pak', + inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'ui_strings', + 'ui_strings_%s.pak' % locale)) + + #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/app_locale_settings_da.pak', + inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'app_locale_settings', + 'app_locale_settings_%s.pak' % locale)) + + #e.g. '<(SHARED_INTERMEDIATE_DIR)/cef/cef_strings_da.pak' + inputs.append(os.path.join(SHARE_INT_DIR, 'cef', + 'cef_strings_%s.pak' % locale)) + + return inputs + + +def list_outputs(locales): + """Returns the names of files that will be generated for the given locales. + + This is to provide gyp the list of output files, so build targets can + properly track what needs to be built. + """ + outputs = [] + for locale in locales: + outputs.append(calc_output(locale, False)) + # Quote each element so filename spaces don't mess up gyp's attempt to parse + # it into a list. + return " ".join(['"%s"' % x for x in outputs]) + + +def list_inputs(locales): + """Returns the names of files that will be processed for the given locales. + + This is to provide gyp the list of input files, so build targets can properly + track their prerequisites. + """ + inputs = [] + for locale in locales: + inputs += calc_inputs(locale) + # Quote each element so filename spaces don't mess up gyp's attempt to parse + # it into a list. + return " ".join(['"%s"' % x for x in inputs]) + + +def repack_locales(locales): + """ Loop over and repack the given locales.""" + for locale in locales: + inputs = [] + inputs += calc_inputs(locale) + output = calc_output(locale, True) + data_pack.DataPack.RePack(output, inputs) + + +def DoMain(argv): + global GRIT_DIR + global SHARE_INT_DIR + global INT_DIR + + short_options = 'iog:s:x:b:h' + long_options = 'help' + + print_inputs = False + print_outputs = False + usage_msg = '' + + helpstr = """\ +Usage: %s [-h] [-i | -o] -g -x -s [...] + -h, --help Print this help, then exit. + -i Print the expected input file list, then exit. + -o Print the expected output file list, then exit. + -g DIR GRIT build files output directory. + -x DIR Intermediate build files output directory. + -s DIR Shared intermediate build files output directory. + locale [...] One or more locales to repack.""" % ( + os.path.basename(__file__)) + + try: + opts, locales = getopt.getopt(argv, short_options, long_options) + except getopt.GetoptError, msg: + raise Usage(str(msg)) + + if not locales: + usage_msg = 'Please specificy at least one locale to process.\n' + + for o, a in opts: + if o in ('-i'): + print_inputs = True + elif o in ('-o'): + print_outputs = True + elif o in ('-g'): + GRIT_DIR = a + elif o in ('-s'): + SHARE_INT_DIR = a + elif o in ('-x'): + INT_DIR = a + elif o in ('-h', '--help'): + raise Usage(helpstr) + + if not (GRIT_DIR and INT_DIR and SHARE_INT_DIR): + usage_msg += 'Please specify all of "-g" and "-x" and "-s".\n' + if print_inputs and print_outputs: + usage_msg += 'Please specify only one of "-i" or "-o".\n' + + if usage_msg: + raise Usage(usage_msg) + + if print_inputs: + return list_inputs(locales) + + if print_outputs: + return list_outputs(locales) + + if not os.path.exists(INT_DIR): + os.makedirs(INT_DIR) + + return repack_locales(locales) + +if __name__ == '__main__': + results = DoMain(sys.argv[1:]) + if results: + print results diff --git a/tools/revision.py b/tools/revision.py new file mode 100644 index 000000000..1d946029f --- /dev/null +++ b/tools/revision.py @@ -0,0 +1,22 @@ +# 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. + +import svn_util as svn +import git_util as git +import os +import sys + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +if os.path.exists(os.path.join('.', '.svn')): + sys.stdout.write(svn.get_revision()) +elif os.path.exists(os.path.join('.', '.git')): + sys.stdout.write(git.get_svn_revision()) +else: + raise Exception('Not a valid checkout') + + diff --git a/tools/svn_util.py b/tools/svn_util.py new file mode 100644 index 000000000..a0d00337a --- /dev/null +++ b/tools/svn_util.py @@ -0,0 +1,60 @@ +# 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 + +from exec_util import exec_cmd +import os +import urllib +import xml.etree.ElementTree as ET + +def is_checkout(path): + """ Returns true if the path represents an svn checkout. """ + return os.path.exists(os.path.join(path, '.svn')) + +def check_url(url): + """ Check the URL and raise an exception if invalid. """ + if ':' in url[:7]: + parts = url.split(':', 1) + if (parts[0] == 'http' or parts[0] == 'https' or parts[0] == 'svn') and \ + parts[1] == urllib.quote(parts[1]): + return url + raise Exception('Invalid URL: %s' % (url)) + +def get_svn_info(path = '.'): + """ Retrieves the URL and revision from svn info. """ + url = 'None' + rev = 'None' + cmd = "svn info --xml %s" % (path) + is_http = path[0:4] == 'http' + if is_http or os.path.exists(path): + result = exec_cmd(cmd, path if not is_http else '.') + if result['err'] == '': + tree = ET.ElementTree(ET.fromstring(result['out'])) + entry = tree.getroot().find('entry') + url = entry.find('url').text + rev = entry.attrib['revision'] + else: + raise Exception("Failed to execute svn info: %s" % (result['err'])) + return {'url': url, 'revision': rev} + +def get_revision(path = '.'): + """ Retrieves the revision from svn info. """ + info = get_svn_info(path) + if info['revision'] == 'None': + raise Exception('Unable to retrieve SVN revision for %s' % (path)) + return info['revision'] + +def get_changed_files(path = '.'): + """ Retrieves the list of changed files from svn status. """ + files = [] + if os.path.exists(path): + try: + stream = os.popen('svn status '+path) + for line in stream: + status = line[0] + # Return paths with add, modify and switch status. + if status == 'A' or status == 'M' or status == 'S': + files.append(line[8:].strip()) + except IOError, (errno, strerror): + raise + return files diff --git a/tools/translator.README.txt b/tools/translator.README.txt new file mode 100644 index 000000000..2be478f36 --- /dev/null +++ b/tools/translator.README.txt @@ -0,0 +1,1697 @@ +Chromium Embedded Framework (CEF) Translator Tool -- translator.py +------------------------------------------------------------------------------- + +Document Last Updated: February 14, 2012 + + +OVERVIEW +-------- + +The CEF translator tool automatically generates CEF source code based on the +contents of the CEF header file (cef.h). The generated source code includes the +main C API header file (cef_capi.h) and all files in the libcef_dll/cpptoc and +libcef_dll/ctocpp directories. + +If any differences are detected between the new translator-generated output and +the file that currently exists on disk a backup of the existing file will be +created before the new file is written (this behavior can be controlled using +a command-line switch -- see 'translator.py -h' for more information). Header +files (*.h) are completely generated by the translator and should never be +edited by hand. Implementation files (*.cc) may contain user-created content +within method and function body blocks. The user-created content is extracted +from the existing file and inserted into the new translator-generated file. Any +differences between existing method/function prototypes and new method/function +prototypes in manually edited implementations will be noted as a warning in new +output file. + + // WARNING - CHANGED ATTRIBUTES + // REMOVED: const wchar_t* key + // ADDED: int index + // WARNING - CHANGED RETURN VALUE + // WAS: void + // NOW: int + #pragma message("Warning: "__FILE__": MyFunction prototype has changed") + +Auto-generated implementations will be added in the new output file for any +methods/functions that exist in the CEF header file but did not exist in the +current on-disk implementation file. Each time the translator re-generates the +implementation file it will warn if an implementation could not be auto- +generated. Delete the indicated portion of the generated code after adding the +implementation manually. + + size_t CEF_CALLBACK frame_new_func(struct _cef_frame_t* self) + { + // BEGIN DELETE BEFORE MODIFYING + // AUTO-GENERATED CONTENT + #pragma message("Warning: "__FILE__": frame_new_func is not implemented") + // END DELETE BEFORE MODIFYING + } + +If the complete function or method implementation has been auto-generated the +body of the function or method will contain the following comment. + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + +If you edit the implementation manually you should remove this comment so that +CEF will not discard your changes on the next run of the translator tool. + +The 'translator.[bat|sh]' file can be used to run the translator tool with +command- line arguments that match the default CEF directory structure and +output options. Run 'translator.py -h' for a complete list of available command- +line arguments. + + +HEADER ATTRIBUTES +----------------- + +Comment-based attribute tags are added before each function, class and method +definition in the CEF header file to provide the translator with additional +information about how the output should be generated. The attribute tags must +be in the form of a comma-delimited list of name=value pairs. Attribute names +and values must contain only alpha-numeric characters, numbers and underscores, +and must all exist on a single line. + + /*--cef(name1=value1,name2=value2,name3=value3)--*/ + +Supported method/function attributes: + + capi_name=[string] (Optional) Force a specific output name for the + resulting C API function. + optional_param=[param] (Optional) Parameter name that will be optional + instead of required. + index_param=[param] (Optional) Parameter name representing an index + value that will be verified as >= 0. + default_retval=[string] (Required for enumeration types, Optional for other + types) Specify the default return value. + count_func=[param:func] (Required for non-const non-string std::vector + types) Specify the C++ function that returns the + count of elements for a vector parameter. + api_hash_check (Optional) If set an API hash check will be added + to the CToCpp version of the method/function. + +Supported class attributes: + + source=[library|client] (Required) Indicates whether the class + implementation is provided by the library or the + client. This effects the generation of guard + blocks in the cpptoc and ctocpp header files. + no_debugct_check (Optional) If set the debug reference count + of the object will not be checked on shutdown. + + +TRANSLATION RULES +----------------- + +All C++ names in the CEF header file are written in CamelCaps format and all +C API translations are generated in lowercase_underscore format. + + +Translating Classes and Methods +------------------------------- + +Class names and global function names must be prefixed with the 'Cef' string. + + Global function translation + C++: void CefShutdown() + C API: void cef_shutdown() + +The translation of a C++ class name to a C API structure name is prefixed with +'_' and postfixed with '_t'. A typedef of the C API structure to a value +without the prefixed '_' is also provided and may be used interchangeably. + + Class name translation + C++: class CefPostData + C API: typedef struct _cef_post_data_t { ... } cef_post_data_t + +The translation of a C++ virtual class method to a C API member function adds a +'self' structure pointer as the first parameter. This will always be a pointer +to the structure that contains the member function. + + Virtual method translation + C++: virtual void SetFocus(bool enable) + C API: void set_focus(struct _cef_browser_t* self, int enable) + +The translation of a C++ static class method to a C API global function +is prefixed with 'cef_classname_' where 'classname' is the +lowercase_underscore name of the class that contains the static method. Any +repeat of 'classname' in the function name is removed. + + Static method translation + C++: static CefRefPtr CreateRequest() + C API: struct _cef_request_t* cef_request_create() + +Implementation of the wrapper method/function body is generally formatted as +follows. + + Static/Global CppToC (without Return): + + CEF_EXPORT void cef_function(capi_params) + { + // Parameter Verification (Optional) + // Verify the C parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C parameter values to C++ parameter values. + // ... + + // Execution + CefFunction(cpp_arams); + + // Parameter Restoration (Optional) + // Retore the C parameter values if changed. + // ... + } + + Static/Global CppToC (with Return): + + CEF_EXPORT capi_retval cef_function(capi_params) + { + // Parameter Verification (Optional) + // Verify the C parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C parameter values to C++ parameter values. + // ... + + // Execution + cpp_retval _rv = CefFunction(cpp_params); + + // Parameter Restoration (Optional) + // Restore the C parameter values if changed. + // ... + + // Return Translation + // Convert the C++ return value to a C return value. + return ...; + } + + Static/Global CToCpp (without Return): + + void CefFunction(cpp_params) + { + // Parameter Verification (Optional) + // Verify the C++ parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C++ parameter values to C parameter values. + // ... + + // Execution + cef_function(capi_params); + + // Parameter Restoration (Optional) + // Restore the C++ parameter values if changed. + // ... + } + + Static/Global CToCpp (with Return): + + cpp_retval CefFunction(cpp_params) + { + // Parameter Verification (Optional) + // Verify the C++ parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C++ parameter values to C parameter values. + // ... + + // Execution + capi_retval _rv = cef_function(capi_params); + + // Parameter Restoration (Optional) + // Restore the C++ parameter values if changed. + // ... + + // Return Translation + // Convert the C return value to a C++ return value. + return ...; + } + + Member CppToC (without Return): + + CEF_CALLBACK void class_function(cef_class_t* self, capi_params) + { + // Parameter Verification. + // Verify the C parameter values. + DCHECK(self); + DCHECK(...); + if (!self || ...) + return; + + // Parameter Translation (Optional) + // Convert the C parameter values to C++ parameter values. + // ... + + // Execution + CefClassCppToC::Get(self)->CefFunction(cpp_params); + + // Parameter Restoration (Optional) + // Restore the C parameter values if changed. + // ... + } + + Member CppToC (with Return): + + CEF_CALLBACK capi_retval class_function(cef_class_t* self, capi_params) + { + // Parameter Verification. + // Verify the C parameter values. + DCHECK(self); + DCHECK(...); + if (!self || ...) + return default_retval; // Configured or defaulted automatically. + + // Parameter Translation (Optional) + // Convert the C parameter values to C++ parameter values. + // ... + + // Execution + cpp_retval _rv = CefClassCppToC::Get(self)->CefFunction(cpp_params); + + // Parameter Restoration (Optional) + // Restore the C parameter values if changed. + // ... + + // Return Translation + // Convert the C++ return value to a C return value. + return ...; + } + + Member CToCpp (without Return): + + void CefClassCToCpp::Function(cpp_params) + { + // Structure Verification + if (CEF_MEMBER_MISSING(struct_, function)) + return; + + // Parameter Verification (Optional) + // Verify the C++ parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C++ parameter values to C parameter values. + // ... + + // Execution + struct_->class_function(struct_, capi_params); + + // Parameter Restoration (Optional) + // Restore the C++ parameter values if changed. + // ... + } + + Member CToCpp (with Return): + + cpp_retval CefClassCToCpp::Function(cpp_params) + { + // Structure Verification + if (CEF_MEMBER_MISSING(struct_, function)) + return default_retval; // Configured or defaulted automatically. + + // Parameter Verification (Optional) + // Verify the C++ parameter values. + // ... + + // Parameter Translation (Optional) + // Convert C++ parameter values to C parameter values. + // ... + + // Execution + capi_retval _rv = struct_->class_function(struct_, capi_params); + + // Parameter Restoration (Optional) + // Restore the C++ parameter values if changed. + // ... + + // Return Translation + // Convert the C return value to a C++ return value. + return ...; + } + + +Translating Data Types +---------------------- + +Data types that are available in both C++ and C are left unchanged. This +includes the 'double', 'int', 'long', 'size_t' and 'void' basic types. Other +data types have differing levels of support as indicated below. The translation +tool will terminate with an exception if it encounters a data type that it +cannot translate. + +Parameters: + + Simple/enumeration type by value (simple_byval): + C++: int value + C API: int value + + // CppToC Example + CEF_EXPORT void cef_function(int value) + { + // Execution + CefFunction(value); + } + + // CToCpp Example + void CefFunction(int value) + { + // Execution + cef_function(value); + } + + Simple/enumeration type by reference (simple_byref): + C++: int& value + C API: int* value + + // CppToC Example + CEF_EXPORT void cef_function(int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + int valueVal = value?*value:0; + + // Execution + CefFunction(valueVal); + + // Parameter Restoration + if (value) + *value = valueVal; + } + + // CToCpp Example + void CefFunction(int& value) + { + // Execution + cef_function(&value); + } + + Simple/enumeration const type by reference (simple_byref_const): + C++: const int& value + C API: const int* value + + // CppToC Example + CEF_EXPORT void cef_function(const int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + int valueVal = value?*value:0; + + // Execution + CefFunction(valueVal); + } + + // CToCpp Example + void CefFunction(const int& value) + { + // Execution + cef_function(&value); + } + + Simple/enumeration type by address (simple_byaddr): + C++: int* value + C API: int* value + + // CppToC Example + CEF_EXPORT void cef_function(int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Execution + CefFunction(value); + } + + // CToCpp Example + void CefFunction(int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Execution + cef_function(value); + } + + Boolean type by value (bool_byval): + C++: bool value + C API: int value + + // CppToC Example + CEF_EXPORT void cef_function(int value) + { + // Execution + CefFunction(value?true:false); + } + + // CToCpp Example + void CefFunction(bool value) + { + // Execution + cef_function(value); + } + + Boolean type by reference (bool_byref): + C++: bool& value + C API: int* value + + // CppToC Example + CEF_EXPORT void cef_function(int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + bool valueBool = (value && *value)?true:false; + + // Execution + CefFunction(valueBool); + + // Parameter Restoration + if (value) + *value = valueBool?true:false; + } + + // CToCpp Example + void CefFunction(bool& value) + { + // Parameter Translation + int valueInt = value; + + // Execution + cef_function(&valueInt); + + // Parameter Restoration + value = valueInt?true:false; + } + + Boolean type by address (bool_byaddr): + C++: bool* value + C API: int* value + + // CppToC Example + CEF_EXPORT void cef_function(int* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + bool valueBool = (value && *value)?true:false; + + // Execution + CefFunction(&valueBool); + + // Parameter Restoration + if (value) + *value = valueBool?true:false; + } + + // CToCpp Example + void CefFunction(bool* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + int valueInt = value?*value:0; + + // Execution + cef_function(&valueInt); + + // Parameter Restoration + if (value) + *value = valueInt?true:false; + } + + Structure const type by reference (struct_byref_const): + C++: const CefPopupFeatures& value + C API: const cef_popup_features_t* value + + // CppToC Example + CEF_EXPORT void cef_function(const cef_popup_features_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + CefPopupFeatures valueObj; + // Reference the existing values instead of copying. + if (value) + valueObj.Set(*value, false); + + // Execution + CefFunction(valueObj); + } + + // CToCpp Example + void CefFunction(const CefPopupFeatures& value) + { + // Execution + cef_function(&value); + } + + Structure non-const type by reference (struct_byref): + C++: CefWindowInfo& value + C API: cef_window_info_t* value + + // CppToC Example + CEF_EXPORT void cef_function(cef_window_info_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + CefWindowInfo valueObj; + // Take ownership of the values. + if (value) + valueObj.AttachTo(*value); + + // Execution + CefFunction(valueObj); + + // Parameter Restoration + // Return the values to the structure. + if (value) + valueObj.DetachTo(*value); + } + + // CToCpp Example + void CefFunction(CefWindowInfo& value) + { + // Execution + cef_function(&value); + } + + String const type by reference (string_byref_const): + C++: const CefString& value + C API: const cef_string_t* value + + // CppToC Example + CEF_EXPORT void cef_function(const cef_string_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Execution + CefFunction(CefString(value)); + } + + // CToCpp Example + void CefFunction(const CefString& value) + { + // Execution + cef_function(value.GetStruct()); + } + + String non-const type by reference (string_byref): + C++: CefString& value + C API: cef_string_t* value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + CefString valueStr(value); + + // Execution + CefFunction(valueStr); + } + + // CToCpp Example + void CefFunction(CefString& value) + { + // Execution + cef_function(value.GetWritableStruct()); + } + + Smart pointer type same boundary side (refptr_same): + C++: CefRefPtr value + C API: cef_browser_t* value + + // CppToC Example + CEF_EXPORT void cef_function(cef_browser_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Execution + CefFunction(CefBrowserCppToC::Unwrap(value)); + } + + // CToCpp Example + void CefFunction(CefRefPtr value) + { + // Execution + cef_function(CefBrowserCToCpp::Unwrap(value)); + } + + Smart pointer type same boundary side by reference (refptr_same_byref): + C++: CefRefPtr& value + C API: cef_client_t** value + + // CppToC Example + CEF_EXPORT void cef_function(cef_client_t** value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + CefRefPtr valuePtr; + if (value && *value) + valuePtr = CefClientCppToC::Unwrap(*value); + CefClient* valueOrig = valuePtr.get(); + + // Execution + CefFunction(valuePtr); + + // Parameter Restoration + if (value) { + if (valuePtr.get()) { + if (valuePtr.get() != valueOrig) { + // The value has been changed. + *value = CefClientCppToC::Wrap(valuePtr); + } + } else { + *value = NULL; + } + } + } + + // CToCpp Example + void CefFunction(CefRefPtr& value) + { + // Parameter Translation + cef_client_t* valueStruct = NULL; + if(value.get()) + valueStruct = CefClientCToCpp::Unwrap(value); + cef_client_t* valueOrig = valueStruct; + + // Execution + cef_function(valueStuct); + + // Parameter Restoration + if (valueStruct) { + if (valueStruct != valueOrig) { + // The value was changed. + value = CefClientCToCpp::Wrap(valueStruct); + } + } else { + value = NULL; + } + } + + Smart pointer type different boundary side (refptr_diff): + C++: CefRefPtr value + C API: cef_browser_t* value + + // CppToC Example + CEF_EXPORT void cef_function(cef_browser_t* value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Execution + CefFunction(CefBrowserCToCpp::Wrap(value)); + } + + // CToCpp Example + void CefFunction(CefRefPtr value) + { + // Execution + cef_function(CefBrowserCppToC::Wrap(value)); + } + + Smart pointer type different boundary side by reference (refptr_diff_byref): + C++: CefRefPtr& value + C API: cef_client_t** value + + // CppToC Example + CEF_EXPORT void cef_function(cef_client_t** value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + CefRefPtr valuePtr; + if (value && *value) + valuePtr = CefClientCToCpp::Wrap(*value); + CefClient* valueOrig = valuePtr.get(); + + // Execution + CefFunction(valuePtr); + + // Parameter Restoration + if (value) { + if (valuePtr.get()) { + if (valuePtr.get() != valueOrig) { + // The value has been changed. + *value = CefClientCToCpp::Unwrap(valuePtr); + } + } else { + *value = NULL; + } + } + } + + // CToCpp Example + void CefFunction(CefRefPtr& value) + { + // Parameter Translation + cef_client_t* valueStruct = NULL; + if(value.get()) + valueStruct = CefClientCppToC::Wrap(value); + cef_client_t* valueOrig = valueStruct; + + // Execution + cef_function(valueStuct); + + // Parameter Restoration + if (valueStruct) { + if (valueStruct != valueOrig) { + // The value was changed. + value = CefClientCppToC::Unwrap(valueStruct); + } + } else { + value = NULL; + } + } + + String vector type by reference (string_vec_byref): + C++: std::vector& value + C API: cef_string_list_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_list_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::vector valueList; + transfer_string_list_contents(value, valueList); + + // Execution + CefFunction(valueList); + + // Parameter Restoration + cef_string_list_clear(value); + transfer_string_list_contents(valueList, value); + } + + // CToCpp Example + void CefFunction(std::vector& value) + { + // Parameter Translation + cef_string_list_t valueList = cef_string_list_alloc(); + DCHECK(valueList); + if (valueList) + transfer_string_list_contents(value, valueList); + + // Execution + cef_function(valueList); + + // Parameter Restoration + if (valueList) { + value.clear(); + transfer_string_list_contents(valueList, value); + cef_string_list_free(valueList); + } + } + + String vector const type by reference (string_vec_byref_const): + C++: const std::vector& value + C API: cef_string_list_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_list_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::vector valueList; + transfer_string_list_contents(value, valueList); + + // Execution + CefFunction(valueList); + } + + // CToCpp Example + void CefFunction(const std::vector& value) + { + // Parameter Translation + cef_string_list_t valueList = cef_string_list_alloc(); + DCHECK(valueList); + if (valueList) + transfer_string_list_contents(value, valueList); + + // Execution + cef_function(valueList); + + // Parameter Restoration + if (valueList) + cef_string_list_free(valueList); + } + + String-to-string single map type by reference (string_map_single_byref): + C++: std::map& value + C API: cef_string_map_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_map_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::map valueMap; + transfer_string_map_contents(value, valueMap); + + // Execution + CefFunction(valueMap); + + // Parameter Restoration + cef_string_map_clear(value); + transfer_string_map_contents(valueMap, value); + } + + // CToCpp Example + void CefFunction(std::map& value) + { + // Parameter Translation + cef_string_map_t valueMap = cef_string_map_alloc(); + DCHECK(valueMap); + if (valueMap) + transfer_string_map_contents(value, valueMap); + + // Execution + cef_function(valueMap); + + // Parameter Restoration + if (valueMap) { + value.clear(); + transfer_string_map_contents(valueMap, value); + cef_string_map_free(valueMap); + } + } + + String-to-string single map const type by reference + (string_map_single_byref_const): + C++: const std::map& value + C API: cef_string_map_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_map_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::map valueMap; + transfer_string_map_contents(value, valueMap); + + // Execution + CefFunction(valueMap); + } + + // CToCpp Example + void CefFunction(const std::map& value) + { + // Parameter Translation + cef_string_map_t valueMap = cef_string_map_alloc(); + DCHECK(valueMap); + if (valueMap) + transfer_string_map_contents(value, valueMap); + + // Execution + cef_function(valueMap); + + // Parameter Restoration + if (valueMap) + cef_string_map_free(valueMap); + } + + String-to-string multi map type by reference (string_map_multi_byref): + C++: std::multimap& value + C API: cef_string_multimap_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_multimap_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::multimap valueMultimap; + transfer_string_multimap_contents(value, valueMultimap); + + // Execution + CefFunction(valueMultimap); + + // Parameter Restoration + cef_string_multimap_clear(value); + transfer_string_multimap_contents(valueMultimap, value); + } + + // CToCpp Example + void CefFunction(std::multimap& value) + { + // Parameter Translation + cef_string_multimap_t valueMultimap = cef_string_multimap_alloc(); + DCHECK(valueMultimap); + if (valueMultimap) + transfer_string_multimap_contents(value, valueMultimap); + + // Execution + cef_function(valueMultimap); + + // Parameter Restoration + if (valueMultimap) { + value.clear(); + transfer_string_multimap_contents(valueMultimap, value); + cef_string_multimap_free(valueMultimap); + } + } + + String-to-string multi map const type by reference + (string_map_multi_byref_const): + C++: const std::multimap& value + C API: cef_string_multimap_t value + + // CppToC Example + CEF_EXPORT void cef_function(cef_string_multimap_t value) + { + // Parameter Verification + DHECK(value); + if (!value) + return; + + // Parameter Translation + std::multimap valueMultimap; + transfer_string_multimap_contents(value, valueMultimap); + + // Execution + CefFunction(valueMultimap); + } + + // CToCpp Example + void CefFunction(const std::multimap& value) + { + // Parameter Translation + cef_string_multimap_t valueMultimap = cef_string_multimap_alloc(); + DCHECK(valueMultimap); + if (valueMultimap) + transfer_string_multimap_contents(value, valueMultimap); + + // Execution + cef_function(valueMultimap); + + // Parameter Restoration + if (valueMultimap) + cef_string_multimap_free(valueMultimap); + } + + Simple/Enumeration vector non-const type by reference (simple_vec_byref): + C++: std::vector& value + C API: size_t* valueCount, int* value + + // CppToC Example + CEF_EXPORT void cef_function(size_t* valueCount, int* value) + { + // Parameter Verification + DCHECK(valueCount && (*valueCount == 0 || value)); + if (!valueCount || (*valueCount > 0 && !value)) + return; + + // Parameter Translation + std::vector valueList; + if (valueCount && *valueCount > 0 && value) { + for (size_t i = 0; i < *valueCount; ++i) + valueList.push_back(value[i]); + } + + // Execution + CefFunction(valueList); + + // Parameter Restoration + if (valueCount && value) { + *valueCount = std::min(valueList.size(), *valueCount); + if (*valueCount > 0) { + for (size_t i = 0; i < *valueCount; ++i) + value[i] = valueList[i]; + } + } + } + + // CToCpp Example + void CefFunction(std::vector& value) + { + // Parameter Translation + // Function identified by the "count_func" method attribute. + size_t valueSize = value.size(); + size_t valueCount = std::max(GetFunctionCount(), valueSize); + int* valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList); + if (valueList) + memset(valueList, 0, sizeof(int)*valueCount); + if (valueList && valueSize > 0) { + for (size_t i = 0; i < valueSize; ++i) { + valueList[i] = value[i]; + } + } + } + + // Execution + cef_function(&valueCount, valueList); + + // Parameter Restoration + value.clear(); + if (valueCount > 0 && valueList) { + for (size_t i = 0; i < valueCount; ++i) + value.push_back(valueList[i]); + delete [] valueList; + } + } + + Simple/Enumeration vector const type by reference (simple_vec_byref_const): + C++: const std::vector& value + C API: size_t valueCount, int const* value + + // CppToC Example + CEF_EXPORT void cef_function(size_t valueCount, int const* value) + { + // Parameter Verification + DCHECK(valueCount == 0 || value); + if (valueCount > 0 && !value) + return; + + // Parameter Translation + std::vector valueList; + if (valueCount > 0) { + for (size_t i = 0; i < valueCount; ++i) + valueList.push_back(value[i]); + } + + // Execution + CefFunction(valueList); + } + + // CToCpp Example + void CefFunction(const std::vector& value) + { + // Parameter Translation + const size_t valueCount = value.size(); + int* valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList); + if (valueList) { + for (size_t i = 0; i < valueCount; ++i) + valueList[i] = value[i]; + } + } + + // Execution + cef_function(valueCount, valueList); + + // Parameter Restoration + if (valueList) + delete [] valueList; + } + + Boolean vector non-const type by reference (bool_vec_byref): + C++: std::vector& value + C API: size_t* valueCount, int* value + + // CppToC Example + CEF_EXPORT void cef_function(size_t* valueCount, int* value) + { + // Parameter Verification + DCHECK(valueCount && (*valueCount == 0 || value)); + if (!valueCount || (*valueCount > 0 && !value)) + return; + + // Parameter Translation + std::vector valueList; + if (valueCount && *valueCount > 0 && value) { + for (size_t i = 0; i < *valueCount; ++i) + valueList.push_back(value[i]?true:false); + } + + // Execution + CefFunction(valueList); + + // Parameter Restoration + if (valueCount && value) { + *valueCount = std::min(valueList.size(), *valueCount); + if (*valueCount > 0) { + for (size_t i = 0; i < *valueCount; ++i) + value[i] = valueList[i]; + } + } + } + + // CToCpp Example + void CefFunction(std::vector& value) + { + // Parameter Translation + // Function identified by the "count_func" method attribute. + size_t valueSize = value.size(); + size_t valueCount = std::max(GetFunctionCount(), valueSize); + int* valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList); + if (valueList) + memset(valueList, 0, sizeof(int)*valueCount); + if (valueList && valueSize > 0) { + for (size_t i = 0; i < valueSize; ++i) { + valueList[i] = value[i]; + } + } + } + + // Execution + cef_function(&valueCount, valueList); + + // Parameter Restoration + value.clear(); + if (valueCount > 0 && valueList) { + for (size_t i = 0; i < valueCount; ++i) + value.push_back(valueList[i]?true:false); + delete [] valueList; + } + } + + Boolean vector const type by reference (bool_vec_byref_const): + C++: const std::vector& value + C API: size_t valueCount, int const* value + + // CppToC Example + CEF_EXPORT void cef_function(size_t valueCount, int const* value) + { + // Parameter Verification + DCHECK(valueCount == 0 || value); + if (valueCount > 0 && !value) + return; + + // Parameter Translation + std::vector valueList; + if (valueCount > 0) { + for (size_t i = 0; i < valueCount; ++i) + valueList.push_back(value[i]?true:false); + } + + // Execution + CefFunction(valueList); + } + + // CToCpp Example + void CefFunction(const std::vector& value) + { + // Parameter Translation + const size_t valueCount = value.size(); + int* valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList) + if (valueList) { + for (size_t i = 0; i < valueCount; ++i) + valueList[i] = value[i]; + } + } + + // Execution + cef_function(valueCount, valueList); + + // Parameter Restoration + if (valueList) + delete [] valueList; + } + + Smart pointer vector non-const type same boundary side by reference + (refptr_vec_same_byref): + C++: std::vector>& value + C API: size_t* valueCount, cef_post_data_element_t** value + + // CppToC Example + CEF_EXPORT void cef_function(size_t* valueCount, + cef_post_data_element_t** value) + { + // Parameter Verification + DCHECK(valueCount && (*valueCount == 0 || value)); + if (!valueCount || (*valueCount > 0 && !value)) + return; + + // Parameter Translation + std::vector> valueList; + if (valueCount && *valueCount > 0 && value) { + for (size_t i = 0; i < *valueCount; ++i) + valueList.push_back(CefPostDataElementCppToC::Unwrap(value[i])); + } + + // Execution + CefFunction(valueList); + + // Parameter Restoration + if (valueCount && value) { + *valueCount = std::min(valueList.size(), *valueCount); + if (*valueCount > 0) { + for (size_t i = 0; i < *valueCount; ++i) + value[i] = CefPostDataElementCppToC::Wrap(valueList[i]); + } + } + } + + // CToCpp Example + void CefFunction(std::vector& value) + { + // Parameter Translation + // Function identified by the "count_func" method attribute. + size_t valueSize = value.size(); + size_t valueCount = std::max(GetFunctionCount(), valueSize); + cef_post_data_element_t** valueList = NULL; + if (valueCount > 0) { + valueList = new cef_post_data_element_t*[valueCount]; + DCHECK(valueList); + if (valueList) + memset(valueList, 0, sizeof(cef_post_data_element_t*)*valueCount); + if (valueList && valueSize > 0) { + for (size_t i = 0; i < valueSize; ++i) { + valueList[i] = CefPostDataElementCToCpp::Unwrap(value[i]); + } + } + } + + // Execution + cef_function(&valueCount, valueList); + + // Parameter Restoration + value.clear(); + if (valueCount > 0 && valueList) { + for (size_t i = 0; i < valueCount; ++i) + value.push_back(CefPostDataElementCToCpp::Wrap(valueList[i])); + delete [] valueList; + } + } + + Smart pointer vector const type same boundary side by reference + (refptr_vec_same_byref_const): + C++: const std::vector>& value + C API: size_t valueCount, const cef_v8value_t** value + + // CppToC Example + CEF_EXPORT void cef_function(size_t valueCount, + const cef_v8value_t** value) + { + // Parameter Verification + DCHECK(valueCount == 0 || value); + if (valueCount > 0 && !value) + return; + + // Parameter Translation + std::vector> valueList; + if (valueCount > 0) { + for (size_t i = 0; i < valueCount; ++i) + valueList.push_back(CefV8ValueCppToC::Unwrap(value[i])); + } + + // Execution + CefFunction(valueList); + } + + // CToCpp Example + void CefFunction(const std::vector& value) + { + // Parameter Translation + const size_t valueCount = value.size(); + cef_v8value_t** valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList); + if (valueList) { + for (size_t i = 0; i < valueCount; ++i) + valueList[i] = CefV8ValueCToCpp::Unwrap(value[i]); + } + } + + // Execution + cef_function(valueCount, valueList); + + // Parameter Restoration + if (valueList) + delete [] valueList; + } + + Smart pointer vector non-const type different boundary side by reference + (refptr_vec_diff_byref): + C++: std::vector>& value + C API: size_t* valueCount, cef_post_data_element_t** value + + // CppToC Example + CEF_EXPORT void cef_function(size_t* valueCount, + cef_post_data_element_t** value) + { + // Parameter Verification + DCHECK(valueCount && (*valueCount == 0 || value)); + if (!valueCount || (*valueCount > 0 && !value)) + return; + + // Parameter Translation + std::vector> valueList; + if (valueCount && *valueCount > 0 && value) { + for (size_t i = 0; i < *valueCount; ++i) + valueList.push_back(CefPostDataElementCToCpp::Wrap(value[i])); + } + + // Execution + CefFunction(valueList); + + // Parameter Restoration + if (valueCount && value) { + *valueCount = std::min(valueList.size(), *valueCount); + if (*valueCount > 0) { + for (size_t i = 0; i < *valueCount; ++i) + value[i] = CefPostDataElementCToCpp::Unwrap(valueList[i]); + } + } + } + + // CToCpp Example + void CefFunction(std::vector& value) + { + // Parameter Translation + // Function identified by the "count_func" method attribute. + size_t valueSize = value.size(); + size_t valueCount = std::max(GetFunctionCount(), valueSize); + cef_post_data_element_t** valueList = NULL; + if (valueCount > 0) { + valueList = new cef_post_data_element_t*[valueCount]; + DCHECK(valueList); + if (valueList) + memset(valueList, 0, sizeof(cef_post_data_element_t*)*valueCount); + if (valueList && valueSize > 0) { + for (size_t i = 0; i < valueSize; ++i) { + valueList[i] = CefPostDataElementCppToC::Wrap(value[i]); + } + } + } + + // Execution + cef_function(&valueCount, valueList); + + // Parameter Restoration + value.clear(); + if (valueCount > 0 && valueList) { + for (size_t i = 0; i < valueCount; ++i) + value.push_back(CefPostDataElementCppToC::Unwrap(valueList[i])); + delete [] valueList; + } + } + + Smart pointer vector const type different boundary side by reference + (refptr_vec_diff_byref_const): + C++: const std::vector>& value + C API: size_t valueCount, const cef_v8value_t** value + + // CppToC Example + CEF_EXPORT void cef_function(size_t valueCount, + const cef_v8value_t** value) + { + // Parameter Verification + DCHECK(valueCount == 0 || value); + if (valueCount > 0 && !value) + return; + + // Parameter Translation + std::vector> valueList; + if (valueCount > 0) { + for (size_t i = 0; i < valueCount; ++i) + valueList.push_back(CefV8ValueCToCpp::Wrap(value[i])); + } + + // Execution + CefFunction(valueList); + } + + // CToCpp Example + void CefFunction(const std::vector& value) + { + // Parameter Translation + const size_t valueCount = value.size(); + cef_v8value_t** valueList = NULL; + if (valueCount > 0) { + valueList = new int[valueCount]; + DCHECK(valueList); + if (valueList) { + for (size_t i = 0; i < valueCount; ++i) + valueList[i] = CefV8ValueCppToC::Wrap(value[i]); + } + } + + // Execution + cef_function(valueCount, valueList); + + // Parameter Restoration + if (valueList) + delete [] valueList; + } + +Return Values: + + Simple/Enumeration type (simple): + C++: int + C API: int + + // CppToC Example + CEF_EXPORT int cef_function() + { + // Execution + int _rv = CefFunction(); + + // Return Translation + return _rv; + } + + // CToCpp Example + int CefFunction() + { + // Execution + int _rv = cef_function(); + + // Return Translation + return _rv; + } + + Boolean type (bool): + C++: bool + C API: int + + // CppToC Example + CEF_EXPORT int cef_function() + { + // Execution + bool _rv = CefFunction(); + + // Return Translation + return _rv; + } + + // CToCpp Example + bool CefFunction() + { + // Execution + int _rv = cef_function(); + + // Return Translation + return _rv?true:false; + } + + String non-const by reference type (string): + C++: CefString + C API: cef_string_userfree_t + + // CppToC Example + CEF_EXPORT cef_string_userfree_t cef_function() + { + // Execution + CefString _rv = CefFunction(); + + // Return Translation + return _rv.DetachToUserFree(); + } + + // CToCpp Example + CefString CefFunction() + { + // Execution + cef_string_userfree_t _rv = cef_function(); + + // Return Translation + CefString _rvStr; + _rvStr.AttachToUserFree(_rv); + return _rvStr; + } + + Smart pointer type same boundary side (refptr_same): + C++: CefRefPtr + C API: cef_browser_t* + + // CppToC Example + CEF_EXPORT cef_browser_t* cef_function() + { + // Execution + CefRefPtr _rv = CefFunction(); + + // Return Translation + return CefBrowserCppToC::Wrap(_rv); + } + + // CToCpp Example + CefString CefFunction() + { + // Execution + cef_browser_t* _rv = cef_function(); + + // Return Translation + return CefBrowserCToCpp::Wrap(_rv); + } + + Smart pointer type different boundary side (refptr_diff): + C++: CefRefPtr + C API: cef_browser_t* + + // CppToC Example + CEF_EXPORT cef_browser_t* cef_function() + { + // Execution + CefRefPtr _rv = CefFunction(); + + // Return Translation + return CefBrowserCToCpp::Unwrap(_rv); + } + + // CToCpp Example + CefString CefFunction() + { + // Execution + cef_browser_t* _rv = cef_function(); + + // Return Translation + return CefBrowserCppToC::Unwrap(_rv); + } + + +Translating Comments +-------------------- + +Comments from the CEF header file are reproduced in the C API header file with +any referenced C++ types and terminology changed to reflect C API types and +terminology. + +C++: +// Create a new CefV8Value object of the specified type. These methods +// should only be called from within the JavaScript context -- either in a +// CefV8Handler::Execute() callback or a CefHandler::HandleJSBinding() +// callback. + +C API: +// Create a new cef_v8value_t object of the specified type. These functions +// should only be called from within the JavaScript context -- either in a +// cef_v8handler_t::execute() callback or a cef_handler_t::handle_jsbinding() +// callback. + +Situations where the user is responsible for freeing strings allocated and +returned by the library are also noted by comments in the C API header file. + +C API: + // The resulting string must be freed by calling cef_string_free(). + +A comment must occur immediately before the function, class or method that it +documents with no extra space in between. Comments may span multiple lines +but each line must start with the '//' comment identifier. + +C++: + // Set focus for the browser window. If |enable| is true focus will be set + // to the window. Otherwise, focus will be removed. + /*--cef()--*/ + virtual void SetFocus(bool enable) =0; + +If two comments are separated by an empty line it will be assumed that the +higher comment represents a section header and additional space will be added +before it in the translated output. + +C++: + // ARRAY METHODS - These methods are only available on arrays. + + // Returns the number of elements in the array. + /*--cef()--*/ + virtual int GetArrayLength() =0; + +Empty lines and lines with the comment identifier but no content are considered +paragraph breaks for the purposes of wrapping the translated text. Any content +indented more than one space is reproduced as-is without content translation +or wrapping. + +C++: +// Register a new V8 extension with the specified JavaScript extension code and +// handler. Functions implemented by the handler are prototyped using the +// keyword 'native'. The calling of a native function is restricted to the scope +// in which the prototype of the native function is defined. +// +// Example JavaScript extension code: +// +// // create the 'example' global object if it doesn't already exist. +// if (!example) +// example = {}; diff --git a/tools/translator.bat b/tools/translator.bat new file mode 100644 index 000000000..4e5d7727f --- /dev/null +++ b/tools/translator.bat @@ -0,0 +1,3 @@ +@echo off +call python.bat translator.py --cpp-header-dir ..\include --capi-header-dir ..\include\capi --cpptoc-global-impl ..\libcef_dll\libcef_dll.cc --ctocpp-global-impl ..\libcef_dll\wrapper\libcef_dll_wrapper.cc --cpptoc-dir ..\libcef_dll\cpptoc --ctocpp-dir ..\libcef_dll\ctocpp --gypi-file ..\cef_paths.gypi +pause \ No newline at end of file diff --git a/tools/translator.py b/tools/translator.py new file mode 100644 index 000000000..b587cf914 --- /dev/null +++ b/tools/translator.py @@ -0,0 +1,164 @@ +# 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. + +import sys +from cef_parser import * +from make_capi_header import * +from make_cpptoc_header import * +from make_cpptoc_impl import * +from make_ctocpp_header import * +from make_ctocpp_impl import * +from make_gypi_file import * +from optparse import OptionParser + + +# cannot be loaded as a module +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + + +# parse command-line options +disc = """ +This utility generates files for the CEF C++ to C API translation layer. +""" + +parser = OptionParser(description=disc) +parser.add_option('--cpp-header-dir', dest='cppheaderdir', metavar='DIR', + help='input directory for C++ header files [required]') +parser.add_option('--capi-header-dir', dest='capiheaderdir', metavar='DIR', + help='output directory for C API header files') +parser.add_option('--cpptoc-global-impl', dest='cpptocglobalimpl', metavar='FILE', + help='input/output file for CppToC global translations') +parser.add_option('--ctocpp-global-impl', dest='ctocppglobalimpl', metavar='FILE', + help='input/output file for CppToC global translations') +parser.add_option('--cpptoc-dir', dest='cpptocdir', metavar='DIR', + help='input/output directory for CppToC class translations') +parser.add_option('--ctocpp-dir', dest='ctocppdir', metavar='DIR', + help='input/output directory for CppToC class translations') +parser.add_option('--gypi-file', dest='gypifile', metavar='FILE', + help='output file for path information') +parser.add_option('--no-cpptoc-header', + action='store_true', dest='nocpptocheader', default=False, + help='do not output the CppToC headers') +parser.add_option('--no-cpptoc-impl', + action='store_true', dest='nocpptocimpl', default=False, + help='do not output the CppToC implementations') +parser.add_option('--no-ctocpp-header', + action='store_true', dest='noctocppheader', default=False, + help='do not output the CToCpp headers') +parser.add_option('--no-ctocpp-impl', + action='store_true', dest='noctocppimpl', default=False, + help='do not output the CToCpp implementations') +parser.add_option('--no-backup', + action='store_true', dest='nobackup', default=False, + help='do not create a backup of modified files') +parser.add_option('-c', '--classes', dest='classes', action='append', + help='only translate the specified classes') +parser.add_option('-q', '--quiet', + action='store_true', dest='quiet', default=False, + help='do not output detailed status information') +(options, args) = parser.parse_args() + +# the cppheader option is required +if options.cppheaderdir is None: + parser.print_help(sys.stdout) + sys.exit() + +# make sure the header exists +if not path_exists(options.cppheaderdir): + sys.stderr.write('File '+options.cppheaderdir+' does not exist.') + sys.exit() + +# create the header object +if not options.quiet: + sys.stdout.write('Parsing C++ headers from '+options.cppheaderdir+'...\n') +header = obj_header() +excluded_files = ['cef_application_mac.h', 'cef_version.h'] +header.add_directory(options.cppheaderdir, excluded_files) + +writect = 0 + +if not options.capiheaderdir is None: + #output the C API header + if not options.quiet: + sys.stdout.write('In C API header directory '+options.capiheaderdir+'...\n') + filenames = sorted(header.get_file_names()) + for filename in filenames: + if not options.quiet: + sys.stdout.write('Generating '+filename+' C API header...\n') + writect += write_capi_header(header, + os.path.join(options.capiheaderdir, filename), + not options.nobackup) + +# build the list of classes to parse +allclasses = header.get_class_names() +if not options.classes is None: + for cls in options.classes: + if not cls in allclasses: + sys.stderr.write('ERROR: Unknown class: '+cls) + sys.exit() + classes = options.classes +else: + classes = allclasses + +classes = sorted(classes) + +if not options.cpptocglobalimpl is None: + # output CppToC global file + if not options.quiet: + sys.stdout.write('Generating CppToC global implementation...\n') + writect += write_cpptoc_impl(header, None, options.cpptocglobalimpl, \ + not options.nobackup) + +if not options.ctocppglobalimpl is None: + # output CToCpp global file + if not options.quiet: + sys.stdout.write('Generating CToCpp global implementation...\n') + writect += write_ctocpp_impl(header, None, options.ctocppglobalimpl, \ + not options.nobackup) + +if not options.cpptocdir is None: + # output CppToC class files + if not options.quiet: + sys.stdout.write('In CppToC directory '+options.cpptocdir+'...\n') + + for cls in classes: + if not options.nocpptocheader: + if not options.quiet: + sys.stdout.write('Generating '+cls+'CppToC class header...\n') + writect += write_cpptoc_header(header, cls, options.cpptocdir, + not options.nobackup) + if not options.nocpptocimpl: + if not options.quiet: + sys.stdout.write('Generating '+cls+'CppToC class implementation...\n') + writect += write_cpptoc_impl(header, cls, options.cpptocdir, + not options.nobackup) + +if not options.ctocppdir is None: + # output CppToC class files + if not options.quiet: + sys.stdout.write('In CToCpp directory '+options.ctocppdir+'...\n') + for cls in classes: + if not options.nocpptocheader: + if not options.quiet: + sys.stdout.write('Generating '+cls+'CToCpp class header...\n') + writect += write_ctocpp_header(header, cls, options.ctocppdir, + not options.nobackup) + if not options.nocpptocimpl: + if not options.quiet: + sys.stdout.write('Generating '+cls+'CToCpp class implementation...\n') + writect += write_ctocpp_impl(header, cls, options.ctocppdir, + not options.nobackup) + +if not options.gypifile is None: + # output the gypi file + if not options.quiet: + sys.stdout.write('Generating '+options.gypifile+' file...\n') + writect += write_gypi_file(header, options.gypifile, not options.nobackup) + +if not options.quiet: + sys.stdout.write('Done - Wrote '+str(writect)+' files.\n') + + diff --git a/tools/translator.sh b/tools/translator.sh new file mode 100755 index 000000000..abd1c6e91 --- /dev/null +++ b/tools/translator.sh @@ -0,0 +1,2 @@ +#!/bin/sh +python translator.py --cpp-header-dir ../include --capi-header-dir ../include/capi --cpptoc-global-impl ../libcef_dll/libcef_dll.cc --ctocpp-global-impl ../libcef_dll/wrapper/libcef_dll_wrapper.cc --cpptoc-dir ../libcef_dll/cpptoc --ctocpp-dir ../libcef_dll/ctocpp --gypi-file ../cef_paths.gypi