From 4c234327b546dae91badb70a1a6f384c0e607a29 Mon Sep 17 00:00:00 2001 From: chrome-release-bot Date: Mon, 23 Jul 2018 10:05:41 -0700 Subject: [PATCH 1/3] Publish DEPS for 68.0.3440.75 --- DEPS | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/DEPS b/DEPS index d6b65d6fdfa7f..2b667ae8cbac9 100644 --- a/DEPS +++ b/DEPS @@ -37,6 +37,7 @@ gclient_gn_args = [ vars = { + "buildspec_platforms": "win, linux64, mac64, win64", # By default, we should check out everything needed to run on the main # chromium waterfalls. This var can be also be set to "small", in order # to skip things are not strictly needed to build chromium for development @@ -96,11 +97,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'refs/heads/chrome/m68', + 'skia_revision': '7d479192f0bf2a2f0e872d40e3fe3ce9978bf3cc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'refs/heads/6.8-lkgr', + 'v8_revision': '5b8126a8d6fa0c58c89c2d618264ee087d6795a1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -108,11 +109,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'refs/heads/chromium/3440', + 'angle_revision': 'ba16270867793da817417c722abe3a5d98d50fc0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. - 'buildtools_revision': 'refs/heads/chromium/3440', + 'buildtools_revision': '893eb86b02b2571894e328f05551112b96df1cce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -120,7 +121,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'refs/heads/chromium/3440', + 'pdfium_revision': 'a1c1c63d3454e51ec321cdaa6e3420db2ed6c957', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -979,7 +980,7 @@ deps = { Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7c0541da63f571512c49758cbc0767117997a270', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'refs/branch-heads/68', # commit position 21742 + Var('webrtc_git') + '/src.git' + '@' + '350e48ae5ad0e63f9d600dd87cc47799abab5278', # commit position 21742 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1013,7 +1014,7 @@ deps = { Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@refs/heads/chromium/3440', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f7ec728f7bbea50aaa63eeb31e3bedaa10ee6451', 'condition': 'checkout_src_internal', }, From b9056bc842699be921599732db2e76ff2a82701a Mon Sep 17 00:00:00 2001 From: Kevin Fan Date: Wed, 25 Jul 2018 08:14:54 -0600 Subject: [PATCH 2/3] nwjs master --- .gitignore | 2 + BUILD.gn | 1 + DEPS | 15 +- apps/app_lifetime_monitor.cc | 2 + apps/launcher.cc | 7 +- base/BUILD.gn | 2 + base/base_switches.cc | 1 + base/base_switches.h | 1 + base/command_line.cc | 93 +- base/command_line.h | 15 + base/files/file_util_posix.cc | 2 +- base/message_loop/message_loop.cc | 3 + base/message_loop/message_loop.h | 45 +- base/message_loop/message_pump_mac.h | 20 +- base/message_loop/message_pump_mac.mm | 4 + base/message_loop/message_pump_uv.cc | 184 +++ base/message_loop/message_pump_uv.h | 50 + base/message_loop/message_pumpuv_mac.h | 95 ++ base/message_loop/message_pumpuv_mac.mm | 380 +++++ base/native_library_posix.cc | 2 +- base/native_library_win.cc | 85 + base/process/launch_posix.cc | 2 + base/threading/thread_restrictions.h | 8 + build/config/BUILD.gn | 3 + build/config/BUILDCONFIG.gn | 2 + build/config/allocator.gni | 2 +- build/config/chrome_build.gni | 2 +- build/config/compiler/BUILD.gn | 5 +- build/config/compiler/compiler.gni | 6 +- build/config/features.gni | 4 +- build/config/nacl/rules.gni | 7 +- build/dotfile_settings.gni | 1 + build/gyp_chromium.py | 1 - build/toolchain/toolchain.gni | 6 +- build/util/version.gypi | 20 + build/win/reorder-imports.py | 16 +- chrome/BUILD.gn | 170 +- chrome/app/app-Info.plist | 2 +- chrome/app/chrome_crash_reporter_client.cc | 16 +- chrome/app/chrome_crash_reporter_client.h | 5 +- .../app/chrome_crash_reporter_client_win.cc | 8 +- chrome/app/chrome_dll.ver | 4 +- chrome/app/chrome_exe.ver | 4 +- chrome/app/chrome_exe_main_mac.cc | 2 +- chrome/app/chrome_exe_main_win.cc | 11 +- chrome/app/chrome_main.cc | 2 +- chrome/app/chrome_main_delegate.cc | 113 +- chrome/app/chrome_version.rc.version | 5 - chrome/app/chromium_strings.grd | 14 +- chrome/app/framework.order | 261 ++++ chrome/app/main_dll_loader_win.cc | 15 +- chrome/app/nibs/MainMenu.xib | 1378 ++++++++++------- chrome/app/nw.dll.manifest | 8 + chrome/app/nw.exe.manifest | 20 + chrome/app/theme/chromium/BRANDING | 16 +- chrome/app/theme/chromium/mac/app.icns | Bin 111762 -> 378456 bytes chrome/app/theme/chromium/mac/document.icns | Bin 97120 -> 378456 bytes .../app/theme/chromium/product_logo_128.png | Bin 8366 -> 22073 bytes chrome/app/theme/chromium/product_logo_22.png | Bin 1030 -> 1539 bytes .../theme/chromium/product_logo_22_mono.png | Bin 537 -> 1539 bytes chrome/app/theme/chromium/product_logo_24.png | Bin 1022 -> 1728 bytes .../app/theme/chromium/product_logo_256.png | Bin 19849 -> 71833 bytes chrome/app/theme/chromium/product_logo_32.xpm | 563 +++++++ chrome/app/theme/chromium/product_logo_64.png | Bin 3634 -> 7342 bytes chrome/app/theme/chromium/win/chromium.ico | Bin 42219 -> 270398 bytes chrome/app/version_assembly/BUILD.gn | 3 +- .../version_assembly_manifest.template | 2 +- chrome/browser/BUILD.gn | 43 +- chrome/browser/app_controller_mac.mm | 27 +- chrome/browser/apps/app_load_service.cc | 4 + .../apps/app_shim/app_shim_handler_mac.cc | 7 +- .../extension_app_shim_handler_mac.cc | 7 +- .../app_shim/extension_app_shim_handler_mac.h | 2 +- .../browser/apps/app_window_registry_util.cc | 15 +- .../browser/apps/app_window_registry_util.h | 4 +- ...browser_context_keyed_service_factories.cc | 2 +- .../background_application_list_model.cc | 4 +- .../background/background_contents_service.cc | 2 + chrome/browser/browser_process.h | 3 +- chrome/browser/browser_process_impl.cc | 19 +- chrome/browser/browser_process_impl.h | 2 + chrome/browser/browser_resources.grd | 2 + .../chrome_browsing_data_remover_delegate.cc | 5 + chrome/browser/chrome_browser_main.cc | 31 +- chrome/browser/chrome_browser_main_mac.mm | 8 + chrome/browser/chrome_browser_main_win.cc | 4 + .../browser/chrome_content_browser_client.cc | 90 +- .../browser/chrome_content_browser_client.h | 1 + .../chrome_quota_permission_context.cc | 2 +- .../file_type_policies_component_installer.cc | 2 + .../sw_reporter_installer_win.cc | 18 + .../browser/devtools/devtools_ui_bindings.cc | 19 +- chrome/browser/devtools/devtools_window.cc | 37 +- chrome/browser/devtools/devtools_window.h | 16 +- .../chrome_download_manager_delegate.cc | 4 + .../browser/download/download_browsertest.cc | 2 + chrome/browser/download/download_commands.cc | 2 + .../download/download_danger_prompt.cc | 8 +- chrome/browser/download/download_prefs.cc | 7 +- .../download/download_status_updater_mac.mm | 6 +- .../download/download_target_determiner.cc | 5 +- .../download/download_ui_controller.cc | 18 + chrome/browser/extensions/BUILD.gn | 18 +- .../extensions/activity_log/activity_log.cc | 2 +- .../content_settings_store.cc | 16 + .../extensions/api/cookies/cookies_api.cc | 47 + .../desktop_capture/desktop_capture_api.cc | 6 +- .../extensions/api/downloads/downloads_api.cc | 3 + .../language_settings_private_api.cc | 18 +- .../api/preference/preference_api.cc | 6 +- .../api/preference/preference_helpers.cc | 7 +- .../api/tab_capture/tab_capture_api.cc | 19 +- .../api/tab_capture/tab_capture_registry.cc | 12 +- .../browser/extensions/api/tabs/tabs_api.cc | 15 +- .../webstore_private/webstore_private_api.cc | 11 +- ...browser_context_keyed_service_factories.cc | 3 + ...me_component_extension_resource_manager.cc | 4 +- ..._content_browser_client_extensions_part.cc | 15 + .../chrome_content_verifier_delegate.cc | 6 +- .../chrome_content_verifier_delegate.h | 4 +- .../chrome_extension_web_contents_observer.cc | 37 +- .../chrome_extension_web_contents_observer.h | 6 + .../chrome_extensions_browser_client.cc | 3 + .../extensions/chrome_url_request_util.cc | 24 + chrome/browser/extensions/component_loader.cc | 169 +- chrome/browser/extensions/component_loader.h | 26 +- .../extensions/component_loader_unittest.cc | 41 +- .../content_verifier_browsertest.cc | 2 +- chrome/browser/extensions/crx_installer.cc | 4 + .../browser/extensions/extension_service.cc | 34 +- chrome/browser/extensions/extension_service.h | 4 +- .../extensions/extension_system_factory.cc | 2 +- .../extensions/extension_system_impl.cc | 8 +- .../browser/extensions/extension_tab_util.cc | 29 +- .../extension_webkit_preferences.cc | 15 +- .../global_shortcut_listener_win.cc | 2 + .../global_shortcut_listener_x11.cc | 2 + .../scripting_permissions_modifier.cc | 2 +- .../standard_management_policy_provider.cc | 1 + .../extensions/test_extension_system.cc | 2 +- .../extensions/webstore_inline_installer.cc | 7 +- chrome/browser/file_select_helper.cc | 8 +- chrome/browser/file_select_helper.h | 1 + .../chrome_guest_view_manager_delegate.cc | 3 + chrome/browser/io_thread.cc | 17 +- ...hrome_resource_dispatcher_host_delegate.cc | 4 + chrome/browser/mac/master_prefs.mm | 4 +- .../router/media_router_dialog_controller.cc | 4 +- .../presentation_service_delegate_impl.cc | 6 + .../webrtc/desktop_capture_access_handler.cc | 10 +- .../media/webrtc/desktop_streams_registry.cc | 4 +- .../media/webrtc/desktop_streams_registry.h | 3 +- .../webrtc/media_stream_capture_indicator.cc | 2 + .../metrics/chrome_metrics_service_client.cc | 7 + ...ofile_session_durations_service_factory.cc | 3 + .../metrics/extensions_metrics_provider.cc | 1 + chrome/browser/net/predictor.cc | 4 +- .../net/trial_comparison_cert_verifier.cc | 2 + .../notification_platform_bridge_linux.cc | 2 + .../notification_platform_bridge_mac.mm | 3 +- .../platform_notification_service_impl.cc | 2 + chrome/browser/nwjs_resources.grd | 522 +++++++ .../password_manager_util_linux.cc | 2 +- .../permissions/permission_context_base.cc | 10 + .../browser/permissions/permission_manager.cc | 2 + .../plugins/chrome_plugin_service_filter.cc | 2 +- .../browser/plugins/plugin_info_host_impl.cc | 36 +- chrome/browser/plugins/plugin_observer.cc | 2 + chrome/browser/plugins/plugin_utils.cc | 3 +- ...nfiguration_policy_handler_list_factory.cc | 2 + chrome/browser/policy/policy_browsertest.cc | 3 + chrome/browser/prefs/browser_prefs.cc | 6 +- chrome/browser/process_singleton_posix.cc | 78 +- chrome/browser/process_singleton_win.cc | 1 + ...hrome_browser_main_extra_parts_profiles.cc | 6 +- .../profiles/profile_attributes_storage.cc | 4 +- chrome/browser/profiles/profile_impl.cc | 4 +- .../browser/profiles/profile_impl_io_data.cc | 14 + chrome/browser/profiles/profile_io_data.cc | 9 +- .../context_menu_content_type_platform_app.cc | 18 +- .../render_view_context_menu.cc | 31 +- chrome/browser/renderer_preferences_util.cc | 5 + .../component_extension_resources.grd | 8 + chrome/browser/resources/empty.css | 0 chrome/browser/resources/empty.html | 0 chrome/browser/resources/empty.js | 0 chrome/browser/resources/empty.json | 0 chrome/browser/resources/empty.png | 0 chrome/browser/resources/nwjs/default.js | 46 + .../resources/nwjs_default_app/main.js | 7 + .../resources/nwjs_default_app/manifest.json | 17 + .../resources/nwjs_default_app/nw_blank.html | 74 + .../browser/resources/nwjs_newwin_app/main.js | 7 + .../resources/nwjs_newwin_app/manifest.json | 17 + .../resources/nwjs_newwin_app/nw_blank.html | 74 + chrome/browser/resources/pdf/pdf.js | 2 +- .../print_preview/data/destination_store.js | 7 +- .../resources/print_preview/native_layer.js | 1 + .../resources/print_preview/print_preview.js | 4 +- chrome/browser/sessions/session_service.cc | 23 + chrome/browser/shell_integration_linux.cc | 15 + .../spellchecker/spellcheck_factory.cc | 2 +- .../browser/ssl/security_state_tab_helper.cc | 2 + chrome/browser/status_icons/status_icon.h | 4 +- .../chrome_subresource_filter_client.cc | 2 + .../supervised_user_service.cc | 2 + chrome/browser/ui/BUILD.gn | 116 +- chrome/browser/ui/apps/chrome_app_delegate.cc | 50 +- chrome/browser/ui/apps/chrome_app_delegate.h | 1 + .../ui/apps/chrome_app_window_client.cc | 5 +- .../ui/autofill/chrome_autofill_client.cc | 3 + chrome/browser/ui/browser.cc | 21 +- chrome/browser/ui/browser.h | 3 +- chrome/browser/ui/browser_commands.cc | 6 + chrome/browser/ui/browser_list.cc | 3 +- chrome/browser/ui/chrome_bubble_manager.cc | 8 +- chrome/browser/ui/chrome_pages.cc | 10 +- .../apps/app_shim_menu_controller_mac.mm | 87 +- .../ui/cocoa/apps/native_app_window_cocoa.h | 8 + .../ui/cocoa/apps/native_app_window_cocoa.mm | 120 +- .../browser/ui/cocoa/browser_window_cocoa.mm | 4 + .../ui/cocoa/browser_window_controller.mm | 2 + .../download/download_item_controller.mm | 4 + .../location_bar/location_bar_view_mac.mm | 2 + .../chooser_bubble_ui_cocoa.h | 6 + .../chooser_bubble_ui_cocoa.mm | 27 +- .../chooser_bubble_ui_views_mac.mm | 10 +- .../ui/cocoa/status_icons/status_icon_mac.h | 2 +- .../ui/cocoa/status_icons/status_icon_mac.mm | 2 +- chrome/browser/ui/libgtkui/BUILD.gn | 7 +- .../browser/ui/libgtkui/app_indicator_icon.cc | 5 +- .../ui/libgtkui/app_indicator_icon_menu.cc | 2 +- .../libgtkui/select_file_dialog_impl_gtk.cc | 4 +- .../ui/omnibox/chrome_omnibox_client.cc | 4 + .../manage_passwords_ui_controller.cc | 3 +- .../chooser_bubble_delegate.cc | 10 +- .../chooser_bubble_delegate.h | 5 + .../ui/scoped_tabbed_browser_displayer.cc | 2 +- .../ui/signin_view_controller_delegate.cc | 2 + .../ui/startup/startup_browser_creator.cc | 62 +- chrome/browser/ui/tab_helpers.cc | 8 +- .../component_toolbar_actions_factory.cc | 5 +- ...app_window_desktop_window_tree_host_win.cc | 8 + .../apps/chrome_native_app_window_views.cc | 77 +- .../apps/chrome_native_app_window_views.h | 1 + .../apps/glass_app_window_frame_view_win.cc | 13 +- .../autofill/autofill_popup_base_view.cc | 11 +- .../browser/ui/views/chrome_views_delegate.cc | 1 + .../ui/views/chrome_views_delegate_linux.cc | 5 + chrome/browser/ui/views/frame/browser_view.cc | 40 +- .../views/location_bar/location_bar_view.cc | 6 +- .../presentation_receiver_window_view.cc | 2 +- .../ui/views/overlay/overlay_window_views.h | 5 + .../permission_bubble/chooser_bubble_ui.cc | 26 +- .../permission_bubble/chooser_bubble_ui.h | 7 +- .../chooser_bubble_ui_views.cc | 15 +- .../status_icons/status_icon_linux_wrapper.cc | 14 +- .../status_icons/status_icon_linux_wrapper.h | 4 +- .../ui/views/status_icons/status_icon_win.cc | 6 +- .../ui/views/status_icons/status_icon_win.h | 2 +- .../ui/views/status_icons/status_tray_win.cc | 10 +- .../ui/views/status_icons/status_tray_win.h | 5 +- .../browser/ui/views/toolbar/toolbar_view.cc | 2 + .../views/translate/translate_bubble_view.cc | 3 + .../ui/webui/chrome_web_contents_handler.cc | 2 +- .../webui/chrome_web_ui_controller_factory.cc | 57 +- .../media_router/media_router_ui_service.cc | 10 + .../media_router/media_router_ui_service.h | 2 + .../print_preview/pdf_printer_handler.cc | 6 + .../print_preview/print_preview_handler.cc | 93 +- .../print_preview/print_preview_handler.h | 12 + .../print_preview/print_preview_utils.cc | 36 +- .../webui/settings/change_password_handler.cc | 4 + .../ui/webui/settings/md_settings_ui.cc | 2 + .../ui/webui/settings/people_handler.cc | 2 + .../translate_internals_handler.cc | 2 + chrome/browser/web_applications/web_app.cc | 2 +- .../browser/web_applications/web_app_win.cc | 9 +- chrome/browser/win/app_icon.cc | 12 + chrome/chrome_paks.gni | 10 +- chrome/chrome_watcher/BUILD.gn | 1 + chrome/chrome_watcher/chrome_watcher.def | 2 +- chrome/chrome_watcher/chrome_watcher_main.cc | 3 +- chrome/common/BUILD.gn | 7 +- chrome/common/child_process_logging_win.cc | 1 + chrome/common/chrome_constants.cc | 36 +- chrome/common/chrome_content_client.cc | 66 + chrome/common/chrome_content_client.h | 1 + chrome/common/chrome_paths.cc | 2 +- chrome/common/chrome_paths_linux.cc | 4 +- chrome/common/chrome_paths_mac.mm | 8 +- chrome/common/chrome_paths_win.cc | 5 +- chrome/common/extensions/api/BUILD.gn | 1 + .../common/extensions/api/_api_features.json | 11 +- .../extensions/api/_permission_features.json | 32 +- chrome/common/extensions/api/webview_tag.json | 42 + .../extensions/chrome_extensions_client.cc | 7 + chrome/common/extensions/sync_helper.cc | 1 + chrome/common/logging_chrome.cc | 1 + chrome/common/mac/app_mode_chrome_locator.mm | 1 + chrome/common/pepper_flash.cc | 5 +- .../install_static/chromium_install_modes.cc | 8 +- chrome/install_static/install_util.cc | 16 +- chrome/installer/linux/BUILD.gn | 7 +- .../installer/linux/common/installer.include | 6 +- chrome/installer/mini_installer/BUILD.gn | 4 +- .../installer/mini_installer/chrome.release | 104 +- chrome/installer/util/browser_distribution.cc | 4 +- .../installer/util/google_update_settings.cc | 2 +- chrome/installer/util/util_constants.cc | 6 +- chrome/renderer/BUILD.gn | 5 +- .../chrome_content_renderer_client.cc | 31 +- .../renderer/chrome_content_renderer_client.h | 9 + .../renderer/chrome_render_frame_observer.cc | 6 + chrome/renderer/content_settings_observer.cc | 2 +- .../chrome_extensions_renderer_client.cc | 3 + .../extensions/extension_process_policy.cc | 3 + .../extensions/resource_request_policy.cc | 5 +- .../url_loader_throttle_provider_impl.cc | 5 +- chrome/test/BUILD.gn | 18 +- chrome/test/base/testing_browser_process.cc | 2 + chrome/test/base/testing_browser_process.h | 3 + chrome/test/chromedriver/capabilities.cc | 15 + chrome/test/chromedriver/capabilities.h | 2 + .../test/chromedriver/chrome/chrome_finder.cc | 21 +- .../test/chromedriver/chrome/chrome_impl.cc | 19 +- .../chrome/devtools_http_client.cc | 9 + chrome/test/chromedriver/chrome_launcher.cc | 22 +- chrome/tools/build/linux/FILES.cfg | 4 +- chrome/tools/build/win/FILES.cfg | 4 +- .../utility/chrome_content_utility_client.cc | 4 + chrome_elf/BUILD.gn | 1 + chrome_elf/chrome_elf.ver | 4 +- chrome_elf/chrome_elf_main.cc | 23 +- chrome_elf/chrome_elf_main.h | 3 +- chrome_elf/chrome_elf_x64.def | 3 +- chrome_elf/chrome_elf_x86.def | 4 +- .../about_ui/resources/about_credits.tmpl | 1 - .../app_modal/javascript_dialog_manager.cc | 7 +- .../core/browser/autofill_download_manager.cc | 2 +- .../core/browser/content_settings_registry.cc | 4 +- components/cookie_config/cookie_store_util.cc | 9 +- components/cookie_config/cookie_store_util.h | 2 +- .../crash/content/app/breakpad_linux.cc | 21 +- .../content/app/crash_reporter_client.cc | 6 +- .../crash/content/app/crash_reporter_client.h | 10 +- components/crash/content/app/crashpad_mac.mm | 12 +- components/crx_file/id_util.cc | 2 + .../gcm_driver/gcm_channel_status_syncer.cc | 8 +- components/gcm_driver/gcm_driver_desktop.cc | 5 +- .../guest_view/browser/guest_view_manager.cc | 9 +- .../guest_view/browser/guest_view_manager.h | 5 +- .../core/simple_alert_infobar_delegate.cc | 3 + .../keep_alive_registry/keep_alive_registry.h | 2 + components/metrics/metrics_service.cc | 6 +- .../metrics_services_manager.cc | 12 +- components/nacl/features.gni | 5 +- components/nacl/loader/BUILD.gn | 7 + components/nacl/loader/nacl_helper_linux.cc | 6 +- .../sandbox_linux/nacl_sandbox_linux.cc | 2 +- .../nacl/zygote/nacl_fork_delegate_linux.cc | 2 +- .../network_time/network_time_tracker.cc | 2 +- components/os_crypt/keychain_password_mac.mm | 4 +- components/os_crypt/os_crypt_mac.mm | 2 +- .../core/browser/password_manager.cc | 3 + .../payments/content/payment_request.cc | 4 +- components/resources/BUILD.gn | 6 + .../portable_device_watcher_win.cc | 2 +- .../core/language_detection/BUILD.gn | 2 +- .../software_output_device_win.cc | 5 + .../web_data_service_wrapper.cc | 2 + content/BUILD.gn | 2 + content/app/content_main.cc | 2 +- content/app/content_main_runner_impl.cc | 6 +- content/browser/browser_main_loop.cc | 10 +- .../browser_plugin/browser_plugin_guest.cc | 18 + .../child_process_security_policy_impl.cc | 22 +- .../child_process_security_policy_impl.h | 1 + .../browser/devtools/devtools_http_handler.cc | 15 +- .../browser/dom_storage/dom_storage_area.cc | 2 +- .../dom_storage/local_storage_context_mojo.cc | 2 +- .../browser/download/download_request_core.cc | 1 + .../browser/frame_host/ancestor_throttle.cc | 3 + .../frame_host/interstitial_page_impl.cc | 3 + .../frame_host/navigation_controller_impl.cc | 11 +- .../frame_host/navigation_controller_impl.h | 3 +- .../browser/frame_host/navigation_request.cc | 23 +- .../frame_host/navigation_request_info.cc | 6 +- .../frame_host/navigation_request_info.h | 3 +- content/browser/frame_host/navigator_impl.cc | 7 +- .../frame_host/render_frame_host_impl.cc | 22 +- .../frame_host/render_frame_host_impl.h | 8 + .../frame_host/render_frame_host_manager.cc | 18 +- content/browser/gpu/gpu_process_host.cc | 5 +- content/browser/gpu/gpu_process_host.h | 1 + .../loader/resource_dispatcher_host_impl.cc | 2 +- .../renderer_host/render_process_host_impl.cc | 59 +- .../renderer_host/render_process_host_impl.h | 2 + .../render_view_host_delegate.cc | 11 + .../renderer_host/render_view_host_delegate.h | 5 + .../renderer_host/render_view_host_impl.cc | 1 + .../render_widget_host_ns_view_bridge.h | 5 + .../render_widget_host_ns_view_bridge.mm | 24 +- .../render_widget_host_ns_view_client.h | 2 + .../render_widget_host_view_cocoa.mm | 29 + .../render_widget_host_view_mac.h | 4 + .../render_widget_host_view_mac.mm | 18 + .../shared_worker/shared_worker_host.cc | 2 +- .../shared_worker/shared_worker_instance.cc | 5 +- .../shared_worker/shared_worker_instance.h | 8 +- .../shared_worker_service_impl.cc | 2 +- content/browser/site_instance_impl.cc | 8 +- .../browser/web_contents/web_contents_impl.cc | 15 +- .../browser/web_contents/web_contents_impl.h | 2 +- .../browser/webui/url_data_manager_backend.cc | 7 + content/child/child_thread_impl.cc | 2 +- content/common/content_switches_internal.cc | 2 +- content/common/dom_storage/dom_storage_map.cc | 3 + content/common/dom_storage/dom_storage_map.h | 4 +- .../common/dom_storage/dom_storage_types.h | 4 +- content/common/frame.mojom | 5 + content/common/frame_messages.h | 4 + content/common/frame_owner_properties.cc | 3 + content/common/frame_owner_properties.h | 2 + content/common/renderer.mojom | 1 + .../shared_worker/shared_worker_info.mojom | 3 + content/common/user_agent.cc | 10 + content/common/view_messages.h | 7 +- content/ppapi_plugin/ppapi_plugin_main.cc | 2 +- .../browser/child_process_security_policy.h | 1 + .../public/browser/content_browser_client.cc | 4 + .../public/browser/content_browser_client.h | 1 + content/public/browser/render_frame_host.h | 2 + .../public/browser/web_contents_delegate.h | 3 +- content/public/common/content_client.h | 1 + content/public/common/content_features.cc | 5 +- content/public/common/content_features.h | 1 + content/public/common/content_switches.cc | 10 +- content/public/common/content_switches.h | 5 + content/public/common/file_chooser_params.h | 3 + content/public/common/renderer_preferences.h | 3 + content/public/common/user_agent.h | 2 + content/public/common/web_preferences.cc | 2 +- content/public/common/web_preferences.h | 2 +- .../renderer/content_renderer_client.cc | 4 + .../public/renderer/content_renderer_client.h | 10 + content/public/test/browser_test_base.cc | 1 + content/renderer/BUILD.gn | 2 + content/renderer/frame_owner_properties.cc | 3 + .../renderer/in_process_renderer_thread.cc | 2 + content/renderer/render_frame_impl.cc | 30 +- content/renderer/render_frame_impl.h | 8 + content/renderer/render_process_impl.cc | 6 + content/renderer/render_view_impl.cc | 25 +- content/renderer/render_view_impl.h | 4 +- content/renderer/render_widget.cc | 13 + .../renderer/renderer_blink_platform_impl.cc | 50 +- .../renderer/renderer_blink_platform_impl.h | 2 +- content/renderer/renderer_main.cc | 47 +- .../embedded_shared_worker_stub.cc | 4 +- .../embedded_shared_worker_stub.h | 4 + .../shared_worker/shared_worker_repository.cc | 4 + .../shared_worker/shared_worker_repository.h | 1 + .../shell/test_runner/web_view_test_proxy.h | 2 +- content/test/test_render_frame.cc | 2 + extensions/BUILD.gn | 2 +- extensions/browser/BUILD.gn | 4 + .../app_current_window_internal_api.cc | 15 +- .../app_current_window_internal_api.h | 10 + .../browser/api/app_window/app_window_api.cc | 75 +- .../browser/api/app_window/app_window_api.h | 5 + .../browser/api/execute_code_function.cc | 6 +- .../web_view/web_view_internal_api.cc | 36 +- .../web_view/web_view_internal_api.h | 31 + extensions/browser/api/runtime/runtime_api.cc | 17 +- extensions/browser/api/runtime/runtime_api.h | 2 +- .../app_window/app_web_contents_helper.cc | 20 +- extensions/browser/app_window/app_window.cc | 222 ++- extensions/browser/app_window/app_window.h | 48 +- .../browser/app_window/app_window_contents.cc | 28 +- .../browser/app_window/app_window_contents.h | 8 +- .../browser/app_window/app_window_registry.cc | 5 +- .../browser/app_window/app_window_registry.h | 2 +- .../browser/app_window/native_app_window.h | 4 + .../app_window/test_app_window_contents.cc | 3 +- .../app_window/test_app_window_contents.h | 3 +- extensions/browser/content_hash_fetcher.cc | 2 + extensions/browser/content_verifier.cc | 75 +- extensions/browser/content_verifier.h | 20 +- .../browser/content_verifier/content_hash.cc | 2 +- .../browser/content_verifier/test_utils.cc | 4 +- .../browser/content_verifier/test_utils.h | 4 +- .../browser/content_verifier_delegate.h | 4 +- extensions/browser/content_verify_job.cc | 35 +- extensions/browser/content_verify_job.h | 21 +- extensions/browser/event_listener_map.cc | 20 +- extensions/browser/event_listener_map.h | 4 +- extensions/browser/event_router.cc | 10 +- extensions/browser/event_router.h | 6 +- extensions/browser/extension_function.cc | 45 +- extensions/browser/extension_function.h | 24 + .../browser/extension_function_dispatcher.cc | 41 +- .../browser/extension_function_dispatcher.h | 13 +- extensions/browser/extension_prefs.cc | 16 +- extensions/browser/extension_protocols.cc | 37 +- extensions/browser/extension_registrar.cc | 4 + .../extension_web_contents_observer.cc | 48 +- .../browser/extension_web_contents_observer.h | 8 + .../extensions_guest_view_manager_delegate.cc | 4 +- .../mime_handler_view_guest.cc | 3 + .../web_view/javascript_dialog_helper.cc | 4 + .../guest_view/web_view/web_view_constants.cc | 1 + .../guest_view/web_view/web_view_constants.h | 1 + .../guest_view/web_view/web_view_guest.cc | 57 +- .../guest_view/web_view/web_view_guest.h | 5 +- extensions/browser/process_manager.cc | 3 + extensions/browser/url_request_util.cc | 3 +- extensions/browser/verified_contents.cc | 24 +- extensions/browser/verified_contents.h | 2 +- extensions/common/api/_api_features.json | 9 +- extensions/common/api/_manifest_features.json | 2 +- .../common/api/_permission_features.json | 2 + .../api/app_current_window_internal.idl | 3 + extensions/common/api/app_window.idl | 16 + .../api/bluetooth/bluetooth_manifest_data.cc | 8 + extensions/common/api/events.json | 14 + extensions/common/api/extension_types.json | 1 + extensions/common/api/runtime.json | 5 + .../api/sockets/sockets_manifest_data.cc | 2 + extensions/common/api/web_view_internal.json | 52 + extensions/common/constants.cc | 4 + extensions/common/constants.h | 2 + extensions/common/extension.cc | 22 + extensions/common/extension.h | 1 + extensions/common/extension_messages.h | 6 + .../common/features/manifest_feature.cc | 3 + extensions/common/features/simple_feature.cc | 12 + extensions/common/file_util.cc | 27 +- extensions/common/manifest.cc | 15 +- extensions/common/manifest.h | 4 +- extensions/common/manifest_constants.cc | 12 +- extensions/common/manifest_constants.h | 10 + .../manifest_handlers/background_info.cc | 2 + .../content_scripts_handler.cc | 14 +- .../common/manifest_handlers/csp_info.cc | 5 + .../manifest_handlers/permissions_parser.cc | 4 +- .../common/manifest_handlers/webview_info.cc | 33 + .../common/manifest_handlers/webview_info.h | 4 + .../common/permissions/permission_message.cc | 2 +- .../common/permissions/permission_set.cc | 17 +- .../common/permissions/permission_set.h | 11 +- .../common/permissions/permissions_data.cc | 39 +- .../common/permissions/permissions_data.h | 7 +- extensions/common/url_pattern.cc | 2 +- extensions/common/user_script.cc | 3 + extensions/common/user_script.h | 5 + .../native_app_window_views.cc | 120 +- .../native_app_window_views.h | 8 + extensions/extensions_resources.grd | 1 + .../renderer/app_window_custom_bindings.cc | 15 + .../renderer/app_window_custom_bindings.h | 1 + extensions/renderer/dispatcher.cc | 119 +- extensions/renderer/dispatcher.h | 1 + extensions/renderer/event_bindings.cc | 73 +- extensions/renderer/event_bindings.h | 1 + extensions/renderer/extension_frame_helper.cc | 36 +- extensions/renderer/extension_frame_helper.h | 1 + .../renderer/extension_injection_host.cc | 2 +- .../renderer/id_generator_custom_bindings.cc | 7 + extensions/renderer/ipc_message_sender.cc | 12 +- extensions/renderer/ipc_message_sender.h | 5 +- .../renderer/js_extension_bindings_system.cc | 58 +- .../renderer/js_extension_bindings_system.h | 2 +- .../renderer/object_backed_native_handler.cc | 6 +- .../renderer/object_backed_native_handler.h | 1 + .../renderer/render_frame_observer_natives.cc | 99 +- .../renderer/render_frame_observer_natives.h | 5 +- extensions/renderer/request_sender.cc | 58 + extensions/renderer/request_sender.h | 10 + .../resources/app_window_custom_bindings.js | 103 +- extensions/renderer/resources/binding.js | 5 +- extensions/renderer/resources/event.js | 12 + .../extensions_renderer_resources.grd | 13 + .../web_view/web_view_api_methods.js | 28 +- .../web_view/web_view_attributes.js | 14 + .../guest_view/web_view/web_view_constants.js | 1 + extensions/renderer/resources/last_error.js | 2 +- extensions/renderer/resources/send_request.js | 30 +- .../renderer/runtime_custom_bindings.cc | 10 +- extensions/renderer/script_context.cc | 22 +- extensions/renderer/script_context.h | 2 + extensions/renderer/script_context_set.cc | 8 +- extensions/renderer/script_context_set.h | 4 +- extensions/renderer/send_request_natives.cc | 53 + extensions/renderer/send_request_natives.h | 1 + extensions/renderer/user_script_injector.cc | 2 +- extensions/renderer/user_script_set.cc | 12 +- .../renderer/v8_context_native_handler.cc | 12 + headless/BUILD.gn | 13 +- .../browser/snapshots/snapshot_cache.mm | 2 +- ipc/ipc_logging.cc | 2 +- media/BUILD.gn | 10 - media/audio/audio_manager_base.cc | 5 +- media/ffmpeg/ffmpeg_common.cc | 6 + net/base/mime_util.cc | 1 + net/cert/cert_verifier.h | 4 +- net/cert/cert_verify_proc_mac.cc | 11 +- net/cert/cert_verify_proc_win.cc | 36 +- net/cert/multi_threaded_cert_verifier.cc | 4 +- net/cookies/cookie_monster.cc | 1 + .../pnacl_support_extension/BUILD.gn | 1 + remoting/remoting_enable.gni | 2 +- services/service_manager/embedder/BUILD.gn | 1 + services/service_manager/embedder/main.cc | 15 +- .../sandbox/linux/sandbox_linux.cc | 2 + .../zygote/host/zygote_communication_linux.cc | 2 + .../zygote/host/zygote_host_impl_linux.cc | 5 +- storage/browser/fileapi/isolated_context.cc | 1 + .../variations/fieldtrial_testing_config.json | 18 - third_party/blink/public/platform/platform.h | 2 +- .../public/platform/web_security_origin.h | 2 + third_party/blink/public/web/blink.h | 3 + .../public/web/web_file_chooser_params.h | 7 +- third_party/blink/public/web/web_frame.h | 9 +- .../blink/public/web/web_frame_client.h | 2 + .../public/web/web_frame_owner_properties.h | 5 +- third_party/blink/public/web/web_node.h | 2 +- .../blink/public/web/web_shared_worker.h | 5 + .../web/web_shared_worker_repository_client.h | 2 +- .../blink/public/web/web_view_client.h | 4 +- .../blink/renderer/bindings/bindings.gni | 2 + .../bindings/core/v8/binding_security.cc | 2 + .../core/v8/custom/v8_filelist_custom.cc | 24 + .../custom/v8_html_iframe_element_custom.cc | 25 + .../core/v8/custom/v8_window_custom.cc | 38 + .../bindings/core/v8/generated_code_helper.h | 2 +- .../bindings/core/v8/script_controller.cc | 3 + .../bindings/core/v8/v8_initializer.cc | 29 + .../bindings/templates/interface.cpp.tmpl | 3 + .../bindings/templates/interface.h.tmpl | 7 +- third_party/blink/renderer/core/BUILD.gn | 2 +- .../editing/commands/clipboard_commands.cc | 6 + .../core/exported/local_frame_client_impl.cc | 20 +- .../core/exported/local_frame_client_impl.h | 1 + .../shared_worker_repository_client_impl.cc | 4 +- .../shared_worker_repository_client_impl.h | 2 +- .../blink/renderer/core/exported/web_frame.cc | 2 + .../renderer/core/exported/web_frame_test.cc | 3 +- .../core/exported/web_shared_worker_impl.cc | 21 +- .../core/exported/web_shared_worker_impl.h | 3 + .../renderer/core/exported/web_view_test.cc | 3 +- .../blink/renderer/core/fileapi/file.h | 6 +- .../blink/renderer/core/fileapi/file.idl | 4 +- .../blink/renderer/core/fileapi/file_list.h | 1 + .../blink/renderer/core/fileapi/file_list.idl | 3 + .../core/frame/csp/csp_directive_list.cc | 2 + .../blink/renderer/core/frame/frame.cc | 49 +- third_party/blink/renderer/core/frame/frame.h | 9 + .../blink/renderer/core/frame/frame_owner.h | 4 + .../renderer/core/frame/local_dom_window.cc | 4 +- .../renderer/core/frame/local_frame_client.h | 1 + .../blink/renderer/core/frame/location.cc | 3 + .../renderer/core/frame/remote_frame_owner.cc | 2 + .../renderer/core/frame/remote_frame_owner.h | 7 + .../core/frame/web_local_frame_impl.cc | 2 + .../core/frame/web_local_frame_impl.h | 8 + .../blink/renderer/core/frame/window.idl | 4 +- .../renderer/core/fullscreen/fullscreen.cc | 2 +- .../core/html/canvas/html_canvas_element.cc | 4 +- .../chooser_only_temporal_input_type_view.cc | 3 +- .../core/html/forms/color_input_type.cc | 2 +- .../renderer/core/html/forms/file_chooser.cc | 5 +- .../renderer/core/html/forms/file_chooser.h | 2 +- .../core/html/forms/file_input_type.cc | 29 +- .../core/html/forms/file_input_type.h | 2 +- .../core/html/forms/html_input_element.cc | 20 + .../core/html/forms/html_input_element.h | 4 + .../core/html/forms/html_input_element.idl | 3 + .../core/html/html_attribute_names.json5 | 7 + .../core/html/html_frame_owner_element.h | 6 + .../renderer/core/html/html_html_element.cc | 1 + .../renderer/core/html/html_iframe_element.cc | 12 + .../renderer/core/html/html_iframe_element.h | 4 + .../core/html/html_iframe_element.idl | 3 + .../core/html/media/autoplay_policy.cc | 4 +- .../core/inspector/inspected_frames.h | 8 +- .../layout_worklet_global_scope_proxy.cc | 2 +- .../renderer/core/loader/empty_clients.h | 3 +- .../renderer/core/loader/frame_loader.cc | 51 +- .../blink/renderer/core/loader/frame_loader.h | 3 + .../blink/renderer/core/page/chrome_client.h | 3 +- .../renderer/core/page/chrome_client_impl.cc | 6 +- .../renderer/core/page/chrome_client_impl.h | 2 +- .../blink/renderer/core/page/create_window.cc | 39 +- .../blink/renderer/core/page/create_window.h | 2 +- .../renderer/core/page/drag_controller.cc | 9 +- .../blink/renderer/core/page/frame_tree.cc | 12 +- .../blink/renderer/core/probe/core_probes.h | 20 + .../blink/renderer/core/script/modulator.h | 1 + .../core/script/modulator_impl_base.cc | 5 + .../core/script/modulator_impl_base.h | 1 + .../blink/renderer/core/script/module_map.cc | 9 + .../blink/renderer/core/script/module_map.h | 1 + .../renderer/core/workers/dedicated_worker.cc | 22 +- .../workers/dedicated_worker_global_scope.cc | 1 + .../workers/global_scope_creation_params.cc | 2 + .../workers/global_scope_creation_params.h | 3 + .../renderer/core/workers/shared_worker.cc | 6 +- .../workers/shared_worker_repository_client.h | 2 +- .../threaded_worklet_messaging_proxy.cc | 1 + .../core/workers/worker_backing_thread.cc | 14 + .../core/workers/worker_global_scope.cc | 21 + .../core/workers/worker_global_scope.h | 2 + .../core/workers/worker_global_scope.idl | 1 + .../renderer/core/workers/worker_thread.cc | 18 +- .../core/xmlhttprequest/xml_http_request.cc | 2 + third_party/blink/renderer/devtools/BUILD.gn | 2 +- .../devtools/front_end/devtools_app.json | 2 +- .../front_end/dom_extension/DOMExtension.js | 11 +- .../canvas2d/canvas_rendering_context_2d.cc | 2 + .../paint_worklet_global_scope_proxy.cc | 2 +- .../exported/web_embedded_worker_impl.cc | 22 + .../platform/bindings/script_state.cc | 2 + .../renderer/platform/bindings/script_state.h | 2 +- .../platform/exported/web_security_origin.cc | 7 +- .../renderer/platform/lifecycle_observer.h | 1 + .../renderer/platform/memory_coordinator.cc | 16 + .../webthread_impl_for_worker_scheduler.cc | 12 + .../platform/weborigin/security_origin.h | 1 + .../blink/renderer/platform/wtf/BUILD.gn | 1 + .../wtf/typed_arrays/array_buffer_contents.h | 5 +- .../handler/crash_report_upload_thread.cc | 14 +- .../crashpad/crashpad/handler/handler_main.cc | 2 +- third_party/node/node.py | 27 +- tools/grit/grit_rule.gni | 7 + tools/gritsettings/resource_ids | 9 + tools/licenses.py | 11 + tools/v8_context_snapshot/BUILD.gn | 5 +- tools/v8_context_snapshot/run.py | 19 + ui/accelerated_widget_mac/BUILD.gn | 1 + .../platform/atk_util_auralinux.cc | 2 + ui/base/accelerators/accelerator.cc | 12 +- ui/base/base_window.cc | 4 + ui/base/base_window.h | 1 + ui/base/clipboard/clipboard.h | 2 +- ui/base/models/simple_menu_model.cc | 6 +- ui/base/models/simple_menu_model.h | 2 + ui/base/resource/resource_bundle.cc | 15 +- ui/base/resource/resource_bundle_mac.mm | 4 +- ui/display/display.cc | 10 + ui/display/display.h | 5 + ui/gfx/BUILD.gn | 1 + ui/gfx/icon_util.cc | 15 + ui/gfx/icon_util.h | 4 + ui/gfx/mac/nswindow_frame_controls.h | 1 + ui/gfx/mac/nswindow_frame_controls.mm | 16 + ui/message_center/public/cpp/notification.h | 3 +- .../views/message_popup_collection.cc | 2 +- ui/native_theme/native_theme_win.cc | 5 + ui/shell_dialogs/select_file_dialog_mac.mm | 6 +- ui/shell_dialogs/select_file_dialog_win.cc | 4 +- ui/strings/ui_strings.grd | 6 + .../native_view_accessibility_auralinux.cc | 2 + ui/views/controls/menu/native_menu_win.cc | 12 +- ui/views/controls/menu/native_menu_win.h | 6 + .../widget/desktop_aura/desktop_screen_x11.cc | 2 +- .../desktop_window_tree_host_win.cc | 16 +- .../desktop_window_tree_host_win.h | 2 + .../desktop_window_tree_host_x11.cc | 4 + ui/views/widget/native_widget_delegate.h | 1 + ui/views/widget/widget.cc | 8 +- ui/views/widget/widget.h | 3 +- ui/views/widget/widget_delegate.cc | 16 + ui/views/widget/widget_delegate.h | 7 + ui/views/widget/widget_hwnd_utils.cc | 21 +- ui/views/win/hwnd_message_handler.cc | 84 +- ui/views/win/hwnd_message_handler.h | 2 + ui/views/win/hwnd_message_handler_delegate.h | 6 + ui/views/window/custom_frame_view.cc | 14 +- 779 files changed, 10546 insertions(+), 1914 deletions(-) create mode 100644 base/message_loop/message_pump_uv.cc create mode 100644 base/message_loop/message_pump_uv.h create mode 100644 base/message_loop/message_pumpuv_mac.h create mode 100644 base/message_loop/message_pumpuv_mac.mm create mode 100644 build/util/version.gypi create mode 100644 chrome/app/nw.dll.manifest create mode 100644 chrome/app/nw.exe.manifest create mode 100644 chrome/app/theme/chromium/product_logo_32.xpm create mode 100644 chrome/browser/nwjs_resources.grd create mode 100644 chrome/browser/resources/empty.css create mode 100644 chrome/browser/resources/empty.html create mode 100644 chrome/browser/resources/empty.js create mode 100644 chrome/browser/resources/empty.json create mode 100644 chrome/browser/resources/empty.png create mode 100644 chrome/browser/resources/nwjs/default.js create mode 100644 chrome/browser/resources/nwjs_default_app/main.js create mode 100644 chrome/browser/resources/nwjs_default_app/manifest.json create mode 100644 chrome/browser/resources/nwjs_default_app/nw_blank.html create mode 100644 chrome/browser/resources/nwjs_newwin_app/main.js create mode 100644 chrome/browser/resources/nwjs_newwin_app/manifest.json create mode 100644 chrome/browser/resources/nwjs_newwin_app/nw_blank.html create mode 100644 third_party/blink/renderer/bindings/core/v8/custom/v8_filelist_custom.cc create mode 100644 third_party/blink/renderer/bindings/core/v8/custom/v8_html_iframe_element_custom.cc create mode 100644 tools/v8_context_snapshot/run.py diff --git a/.gitignore b/.gitignore index c6edf625a3aa3..282c30165ac9e 100644 --- a/.gitignore +++ b/.gitignore @@ -280,3 +280,5 @@ vs-chromium-project.txt /win8/metro_driver/metro_driver_version_resources.xml /x86-generic_out/ /xcodebuild +/content/nw + diff --git a/BUILD.gn b/BUILD.gn index 378aa8822becb..286d0b1fe880f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -97,6 +97,7 @@ group("gn_all") { if (!is_ios && !is_android && !is_chromecast && !is_fuchsia) { deps += [ + "//content/nw:nwjs", "//chrome", "//chrome/test:browser_tests", "//chrome/test:interactive_ui_tests", diff --git a/DEPS b/DEPS index 2b667ae8cbac9..18b7f2bfbaaf3 100644 --- a/DEPS +++ b/DEPS @@ -85,6 +85,7 @@ vars = { 'android_git': 'https://android.googlesource.com', 'aomedia_git': 'https://aomedia.googlesource.com', 'chromium_git': 'https://chromium.googlesource.com', + 'nwjs_git': 'https://github.com/nwjs', 'swiftshader_git': 'https://swiftshader.googlesource.com', 'pdfium_git': 'https://pdfium.googlesource.com', 'boringssl_git': 'https://boringssl.googlesource.com', @@ -1010,8 +1011,8 @@ deps = { 'src/tools/swarming_client': Var('chromium_git') + '/infra/luci/client-py.git' + '@' + Var('swarming_revision'), - 'src/v8': - Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), + #'src/v8': + # Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f7ec728f7bbea50aaa63eeb31e3bedaa10ee6451', @@ -1767,7 +1768,15 @@ hooks = [ '--no_auth', '--bucket', 'chromium-nodejs/8.9.1', '-s', 'src/third_party/node/linux/node-linux-x64.tar.gz.sha1', - ], + ], + }, + { + 'name': 'nw_patch', + 'pattern': '.', + 'action': [ + 'python', + 'src/content/nw/tools/patcher.py' + ], }, { 'name': 'node_mac', diff --git a/apps/app_lifetime_monitor.cc b/apps/app_lifetime_monitor.cc index 0e63be8b6bdf4..a584df9d44072 100644 --- a/apps/app_lifetime_monitor.cc +++ b/apps/app_lifetime_monitor.cc @@ -77,8 +77,10 @@ void AppLifetimeMonitor::OnAppWindowRemoved(AppWindow* app_window) { } void AppLifetimeMonitor::OnAppWindowHidden(AppWindow* app_window) { +#if 0 if (!HasOtherVisibleAppWindows(app_window)) NotifyAppDeactivated(app_window->extension_id()); +#endif } void AppLifetimeMonitor::OnAppWindowShown(AppWindow* app_window, diff --git a/apps/launcher.cc b/apps/launcher.cc index 5f8457f81a398..9035b40aa85a1 100644 --- a/apps/launcher.cc +++ b/apps/launcher.cc @@ -104,7 +104,10 @@ class PlatformAppPathLauncher extension_id(app->id()), entry_paths_(entry_paths), mime_type_collector_(context), - is_directory_collector_(context) {} + is_directory_collector_(context) { + if (app->is_nwjs_app()) //NWJS#5097 + entry_paths_.clear(); + } PlatformAppPathLauncher(content::BrowserContext* context, const Extension* app, @@ -113,7 +116,7 @@ class PlatformAppPathLauncher extension_id(app->id()), mime_type_collector_(context), is_directory_collector_(context) { - if (!file_path.empty()) + if (!file_path.empty() && !app->is_nwjs_app()) //NWJS#5097 entry_paths_.push_back(file_path); } diff --git a/base/BUILD.gn b/base/BUILD.gn index 943412faefd75..c6c1d30646703 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -565,6 +565,8 @@ jumbo_component("base") { "message_loop/message_pump_io_ios.h", "message_loop/message_pump_mac.h", "message_loop/message_pump_mac.mm", + "message_loop/message_pump_uv.cc", + "message_loop/message_pump_uv.h", "message_loop/message_pump_win.cc", "message_loop/message_pump_win.h", "message_loop/timer_slack.h", diff --git a/base/base_switches.cc b/base/base_switches.cc index 7ce7380dbe07d..1d22d3771ce23 100644 --- a/base/base_switches.cc +++ b/base/base_switches.cc @@ -124,4 +124,5 @@ const char kForceNativePrefetch[] = "force-native-prefetch"; const char kNativePrefetchOrderedOnly[] = "native-prefetch-ordered-only"; #endif +const char kNWJS[] = "nwjs"; } // namespace switches diff --git a/base/base_switches.h b/base/base_switches.h index 3425e6fad0925..35c5a719f3661 100644 --- a/base/base_switches.h +++ b/base/base_switches.h @@ -48,6 +48,7 @@ extern const char kForceNativePrefetch[]; extern const char kNativePrefetchOrderedOnly[]; #endif +extern const char kNWJS[]; } // namespace switches #endif // BASE_BASE_SWITCHES_H_ diff --git a/base/command_line.cc b/base/command_line.cc index aec89f5633731..21db588626e60 100644 --- a/base/command_line.cc +++ b/base/command_line.cc @@ -155,32 +155,83 @@ string16 QuoteForCommandLineToArgvW(const string16& arg, CommandLine::CommandLine(NoProgram no_program) : argv_(1), - begin_args_(1) { + begin_args_(1), + argc0_(0), argv0_(NULL) { } CommandLine::CommandLine(const FilePath& program) : argv_(1), - begin_args_(1) { + begin_args_(1), + argc0_(0), argv0_(NULL) { SetProgram(program); } CommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv) : argv_(1), - begin_args_(1) { + begin_args_(1), + argc0_(0), argv0_(NULL) { InitFromArgv(argc, argv); } CommandLine::CommandLine(const StringVector& argv) : argv_(1), - begin_args_(1) { + begin_args_(1), + argc0_(0), argv0_(NULL) { InitFromArgv(argv); } -CommandLine::CommandLine(const CommandLine& other) = default; +CommandLine::CommandLine(const CommandLine& other) + : argv_(other.argv_), + original_argv_(other.original_argv_), + switches_(other.switches_), + begin_args_(other.begin_args_), + argc0_(other.argc0_), argv0_(nullptr) { -CommandLine& CommandLine::operator=(const CommandLine& other) = default; +#if defined(OS_WIN) + if (other.argv0_) { + argv0_ = new char*[argc0_ + 1]; + for (int i = 0; i < argc0_; ++i) { + argv0_[i] = new char[strlen(other.argv0_[i]) + 1]; + strcpy(argv0_[i], other.argv0_[i]); + } + argv0_[argc0_] = NULL; + } +#else + argv0_ = other.argv0_; +#endif +} + +CommandLine& CommandLine::operator=(const CommandLine& other) { + argv_ = other.argv_; + original_argv_ = other.original_argv_; + switches_ = other.switches_; + begin_args_ = other.begin_args_; +#if defined(OS_WIN) + if (other.argv0_) { + argc0_ = other.argc0_; + argv0_ = new char*[argc0_ + 1]; + for (int i = 0; i < argc0_; ++i) { + argv0_[i] = new char[strlen(other.argv0_[i]) + 1]; + strcpy(argv0_[i], other.argv0_[i]); + } + argv0_[argc0_] = NULL; + } +#else + argv0_ = other.argv0_; +#endif + return *this; +} -CommandLine::~CommandLine() = default; +CommandLine::~CommandLine() { +#if defined(OS_WIN) + if (!argv0_) + return; + for (int i = 0; i < argc0_; i++) { + delete[] argv0_[i]; + } + delete[] argv0_; +#endif +} #if defined(OS_WIN) // static @@ -253,12 +304,34 @@ CommandLine CommandLine::FromString(const string16& command_line) { void CommandLine::InitFromArgv(int argc, const CommandLine::CharType* const* argv) { StringVector new_argv; + argc0_ = argc; +#if !defined(OS_WIN) + argv0_ = (char**)argv; +#else + argv0_ = new char*[argc + 1]; + for (int i = 0; i < argc; ++i) { + std::string str(base::WideToUTF8(argv[i])); + argv0_[i] = new char[str.length() + 1]; + strcpy(argv0_[i], str.c_str()); + } + argv0_[argc] = NULL; +#endif for (int i = 0; i < argc; ++i) new_argv.push_back(argv[i]); InitFromArgv(new_argv); } void CommandLine::InitFromArgv(const StringVector& argv) { +#if !defined(OS_MACOSX) + original_argv_ = argv; +#else + for (size_t index = 0; index < argv.size(); ++index) { + if (argv[index].compare(0, strlen("--psn_"), "--psn_") != 0 && + argv[index].compare(0, strlen("-psn_"), "-psn_") != 0) { + original_argv_.push_back(argv[index]); + } + } +#endif argv_ = StringVector(1); switches_.clear(); begin_args_ = 1; @@ -397,6 +470,12 @@ void CommandLine::AppendArgNative(const CommandLine::StringType& value) { argv_.push_back(value); } +#if defined(OS_MACOSX) +void CommandLine::FixOrigArgv4Finder(const CommandLine::StringType& value) { + original_argv_.push_back(value); +} +#endif + void CommandLine::AppendArguments(const CommandLine& other, bool include_program) { if (include_program) diff --git a/base/command_line.h b/base/command_line.h index 25fd7d9193e8b..316cc4836fba0 100644 --- a/base/command_line.h +++ b/base/command_line.h @@ -149,6 +149,11 @@ class BASE_EXPORT CommandLine { // Returns the original command line string as a vector of strings. const StringVector& argv() const { return argv_; } + int argc0() { return argc0_; } + char** argv0() { return argv0_; } + + // Returns the original command line string as a vector of strings (keeps precedence). + const StringVector& original_argv() const { return original_argv_; } // Get and Set the program part of the command line string (the first item). FilePath GetProgram() const; @@ -199,6 +204,10 @@ class BASE_EXPORT CommandLine { void AppendArgPath(const FilePath& value); void AppendArgNative(const StringType& value); +#if defined(OS_MACOSX) + void FixOrigArgv4Finder(const StringType& value); +#endif + // Append the switches and arguments from another command line to this one. // If |include_program| is true, include |other|'s program as well. void AppendArguments(const CommandLine& other, bool include_program); @@ -235,11 +244,17 @@ class BASE_EXPORT CommandLine { // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* } StringVector argv_; + // The argv array (precedence not messed). + StringVector original_argv_; + // Parsed-out switch keys and values. SwitchMap switches_; // The index after the program and switches, any arguments start here. size_t begin_args_; + + int argc0_; + char** argv0_; }; } // namespace base diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc index d8a0ae05e3dc1..6e1e59b27a156 100644 --- a/base/files/file_util_posix.cc +++ b/base/files/file_util_posix.cc @@ -134,7 +134,7 @@ std::string TempFileName() { #if defined(GOOGLE_CHROME_BUILD) return std::string(".com.google.Chrome.XXXXXX"); #else - return std::string(".org.chromium.Chromium.XXXXXX"); + return std::string(".io.nwjs.XXXXXX"); #endif } diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 97ed778d8f1a3..32cffa8ad7a4f 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc @@ -143,6 +143,9 @@ std::unique_ptr MessageLoop::CreateMessagePumpForType(Type type) { return std::unique_ptr(new MessagePumpForUI()); #endif + if (type == MessageLoop::TYPE_NODE) + return std::unique_ptr(new MessagePumpUV()); + DCHECK_EQ(MessageLoop::TYPE_DEFAULT, type); #if defined(OS_IOS) // On iOS, a native runloop is always required to pump system work. diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index bd191fd9779dd..35a6dfb9459cf 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h @@ -28,6 +28,8 @@ #include "base/time/time.h" #include "build/build_config.h" +#include "base/message_loop/message_pump_uv.h" + namespace base { class ThreadTaskRunnerHandle; @@ -109,6 +111,9 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate, // TYPE_CUSTOM // MessagePump was supplied to constructor. // + // TYPE_NODE + // For integration with NodeJS/libuv in the renderer thread + enum Type { TYPE_DEFAULT, TYPE_UI, @@ -116,7 +121,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate, TYPE_IO, #if defined(OS_ANDROID) TYPE_JAVA, -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) + TYPE_NODE }; // Normally, it is not necessary to instantiate a MessageLoop. Instead, it @@ -403,6 +409,43 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop { static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForIO), "MessageLoopForIO should not have extra member variables"); +#if !defined(OS_MACOSX) + +//----------------------------------------------------------------------------- +// MessageLoopForUV extends MessageLoop with methods that are particular to a +// MessageLoop instantiated with TYPE_NODE. +// +// This class is typically used like so: +// MessageLoopForUV::current()->...call some method... +// + +class BASE_EXPORT MessageLoopForUV : public MessageLoop { + public: + + MessageLoopForUV() : MessageLoop(TYPE_NODE) { + } + + // Returns the MessageLoopForUV of the current thread. + static MessageLoopForUV* current() { + MessageLoop* loop = MessageLoop::current(); + //DCHECK_EQ(MessageLoop::TYPE_NODE, loop->type()); + return static_cast(loop); + } + + base::MessagePumpUV* pump_uv() { + return static_cast(pump_.get()); + } + +}; + +// Do not add any member variables to MessageLoopForUV! This is important b/c +// MessageLoopForUV is often allocated via MessageLoop(TYPE_IO). Any extra +// data that you need should be stored on the MessageLoop's pump_ instance. +static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForUV), + "MessageLoopForUV should not have extra member variables"); + +#endif + } // namespace base #endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h index fa88c3a7693b5..fb058bff54a5b 100644 --- a/base/message_loop/message_pump_mac.h +++ b/base/message_loop/message_pump_mac.h @@ -124,6 +124,20 @@ class BASE_EXPORT MessagePumpCFRunLoopBase : public MessagePump { // Get the current mode mask from |enabled_modes_|. int GetModeMask() const; +#if 0 + // Invokes function(run_loop_, arg, mode) for all the modes in |mode_mask_|. + template + void InvokeForEnabledModes(void method(CFRunLoopRef, Argument, CFStringRef), + Argument argument) { + for (size_t i = 0; i < nAllModes; ++i) { + if (mode_mask_ & (0x1 << i)) + method(run_loop_, argument, kAllModes[i]); + } + } + + static const CFStringRef kAllModes[]; + static const size_t nAllModes; +#endif private: class ScopedModeEnabler; @@ -155,7 +169,8 @@ class BASE_EXPORT MessagePumpCFRunLoopBase : public MessagePump { // the instance method; the instance method returns true if it resignalled // work_source_ to be called again from the loop. static void RunWorkSource(void* info); - bool RunWork(); + protected: + virtual bool RunWork(); // Perform idle-priority work. This is normally called by PreWaitObserver, // but is also associated with idle_work_source_. When this function @@ -163,7 +178,8 @@ class BASE_EXPORT MessagePumpCFRunLoopBase : public MessagePump { // static method calls the instance method; the instance method returns // true if idle work was done. static void RunIdleWorkSource(void* info); - bool RunIdleWork(); + virtual bool RunIdleWork(); + virtual void PreWaitObserverHook(); // Perform work that may have been deferred because it was not runnable // within a nested run loop. This is associated with diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm index fb2520179995a..31a1957811ad8 100644 --- a/base/message_loop/message_pump_mac.mm +++ b/base/message_loop/message_pump_mac.mm @@ -583,9 +583,13 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : // nesting-deferred work may have accumulated. Schedule it for processing // if appropriate. self->MaybeScheduleNestingDeferredWork(); + self->PreWaitObserverHook(); }); } +void MessagePumpCFRunLoopBase::PreWaitObserverHook() { +} + // Called from the run loop. // static void MessagePumpCFRunLoopBase::PreSourceObserver(CFRunLoopObserverRef observer, diff --git a/base/message_loop/message_pump_uv.cc b/base/message_loop/message_pump_uv.cc new file mode 100644 index 0000000000000..eef24ed23c84f --- /dev/null +++ b/base/message_loop/message_pump_uv.cc @@ -0,0 +1,184 @@ +// 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. + +#include "base/message_loop/message_pump_uv.h" + +#include "base/logging.h" +#include "base/command_line.h" +#include "v8/include/v8.h" +//#include "third_party/node/src/node.h" +#undef CHECK +#undef CHECK_EQ +#undef CHECK_GE +#undef CHECK_GT +#undef CHECK_NE +#undef CHECK_LT +#undef CHECK_LE +#undef CHECK_OP +#undef DISALLOW_COPY_AND_ASSIGN +#include "third_party/node-nw/src/node_webkit.h" + +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#define NW_HOOK_INIT(type, sym, fn) BASE_EXPORT type fn = nullptr; +#define NODE_HOOK_INIT(type, sym, fn) BASE_EXPORT type fn = nullptr; +#include "content/nw/src/common/node_hooks.h" +#undef NODE_HOOK_INIT +#undef NW_HOOK_INIT +#undef NW_HOOK_MAP + +namespace base { + +MessagePumpUV::MessagePumpUV() + : keep_running_(true), + nesting_level_(0) { + // wakeup_event_ = new uv_async_t; + // uv_async_init(uv_default_loop(), wakeup_event_, wakeup_callback); + // node::g_nw_uv_run = uv_run; + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + int worker_support = command_line.HasSwitch("enable-node-worker") ? 1 : 0; //kEnableNodeWorker + g_msg_pump_ctor_fn(&wakeup_event_, worker_support); +} + +MessagePumpUV::~MessagePumpUV() { + // delete wakeup_event_; + // wakeup_event_ = NULL; + g_msg_pump_dtor_fn(&wakeup_event_); +} + +void MessagePumpUV::Run(Delegate* delegate) { + + ++nesting_level_; + DCHECK(keep_running_) << "Quit must have been called outside of Run!"; + + msg_pump_context_t ctx; + memset(&ctx, 0, sizeof(msg_pump_context_t)); + + // Poll external loop in nested message loop, so node.js's events will be + // paused in nested loop. + // uv_loop_t* loop = uv_default_loop(); + ctx.loop = g_uv_default_loop_fn(); + ctx.wakeup_event = wakeup_event_; + ctx.wakeup_events = &wakeup_events_; + + if (nesting_level_ > 1) { + g_msg_pump_nest_enter_fn(&ctx); + wakeup_event_ = ctx.wakeup_event; + // loop = uv_loop_new(); + + // wakeup_events_.push_back(wakeup_event_); + // wakeup_event_ = new uv_async_t; + // uv_async_init(loop, wakeup_event_, wakeup_callback); + } + + // // Create handles for the loop. + // uv_idle_t idle_handle; + // uv_idle_init(loop, &idle_handle); + + // uv_timer_t delay_timer; + // delay_timer.data = &idle_handle; + // uv_timer_init(loop, &delay_timer); + + g_msg_pump_pre_loop_fn(&ctx); + // Enter Loop + for (;;) { + bool did_work = delegate->DoWork(); + if (!keep_running_) + break; + + did_work |= delegate->DoDelayedWork(&delayed_work_time_); + if (!keep_running_) + break; + + if (did_work) { + // // call tick callback after done work in V8, + // // in the same way node upstream handle this in MakeCallBack, + // // or the tick callback is blocked in some cases + // if (node::g_env) { + // v8::Isolate* isolate = node::g_env->isolate(); + // v8::HandleScope handleScope(isolate); + // (*node::g_nw_uv_run)(loop, UV_RUN_NOWAIT); + // node::CallNWTickCallback(node::g_env, v8::Undefined(isolate)); + // } + g_msg_pump_did_work_fn(&ctx); + continue; + } + + did_work = delegate->DoIdleWork(); + if (!keep_running_) + break; + + if (did_work) { + g_msg_pump_did_work_fn(&ctx); + continue; + } + + if (delayed_work_time_.is_null()) { + // (*node::g_nw_uv_run)(loop, UV_RUN_ONCE); + g_msg_pump_need_work_fn(&ctx); + } else { + TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); + if (delay > TimeDelta()) { + // uv_timer_start(&delay_timer, timer_callback, + // delay.InMilliseconds(), 0); + // (*node::g_nw_uv_run)(loop, UV_RUN_ONCE); + // uv_idle_stop(&idle_handle); + // uv_timer_stop(&delay_timer); + g_msg_pump_delay_work_fn(&ctx, delay.InMilliseconds()); + } else { + // It looks like delayed_work_time_ indicates a time in the past, so we + // need to call DoDelayedWork now. + delayed_work_time_ = TimeTicks(); + } + } + // Since event_ is auto-reset, we don't need to do anything special here + // other than service each delegate method. + } + + // should be called before g_msg_pump_nest_leave_fn() or there will + // be heap overrun in nest loop case like NWJS#5742 + g_msg_pump_clean_ctx_fn(&ctx); + + if (nesting_level_ > 1) { + // uv_close((uv_handle_t*)wakeup_event_, NULL); + // // Delete external loop. + // uv_loop_close(loop); + // free(loop); + + // // Restore previous async handle. + // delete wakeup_event_; + // wakeup_event_ = wakeup_events_.back(); + // wakeup_events_.pop_back(); + g_msg_pump_nest_leave_fn(&ctx); + wakeup_event_ = ctx.wakeup_event; + } + + keep_running_ = true; + --nesting_level_; +} + +void MessagePumpUV::Quit() { + keep_running_ = false; +} + +void MessagePumpUV::ScheduleWork() { +// // Since this can be called on any thread, we need to ensure that our Run +// // loop wakes up. +// #if defined(OS_WIN) +// uv_async_send_nw(wakeup_event_); +// #else +// uv_async_send(wakeup_event_); +// #endif + g_msg_pump_sched_work_fn(wakeup_event_); +} + +void MessagePumpUV::ScheduleDelayedWork( + const TimeTicks& delayed_work_time) { + // We know that we can't be blocked on Wait right now since this method can + // only be called on the same thread as Run, so we only need to update our + // record of how long to sleep when we do sleep. + delayed_work_time_ = delayed_work_time; +} + +} // namespace base diff --git a/base/message_loop/message_pump_uv.h b/base/message_loop/message_pump_uv.h new file mode 100644 index 0000000000000..a464e2a9963b7 --- /dev/null +++ b/base/message_loop/message_pump_uv.h @@ -0,0 +1,50 @@ +// 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 BASE_MESSAGE_PUMP_UV_H_ +#define BASE_MESSAGE_PUMP_UV_H_ +#pragma once + +#include "base/message_loop/message_pump.h" +#include "base/time/time.h" +#include "content/common/content_export.h" + +#include + +//#include "third_party/node/deps/uv/include/uv.h" + +typedef struct uv_async_s uv_async_t; +namespace base { + +class BASE_EXPORT MessagePumpUV : public MessagePump { + public: + MessagePumpUV(); + + // MessagePump methods: + void Run(Delegate* delegate) override; + void Quit() override; + void ScheduleWork() override; + void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; + + private: + ~MessagePumpUV() override; + + // This flag is set to false when Run should return. + bool keep_running_; + + // Nested loop level. + int nesting_level_; + + // Handle to wake up loop. + std::vector wakeup_events_; + void* wakeup_event_; + + TimeTicks delayed_work_time_; + + DISALLOW_COPY_AND_ASSIGN(MessagePumpUV); +}; + +} // namespace base + +#endif // BASE_MESSAGE_PUMP_UV_H_ diff --git a/base/message_loop/message_pumpuv_mac.h b/base/message_loop/message_pumpuv_mac.h new file mode 100644 index 0000000000000..c82ce5ede6db6 --- /dev/null +++ b/base/message_loop/message_pumpuv_mac.h @@ -0,0 +1,95 @@ +// 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. + +// The basis for all native run loops on the Mac is the CFRunLoop. It can be +// used directly, it can be used as the driving force behind the similar +// Foundation NSRunLoop, and it can be used to implement higher-level event +// loops such as the NSApplication event loop. +// +// This file introduces a basic CFRunLoop-based implementation of the +// MessagePump interface called CFRunLoopBase. CFRunLoopBase contains all +// of the machinery necessary to dispatch events to a delegate, but does not +// implement the specific run loop. Concrete subclasses must provide their +// own DoRun and Quit implementations. +// +// A concrete subclass that just runs a CFRunLoop loop is provided in +// MessagePumpCFRunLoop. For an NSRunLoop, the similar MessagePumpNSRunLoop +// is provided. +// +// For the application's event loop, an implementation based on AppKit's +// NSApplication event system is provided in MessagePumpNSApplication. +// +// Typically, MessagePumpNSApplication only makes sense on a Cocoa +// application's main thread. If a CFRunLoop-based message pump is needed on +// any other thread, one of the other concrete subclasses is preferrable. +// MessagePumpMac::Create is defined, which returns a new NSApplication-based +// or NSRunLoop-based MessagePump subclass depending on which thread it is +// called on. + +#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMPUV_MAC_H_ +#define BASE_MESSAGE_LOOP_MESSAGE_PUMPUV_MAC_H_ + +#include "base/message_loop/message_pump.h" + +#include +#include "v8.h" +#include "third_party/node-nw/src/node_webkit.h" + +#include "base/memory/weak_ptr.h" +#include "base/message_loop/timer_slack.h" + +#include "base/message_loop/message_pump_mac.h" + +#if defined(__OBJC__) +#if defined(OS_IOS) +#import +#else +#import + +#endif // !defined(OS_IOS) +#endif // defined(__OBJC__) + +namespace base { + +class RunLoop; +class TimeTicks; + +class BASE_EXPORT MessagePumpUVNSRunLoop : public MessagePumpCFRunLoopBase { + public: + MessagePumpUVNSRunLoop(); + ~MessagePumpUVNSRunLoop() override; + + void DoRun(Delegate* delegate) override; + void Quit() override; + + protected: + bool RunWork() override; + bool RunIdleWork() override; + void PreWaitObserverHook() override; + + private: + // A source that doesn't do anything but provide something signalable + // attached to the run loop. This source will be signalled when Quit + // is called, to cause the loop to wake up so that it can stop. + CFRunLoopSourceRef quit_source_; + + // Thread to poll uv events. + static void EmbedThreadRunner(void *arg); + + // False after Quit is called. + bool keep_running_; + // Flag to pause the libuv loop. + bool pause_uv_; + + msg_pump_context_t ctx_; + // Whether we're done. + int embed_closed_; + int nw_nesting_level_; + + DISALLOW_COPY_AND_ASSIGN(MessagePumpUVNSRunLoop); +}; + +} // namespace base + +#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMPUV_MAC_H_ diff --git a/base/message_loop/message_pumpuv_mac.mm b/base/message_loop/message_pumpuv_mac.mm new file mode 100644 index 0000000000000..cf725c40a27e2 --- /dev/null +++ b/base/message_loop/message_pumpuv_mac.mm @@ -0,0 +1,380 @@ +// 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. +// Copyright Plask, (c) Dean McNamee , 2011. BSD license + + +#import "base/message_loop/message_pump_mac.h" +#import "base/message_loop/message_pumpuv_mac.h" + +#include +#import + +#include + +#include + +#include "base/logging.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/message_loop/timer_slack.h" +#include "base/command_line.h" +#include "base/run_loop.h" +#include "base/time/time.h" +#include "v8/include/v8.h" + +#if !defined(OS_IOS) +#import +#endif // !defined(OS_IOS) + +#include +#include +#include + +#include +#include "third_party/node-nw/src/node_webkit.h" +#include "content/nw/src/nw_content.h" + +#define EVENTLOOP_DEBUG 0 + +#if EVENTLOOP_DEBUG +#define EVENTLOOP_DEBUG_C(x) x +#else +#define EVENTLOOP_DEBUG_C(x) do { } while(0) +#endif + + +//static bool g_should_quit = false; +static int g_kqueue_fd = 0; +static int g_main_thread_pipe_fd = 0; +static int g_kqueue_thread_pipe_fd = 0; +static bool g_quit_written = false; + +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + +int kevent_hook(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) { + int res; + + EVENTLOOP_DEBUG_C((printf("KQUEUE--- fd: %d changes: %d\n", kq, nchanges))); + +#if 0 //EVENTLOOP_DEBUG + for (int i = 0; i < nchanges; ++i) { + dump_kevent(&changelist[i]); + } +#endif + +#if EVENTLOOP_BYPASS_CUSTOM + int res = kevent(kq, changelist, nchanges, eventlist, nevents, timeout); + printf("---> results: %d\n", res); + for (int i = 0; i < res; ++i) { + dump_kevent(&eventlist[i]); + } + return res; +#endif + + if (eventlist == NULL) // Just updating the state. + return kevent(kq, changelist, nchanges, eventlist, nevents, timeout); + + struct timespec zerotimeout; + memset(&zerotimeout, 0, sizeof(zerotimeout)); + + // Going for a poll. A bit less optimial but we break it into two system + // calls to make sure that the kqueue state is up to date. We might as well + // also peek since we basically get it for free w/ the same call. + EVENTLOOP_DEBUG_C((printf("-- Updating kqueue state and peek\n"))); + res = kevent(kq, changelist, nchanges, eventlist, nevents, &zerotimeout); + if (res != 0) return res; + + /* + printf("kevent() blocking\n"); + res = kevent(kq, NULL, 0, eventlist, nevents, timeout); + if (res != 0) return res; + return res; + */ + + /* + printf("Going for it...\n"); + res = kevent(kq, changelist, nchanges, eventlist, nevents, timeout); + printf("<- %d\n", res); + return res; + */ + + double ts = 9999; // Timeout in seconds. Default to some "future". + if (timeout != NULL) + ts = timeout->tv_sec + (timeout->tv_nsec / 1000000000.0); + + // NOTE(deanm): We only ever make a single pass, because we need to make + // sure that any user code (which could update timers, etc) is reflected + // and we have a proper timeout value. Since user code can run in response + // to [NSApp sendEvent] (mouse movement, keypress, etc, etc), we wind down + // and go back through the uv loop again to make sure to update everything. + + EVENTLOOP_DEBUG_C((printf("-> Running NSApp iteration: timeout %f\n", ts))); + + // Have the helper thread start select()ing on the kqueue. + write(g_main_thread_pipe_fd, "~", 1); + + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode + beforeDate:[NSDate dateWithTimeIntervalSinceNow:ts]]; + + // Stop the helper thread if it hasn't already woken up (in which case it + // would have already stopped itself). + if (!g_quit_written) + write(g_main_thread_pipe_fd, "!", 1); + + EVENTLOOP_DEBUG_C((printf("<- Finished NSApp iteration\n"))); + + // Do the actual kqueue call now (ignore the timeout, don't block). + return kevent(kq, NULL, 0, eventlist, nevents, &zerotimeout); +} + +namespace base { + +namespace { + +// static +#if 0 +const CFStringRef kMessageLoopExclusiveRunLoopMode = + CFSTR("kMessageLoopExclusiveRunLoopMode"); + +void CFRunLoopAddSourceToAllModes(CFRunLoopRef rl, CFRunLoopSourceRef source) { + CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); + CFRunLoopAddSource(rl, source, kMessageLoopExclusiveRunLoopMode); +} + +void CFRunLoopRemoveSourceFromAllModes(CFRunLoopRef rl, + CFRunLoopSourceRef source) { + CFRunLoopRemoveSource(rl, source, kCFRunLoopCommonModes); + CFRunLoopRemoveSource(rl, source, kMessageLoopExclusiveRunLoopMode); +} +#endif + +void NoOp(void* info) { +} + +#if 0 +void UvNoOp(void* handle) { +} +#endif + +} // namespace + +// A scoper for autorelease pools created from message pump run loops. +// Avoids dirtying up the ScopedNSAutoreleasePool interface for the rare +// case where an autorelease pool needs to be passed in. +class MessagePumpScopedAutoreleasePool { + public: + explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) : + pool_(pump->CreateAutoreleasePool()) { + } + ~MessagePumpScopedAutoreleasePool() { + [pool_ drain]; + } + + private: + NSAutoreleasePool* pool_; + DISALLOW_COPY_AND_ASSIGN(MessagePumpScopedAutoreleasePool); +}; + +bool MessagePumpUVNSRunLoop::RunWork() { + if (!delegate_) { + // This point can be reached with a NULL delegate_ if Run is not on the + // stack but foreign code is spinning the CFRunLoop. Arrange to come back + // here when a delegate is available. + delegateless_work_ = true; + return false; + } + + // The NSApplication-based run loop only drains the autorelease pool at each + // UI event (NSEvent). The autorelease pool is not drained for each + // CFRunLoopSource target that's run. Use a local pool for any autoreleased + // objects if the app is not currently handling a UI event to ensure they're + // released promptly even in the absence of UI events. + MessagePumpScopedAutoreleasePool autorelease_pool(this); + + // Call DoWork and DoDelayedWork once, and if something was done, arrange to + // come back here again as long as the loop is still running. + bool did_work = delegate_->DoWork(); + bool resignal_work_source = did_work; + + TimeTicks next_time; + delegate_->DoDelayedWork(&next_time); + if (!did_work) { + // Determine whether there's more delayed work, and if so, if it needs to + // be done at some point in the future or if it's already time to do it. + // Only do these checks if did_work is false. If did_work is true, this + // function, and therefore any additional delayed work, will get another + // chance to run before the loop goes to sleep. + bool more_delayed_work = !next_time.is_null(); + if (more_delayed_work) { + TimeDelta delay = next_time - TimeTicks::Now(); + if (delay > TimeDelta()) { + // There's more delayed work to be done in the future. + ScheduleDelayedWork(next_time); + } else { + // There's more delayed work to be done, and its time is in the past. + // Arrange to come back here directly as long as the loop is still + // running. + resignal_work_source = true; + } + } + } + + if (resignal_work_source) { + CFRunLoopSourceSignal(work_source_); + } + + return resignal_work_source; +} + +bool MessagePumpUVNSRunLoop::RunIdleWork() { + if (!delegate_) { + // This point can be reached with a NULL delegate_ if Run is not on the + // stack but foreign code is spinning the CFRunLoop. Arrange to come back + // here when a delegate is available. + delegateless_idle_work_ = true; + return false; + } + + // The NSApplication-based run loop only drains the autorelease pool at each + // UI event (NSEvent). The autorelease pool is not drained for each + // CFRunLoopSource target that's run. Use a local pool for any autoreleased + // objects if the app is not currently handling a UI event to ensure they're + // released promptly even in the absence of UI events. + MessagePumpScopedAutoreleasePool autorelease_pool(this); + + // Call DoIdleWork once, and if something was done, arrange to come back here + // again as long as the loop is still running. + bool did_work = delegate_->DoIdleWork(); + if (did_work) { + CFRunLoopSourceSignal(idle_work_source_); + } + + return did_work; +} + +void MessagePumpUVNSRunLoop::PreWaitObserverHook() { + // call tick callback before sleep in mach port + // in the same way node upstream handle this in MakeCallBack, + // or the tick callback is blocked in some cases + nw::KickNextTick(); +} + +MessagePumpUVNSRunLoop::MessagePumpUVNSRunLoop() + : MessagePumpCFRunLoopBase(0x1 /*kCommonModeMask*/), keep_running_(true) { + CFRunLoopSourceContext source_context = CFRunLoopSourceContext(); + source_context.perform = NoOp; + quit_source_ = CFRunLoopSourceCreate(NULL, // allocator + 0, // priority + &source_context); + //InvokeForEnabledModes(&CFRunLoopAddSource, quit_source_); + + embed_closed_ = 0; + nw_nesting_level_ = 0; + int pipefds[2]; + if (pipe(pipefds) != 0) abort(); + + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + int worker_support = command_line.HasSwitch("enable-node-worker") ? 1 : 0; //kEnableNodeWorker + + g_uv_init_nw_fn(worker_support); + g_uv_default_loop_fn(); + + g_kqueue_thread_pipe_fd = pipefds[0]; + g_main_thread_pipe_fd = pipefds[1]; + g_kqueue_fd = g_uv_backend_fd_fn(); + + g_msg_pump_ctor_osx_fn(&ctx_, (void*)EmbedThreadRunner, (void*)kevent_hook, this, worker_support); +} + +MessagePumpUVNSRunLoop::~MessagePumpUVNSRunLoop() { + //InvokeForEnabledModes(&CFRunLoopRemoveSource, quit_source_); + CFRelease(quit_source_); + // Clear uv. + embed_closed_ = 1; + g_msg_pump_dtor_osx_fn(&ctx_); +} + +void MessagePumpUVNSRunLoop::DoRun(Delegate* delegate) { + + nw_nesting_level_++; + // Pause uv in nested loop. + if (nw_nesting_level_ > 1) { + pause_uv_ = true; + while (keep_running_) { + // NSRunLoop manages autorelease pools itself. + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode + beforeDate:[NSDate distantFuture]]; + } + } else { + while (keep_running_) { + g_uv_runloop_once_fn(); + } + } + + keep_running_ = true; + // Resume uv. + if (nw_nesting_level_ > 1) { + pause_uv_ = false; + } + nw_nesting_level_--; +} + +void MessagePumpUVNSRunLoop::Quit() { + keep_running_ = false; + CFRunLoopSourceSignal(quit_source_); + CFRunLoopWakeUp(run_loop()); + if (nw_nesting_level_ < 2 && !g_quit_written) { // NWJS#5020 + g_quit_written = true; + write(g_main_thread_pipe_fd, "q", 1); + } +} + +void MessagePumpUVNSRunLoop::EmbedThreadRunner(void *arg) { + bool check_kqueue = false; + + base::MessagePumpUVNSRunLoop* message_pump = static_cast(arg); + + NSAutoreleasePool* pool = [NSAutoreleasePool new]; // To avoid the warning. + + while (true) { + int nfds = g_kqueue_thread_pipe_fd + 1; + fd_set fds; + FD_ZERO(&fds); + FD_SET(g_kqueue_thread_pipe_fd, &fds); + if (check_kqueue) { + FD_SET(g_kqueue_fd, &fds); + if (g_kqueue_fd + 1 > nfds) nfds = g_kqueue_fd + 1; + } + + EVENTLOOP_DEBUG_C((printf("Calling select: %d\n", check_kqueue))); + int res = select(nfds, &fds, NULL, NULL, NULL); + if (res <= 0) abort(); // TODO(deanm): Handle signals, etc. + + if (FD_ISSET(g_kqueue_fd, &fds)) { + EVENTLOOP_DEBUG_C((printf("postEvent\n"))); + message_pump->ScheduleWork(); + check_kqueue = false; + } + + if (FD_ISSET(g_kqueue_thread_pipe_fd, &fds)) { + char msg; + ssize_t amt = read(g_kqueue_thread_pipe_fd, &msg, 1); + if (amt != 1) abort(); // TODO(deanm): Handle errors. + if (msg == 'q') { // quit. + EVENTLOOP_DEBUG_C((printf("quitting kqueue helper\n"))); + break; + } + check_kqueue = msg == '~'; // ~ - start, ! - stop. + } + } + + [pool drain]; + +} + +} // namespace base diff --git a/base/native_library_posix.cc b/base/native_library_posix.cc index 19ff7a4b0ba53..813b59fba8666 100644 --- a/base/native_library_posix.cc +++ b/base/native_library_posix.cc @@ -28,7 +28,7 @@ NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path, // please refer to the bug tracker. Some useful bug reports to read include: // http://crbug.com/17943, http://crbug.com/17557, http://crbug.com/36892, // and http://crbug.com/40794. - int flags = RTLD_LAZY; + int flags = RTLD_LAZY | RTLD_GLOBAL; #if defined(OS_ANDROID) || !defined(RTLD_DEEPBIND) // Certain platforms don't define RTLD_DEEPBIND. Android dlopen() requires // further investigation, as it might vary across versions. Crash here to diff --git a/base/native_library_win.cc b/base/native_library_win.cc index ca9446816820c..bf14cd603eb12 100644 --- a/base/native_library_win.cc +++ b/base/native_library_win.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/native_library.h" +#include "base/path_service.h" #include @@ -12,6 +13,8 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "base/win/iat_patch_function.h" +#include "chrome/common/chrome_paths.h" namespace base { @@ -79,6 +82,74 @@ LoadLibraryResult GetLoadLibraryResult(bool are_search_flags_available, return result; } +base::win::IATPatchFunction* FlashCreateProcessProxy = nullptr; + +BOOL WINAPI CreateProcessAForFlash( + _In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation) { + bool unhook = false; + if (FlashCreateProcessProxy != nullptr && + strstr(lpCommandLine, "cmd.exe /c echo NOT SANDBOXED") != NULL) { + unhook = true; + dwCreationFlags |= CREATE_NO_WINDOW; + } + + typedef BOOL(WINAPI *CREATE_PROC) ( + LPCSTR, + LPSTR, + LPSECURITY_ATTRIBUTES, + LPSECURITY_ATTRIBUTES, + BOOL, + DWORD, + LPVOID, + LPCSTR, + LPSTARTUPINFOA, + LPPROCESS_INFORMATION + ); + + if (FlashCreateProcessProxy != nullptr) { + CREATE_PROC createProc = (CREATE_PROC)FlashCreateProcessProxy->original_function(); + BOOL retVal = createProc( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation + ); + + if (unhook) { + DWORD lastError = GetLastError(); + delete FlashCreateProcessProxy; + FlashCreateProcessProxy = nullptr; + SetLastError(lastError); + } + return retVal; + } + return FALSE; +} + +bool IsFlash(const FilePath& library_path) { + base::FilePath flash_filename; + if (!PathService::Get(chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN, + &flash_filename)) + return false; + + return flash_filename == library_path; +} + NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path, NativeLibraryLoadError* error) { // LoadLibrary() opens the file off disk. @@ -135,6 +206,20 @@ NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path, if (!module && error) error->code = GetLastError(); + if (module) { + if (IsFlash(library_path)) { + FlashCreateProcessProxy = new base::win::IATPatchFunction; + if (NO_ERROR != + FlashCreateProcessProxy->Patch(library_path.value().c_str(), + "kernel32.dll", + "CreateProcessA", + (void*)CreateProcessAForFlash)) { + delete FlashCreateProcessProxy; + FlashCreateProcessProxy = nullptr; + } + } + } + if (restore_directory) SetCurrentDirectory(current_directory); diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index ec584883b96cf..54bad7c30503e 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc @@ -481,6 +481,7 @@ Process LaunchProcess(const std::vector& argv, #ifndef PR_SET_NO_NEW_PRIVS #define PR_SET_NO_NEW_PRIVS 38 #endif +#if 0 if (!options.allow_new_privs) { if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) && errno != EINVAL) { // Only log if the error is not EINVAL (i.e. not supported). @@ -494,6 +495,7 @@ Process LaunchProcess(const std::vector& argv, _exit(127); } } +#endif #endif if (current_directory != nullptr) { diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 57f2f21e9ee03..8e71f0a4a24d1 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h @@ -21,6 +21,11 @@ class CookieManager; class ScopedAllowInitGLBindings; } +namespace extensions { +class NwAppSetProxyConfigFunction; +class ContentVerifier; +} + namespace cc { class CompletionEvent; class SingleThreadTaskGraphRunner; @@ -447,6 +452,9 @@ class BASE_EXPORT ThreadRestrictions { friend class ui::CommandBufferLocal; friend class ui::GpuState; + friend class extensions::NwAppSetProxyConfigFunction; + friend class extensions::ContentVerifier; + // END ALLOWED USAGE. // BEGIN USAGE THAT NEEDS TO BE FIXED. friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index 4ba4d3367e11b..26f9c10d8a1a1 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn @@ -132,6 +132,9 @@ config("feature_flags") { if (is_official_build) { defines += [ "OFFICIAL_BUILD" ] } + if (nwjs_sdk) { + defines += [ "NWJS_SDK" ] + } if (is_chrome_branded) { defines += [ "GOOGLE_CHROME_BUILD" ] } else { diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 93a97ff2803fe..16034eaf3f769 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -130,6 +130,8 @@ declare_args() { # separate flags. is_official_build = false + nwjs_sdk = true + # Whether we're a traditional desktop unix. is_desktop_linux = current_os == "linux" diff --git a/build/config/allocator.gni b/build/config/allocator.gni index 709f80f35630c..83f3be88c2b07 100644 --- a/build/config/allocator.gni +++ b/build/config/allocator.gni @@ -9,7 +9,7 @@ if (is_android || is_mac || is_ios || is_asan || is_lsan || is_tsan || is_msan || is_win || is_fuchsia || (is_linux && target_cpu == "arm64")) { _default_allocator = "none" } else { - _default_allocator = "tcmalloc" + _default_allocator = "none" } # The debug CRT on Windows has some debug features that are incompatible with diff --git a/build/config/chrome_build.gni b/build/config/chrome_build.gni index 4bb4a043cbbcb..db19d5d53ae72 100644 --- a/build/config/chrome_build.gni +++ b/build/config/chrome_build.gni @@ -10,7 +10,7 @@ declare_args() { # Break chrome.dll into multple pieces based on process type. Only available # on Windows. - is_multi_dll_chrome = is_win && !is_component_build + is_multi_dll_chrome = false #is_win && !is_component_build # Turn this on to generate order files. See # https://chromium.googlesource.com/chromium/src/+/master/docs/win_order_files.md diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 83337d52e4b9b..c51cc8b1aed2e 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -446,7 +446,9 @@ config("compiler") { ldflags += [ "-fuse-ld=bfd" ] } - if (use_icf) { + if (is_linux && current_cpu == "x86") { + ldflags += [ "-Wl,--icf=none" ] + } else if (use_icf) { ldflags += [ "-Wl,--icf=all" ] } @@ -1284,6 +1286,7 @@ config("default_warnings") { "/wd4457", "/wd4458", "/wd4459", + "/wd4275", ] cflags_cc += [ diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 0b13302021b02..a9ddd5d5d9ae7 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni @@ -72,9 +72,9 @@ assert(!is_cfi || use_thin_lto, "CFI requires ThinLTO") # For unofficial (e.g. development) builds and non-Chrome branded (e.g. Cronet # which doesn't use Crashpad, crbug.com/479283) builds it's useful to be able # to unwind at runtime. -exclude_unwind_tables = - (is_chrome_branded && is_official_build) || - (is_chromecast && !is_cast_desktop_build && !is_debug && !is_fuchsia) +exclude_unwind_tables = true + #(is_chrome_branded && is_official_build) || + #(is_chromecast && !is_cast_desktop_build && !is_debug && !is_fuchsia) # If true, optimize for size. Does not affect windows builds. # Linux & Mac favor speed over size. diff --git a/build/config/features.gni b/build/config/features.gni index 09cddfd90c5ef..df83cb5e33d92 100644 --- a/build/config/features.gni +++ b/build/config/features.gni @@ -26,7 +26,7 @@ declare_args() { # # Note: this flag is used by WebRTC which is DEPSed into Chrome. Moving it # out of //build will require using the build_overrides directory. - proprietary_codecs = is_chrome_branded || is_chromecast + proprietary_codecs = true # Variable safe_browsing is used to control the build time configuration for # safe browsing feature. Safe browsing can be compiled in 3 different levels: @@ -37,7 +37,7 @@ declare_args() { } else if (is_android) { safe_browsing_mode = 2 } else { - safe_browsing_mode = 1 + safe_browsing_mode = 0 } # Set to true make a build that disables activation of field trial tests diff --git a/build/config/nacl/rules.gni b/build/config/nacl/rules.gni index 9bb4ede89c709..0ab6f839c7e0f 100644 --- a/build/config/nacl/rules.gni +++ b/build/config/nacl/rules.gni @@ -73,8 +73,13 @@ template("generate_nmf") { # Starts empty so the code below can use += everywhere. data = [] - nmfflags += + if (target_os == "linux") { + nmfflags += + [ "--library-path=" + rebase_path("${root_out_dir}/lib", root_build_dir) ] + } else { + nmfflags += [ "--library-path=" + rebase_path(root_out_dir, root_build_dir) ] + } # NOTE: There is no explicit dependency for the lib directory # (lib32 and lib64 for x86/x64) created in the product directory. diff --git a/build/dotfile_settings.gni b/build/dotfile_settings.gni index 8382c75f24f14..e771c611a1d62 100644 --- a/build/dotfile_settings.gni +++ b/build/dotfile_settings.gni @@ -7,6 +7,7 @@ build_dotfile_settings = { exec_script_whitelist = [ + "//content/nw/BUILD.gn", "//build/config/android/config.gni", "//build/config/android/internal_rules.gni", "//build/config/android/rules.gni", diff --git a/build/gyp_chromium.py b/build/gyp_chromium.py index ab2e470dce305..6deea0fa762da 100644 --- a/build/gyp_chromium.py +++ b/build/gyp_chromium.py @@ -61,7 +61,6 @@ def main(): sys.exit(gyp.main(sys.argv[1:] + [ '--check', '--no-circular-check', - '-I', os.path.join(script_dir, 'common.gypi'), '-D', 'gyp_output_dir=out'])) if __name__ == '__main__': diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index 5b4ca3f8fefed..c06a6336afd0d 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni @@ -62,7 +62,11 @@ assert(!use_xcode_clang || target_os == "ios", # TODO(agrieve): GYP sets this to "lib" for Linux & Android, but this won't work # in GN until support for loadable_module() is added. # See: https://codereview.chromium.org/1236503002/ -shlib_subdir = "." +if (is_linux) { + shlib_subdir = "lib" +} else { + shlib_subdir = "." +} # Root out dir for shared library files. root_shlib_dir = root_out_dir diff --git a/build/util/version.gypi b/build/util/version.gypi new file mode 100644 index 0000000000000..327a5c2e5f596 --- /dev/null +++ b/build/util/version.gypi @@ -0,0 +1,20 @@ +# 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. + +{ + 'variables': { + 'variables': { + 'version_py_path': '<(DEPTH)/build/util/version.py', + 'version_path': '<(DEPTH)/chrome/VERSION', + 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', + }, + 'version_py_path': '<(version_py_path)', + 'version_path': '<(version_path)', + 'lastchange_path': '<(lastchange_path)', + 'version_full': + ' 0: swap = pe.DIRECTORY_ENTRY_IMPORT[0] @@ -68,11 +68,11 @@ def reorder_imports(input_dir, output_dir, architecture): swap.struct.Name, peimport.struct.Name peimport.struct.FirstThunk, swap.struct.FirstThunk = \ swap.struct.FirstThunk, peimport.struct.FirstThunk - assert found_elf, 'chrome_elf.dll import not found' + assert found_elf, 'nw_elf.dll import not found' pe.write(filename=output_image) - for fname in glob.iglob(os.path.join(input_dir, 'chrome.exe.*')): + for fname in glob.iglob(os.path.join(input_dir, 'nw.exe.*')): shutil.copy(fname, os.path.join(output_dir, os.path.basename(fname))) return 0 @@ -80,9 +80,9 @@ def reorder_imports(input_dir, output_dir, architecture): def main(argv): usage = 'reorder_imports.py -i -o -a ' parser = optparse.OptionParser(usage=usage) - parser.add_option('-i', '--input', help='reorder chrome.exe in DIR', + parser.add_option('-i', '--input', help='reorder nw.exe in DIR', metavar='DIR') - parser.add_option('-o', '--output', help='write new chrome.exe to DIR', + parser.add_option('-o', '--output', help='write new nw.exe to DIR', metavar='DIR') parser.add_option('-a', '--arch', help='architecture of build (optional)', default='ia32') diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 395d16c7cef21..92d7e37f17262 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn @@ -55,13 +55,13 @@ if (is_win) { # See comment in chrome_dll.gypi in the hardlink_to_output # target for why this cannot be 'initial' like the DLL. inputs = [ - "$root_out_dir/initialexe/chrome.exe", + "$root_out_dir/initialexe/nw.exe", ] outputs = [ - "$root_out_dir/chrome.exe", + "$root_out_dir/nw.exe", ] if (symbol_level != 0) { - outputs += [ "$root_out_dir/chrome.exe.pdb" ] + outputs += [ "$root_out_dir/nw.exe.pdb" ] } args = [ "-i", @@ -161,7 +161,7 @@ if (!is_android && !is_mac) { data += [ "$root_out_dir/resources.pak" ] if (is_linux || is_win) { data += [ - "$root_out_dir/chrome_100_percent.pak", + "$root_out_dir/nw_100_percent.pak", "$root_out_dir/locales/en-US.pak", "$root_out_dir/locales/fr.pak", ] @@ -243,13 +243,24 @@ if (!is_android && !is_mac) { } if (is_linux) { - sources += [ - "app/chrome_dll_resource.h", - "app/chrome_main.cc", - "app/chrome_main_delegate.cc", - "app/chrome_main_delegate.h", - ] + if (!is_component_build) { + # Set rpath to find our own libfreetype even in a non-component build. + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } + # NWJS: we use upstream like config in component build, but put everything in + # main dll in static build, as we did before GN migration + + if (is_component_build) { + sources += [ + "app/chrome_dll_resource.h", + "app/chrome_main.cc", + "app/chrome_main_delegate.cc", + "app/chrome_main_delegate.h", + ] + } + + if (is_component_build) { deps += [ # On Linux, link the dependencies (libraries) that make up actual # Chromium functionality directly into the executable. @@ -265,11 +276,19 @@ if (!is_android && !is_mac) { "//headless:headless_shell_lib", "//services/service_manager/embedder", ] + } else { + deps += [ + ":chrome_dll", + ":main_dll", + ] + } + if (is_component_build) { public_deps = [ ":xdg_mime", # Needs to be public for installer to consume files. "//chrome/common:buildflags", ] + } ldflags = [ "-pie" ] @@ -336,9 +355,17 @@ if (!is_android && !is_mac) { chrome_binary("chrome_initial") { if (is_win) { - output_name = "initialexe/chrome" + output_name = "initialexe/nw" } else { - output_name = "chrome" + output_name = "nw" + } + deps = [ + "//content/nw:nw_base", + ] + if (is_component_build) { + deps += [ + "//components/startup_metric_utils/browser:lib", + ] } sources = [] @@ -366,7 +393,7 @@ if (!is_android && !is_mac) { } } # !is_android && !is_mac -if (is_win) { +if (is_win || (is_linux && !is_component_build)) { # This target is a forwarding target to compile the necessary DLLs used # by Chrome. group("chrome_dll") { @@ -381,6 +408,7 @@ if (is_win) { shared_library("main_dll") { configs += [ "//build/config/compiler:wexit_time_destructors" ] defines = [] + ldflags = [] sources = [ "//base/win/dllmain.cc", @@ -389,36 +417,40 @@ if (is_win) { "app/chrome_main_delegate.h", ] - output_name = "chrome" + output_name = "nw" deps = [ ":browser_dependencies", - ":chrome_dll_manifest", - ":chrome_dll_version", - "//base/trace_event/etw_manifest:chrome_events_win", "//build/config:exe_and_shlib_deps", "//chrome/app:chrome_dll_resources", "//chrome/app:command_ids", - "//chrome/app/theme:chrome_unscaled_resources", "//chrome/common:buildflags", - "//chrome/install_static:install_static_util", - "//chrome/install_static:secondary_module", - "//chrome_elf", - "//components/crash/content/app", - "//components/policy:generated", - "//content/app/resources", - "//content/public/common:service_names", - "//crypto", - "//headless:headless_shell_browser_lib", - "//net:net_resources", - "//ppapi/buildflags", - "//services/service_manager/embedder", - "//third_party/cld_3/src/src:cld_3", - "//third_party/wtl", - "//ui/views", ] - ldflags = [ + # reverts commit a2052ac9b6ec749735f3d8e269bf5a5600935914 + if (is_win) { + deps += [ + ":chrome_dll_manifest", + ":chrome_dll_version", + "//base/trace_event/etw_manifest:chrome_events_win", + "//chrome/app/theme:chrome_unscaled_resources", + "//chrome/install_static:install_static_util", + "//chrome/install_static:secondary_module", + "//chrome_elf", + "//components/crash/content/app", + "//components/policy:generated", + "//content/app/resources", + "//content/public/common:service_names", + "//crypto", + "//headless:headless_shell_browser_lib", + "//net:net_resources", + "//ppapi/buildflags", + "//services/service_manager/embedder", + "//third_party/wtl", + "//ui/views", + ] + + ldflags += [ "/DELAYLOAD:comdlg32.dll", "/DELAYLOAD:crypt32.dll", "/DELAYLOAD:cryptui.dll", @@ -443,6 +475,7 @@ if (is_win) { configs += [ "//build/config/win:default_large_module_incremental_linking" ] } + } #is_win if (use_aura) { deps += [ "//ui/compositor" ] @@ -462,6 +495,9 @@ if (is_win) { ":child_dependencies", "//content/public/app:both", ] + if (is_linux) { + deps += [ "//headless:headless_shell_lib", ] + } } if (is_clang && is_official_build) { @@ -506,9 +542,6 @@ if (is_win) { "//build/config:exe_and_shlib_deps", "//chrome/browser/policy:path_parser", "//chrome/common:buildflags", - "//chrome/install_static:install_static_util", - "//chrome/install_static:secondary_module", - "//chrome_elf", "//components/browser_watcher:browser_watcher_client", "//components/crash/content/app", "//content/public/app:child", @@ -517,6 +550,12 @@ if (is_win) { "//services/service_manager/embedder", ] + if (is_win) { + deps += [ + "//chrome/install_static:install_static_util", + "//chrome/install_static:secondary_module", + "//chrome_elf", + ] ldflags = [ "/DELAYLOAD:d3d11.dll", "/DELAYLOAD:d3d9.dll", @@ -550,8 +589,10 @@ if (is_win) { configs += [ "//build/config/win:no_incremental_linking" ] } configs += [ "//build/config/compiler/pgo:default_pgo_flags" ] + } #is_win } } + if (is_win) { copy("copy_first_run") { sources = [ "app/FirstRun", @@ -560,6 +601,7 @@ if (is_win) { "$root_out_dir/First Run", ] } + } } else if (is_mac) { chrome_helper_name = chrome_product_full_name + " Helper" chrome_framework_name = chrome_product_full_name + " Framework" @@ -642,7 +684,7 @@ if (is_win) { deps += [ ":chrome_helpers" ] } - if (enable_stripping) { + if (false) { # At link time, preserve the global symbols specified in the .exports # file. All other global symbols will be marked as private. The default # //build/config/mac:strip_all config will then remove the remaining @@ -836,7 +878,7 @@ if (is_win) { ] } - if (enable_stripping) { + if (false) { # At link time, preserve the global symbols specified in the .exports # file. All other global symbols will be marked as private. The default # //build/config/mac:strip_all config will then remove the remaining @@ -966,7 +1008,8 @@ if (is_win) { } else if (current_cpu == "x64") { sources += [ "$root_out_dir/nacl_irt_x86_64.nexe" ] } - public_deps += [ "//ppapi/native_client:irt" ] + sources += [ "$root_out_dir/pnacl" ] + public_deps += [ "//ppapi/native_client:irt", "//ppapi/native_client/src/untrusted/pnacl_support_extension:pnacl_support_extension" ] } } } else { @@ -1185,6 +1228,8 @@ if (is_win) { ":chrome_framework_shared_library", ] + output_name = "nw" + sources = [ "app/chrome_crash_reporter_client.cc", "app/chrome_crash_reporter_client.h", @@ -1208,7 +1253,8 @@ if (is_win) { "//content/public/common:service_names", "//headless:headless_shell_lib", "//services/service_manager/embedder", - "//third_party/cld_3/src/src:cld_3", + #"//third_party/cld_3/src/src:cld_3", + "//ui/events:dom_keycode_converter", ] if (is_component_build) { @@ -1290,7 +1336,7 @@ if (is_win) { ldflags += [ "-rpath", "@loader_path/../../../../..", - "-Wl,-reexport_library,libchrome_dll.dylib", + "-Wl,-reexport_library,libnw.dylib", ] data_deps = [ @@ -1309,7 +1355,7 @@ if (is_win) { assert(_framework_binary_path != "", "Ignore configuration-dependent unused variable warning") - if (!is_asan && !is_component_build) { + if (!is_asan && !is_component_build && false) { action("verify_chrome_framework_order") { script = "//chrome/tools/build/mac/run_verify_order.py" stamp_file = "$target_out_dir/run_$target_name.stamp" @@ -1372,6 +1418,7 @@ if (is_win) { # Use an absolute path to dump_syms in case a user has it in their path. args = rebase_path(outputs, root_out_dir) + [ rebase_path("$root_out_dir/dump_syms"), + "-a", "x86_64", "-g", rebase_path( "$root_out_dir/{{source_name_part}}.dSYM/Contents/Resources/DWARF/{{source_name_part}}", @@ -1389,6 +1436,37 @@ if (is_win) { ] } + action("nw_sym_archive") { + script = "//content/nw/tools/archive_symbols.py" + + _syms = [ + "$root_out_dir/$chrome_framework_name-$chrome_version_full.breakpad", + "$root_out_dir/$chrome_helper_name-$chrome_version_full.breakpad", + "$root_out_dir/$chrome_product_full_name-$chrome_version_full.breakpad", + "$root_out_dir/crashpad_handler-$chrome_version_full.breakpad", + ] + + sources = _chrome_symbols_sources + + _output = "$root_out_dir/nwjs.breakpad.tar" + + outputs = [ + _output, + ] + + args = [ rebase_path(_output, root_out_dir) ] + + rebase_path(_syms, root_out_dir) + + deps = [ + ":chrome_app", + ":chrome_dump_syms", + ":chrome_framework", + ":chrome_helper_app", + "//chrome/browser/ui/cocoa/notifications:alert_notification_xpc_service", + "//third_party/crashpad/crashpad/handler:crashpad_handler", + ] + } + action("chrome_dsym_archive") { script = "//chrome/tools/build/mac/archive_symbols.py" @@ -1847,13 +1925,13 @@ if (enable_resource_whitelist_generation) { if (is_linux) { if (is_official_build) { extract_symbols("linux") { - binary = "$root_out_dir/chrome" + binary = "$root_out_dir/nw" if (current_cpu == "x86") { # GYP used "ia32" so keep that naming for back-compat. - symbol_file = "$root_out_dir/chrome.breakpad.ia32" + symbol_file = "$root_out_dir/nw.breakpad.ia32" } else { - symbol_file = "$root_out_dir/chrome.breakpad.$current_cpu" + symbol_file = "$root_out_dir/nw.breakpad.$current_cpu" } deps = [ diff --git a/chrome/app/app-Info.plist b/chrome/app/app-Info.plist index ab859c1f574c1..29c9598b99cff 100644 --- a/chrome/app/app-Info.plist +++ b/chrome/app/app-Info.plist @@ -341,7 +341,7 @@ public.data UTTypeDescription - Chromium Extra + NWJS Extra UTTypeIdentifier org.chromium.extension UTTypeTagSpecification diff --git a/chrome/app/chrome_crash_reporter_client.cc b/chrome/app/chrome_crash_reporter_client.cc index 321dc3efc953b..f8df0c2446e02 100644 --- a/chrome/app/chrome_crash_reporter_client.cc +++ b/chrome/app/chrome_crash_reporter_client.cc @@ -51,7 +51,7 @@ void ChromeCrashReporterClient::SetCrashReporterClientIdFromGUID( } #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) void ChromeCrashReporterClient::GetProductNameAndVersion( const char** product_name, const char** version) { @@ -63,19 +63,21 @@ void ChromeCrashReporterClient::GetProductNameAndVersion( *product_name = "Chrome_ChromeOS"; #else // OS_LINUX #if !defined(ADDRESS_SANITIZER) - *product_name = "Chrome_Linux"; + *product_name = product_name_.c_str(); #else *product_name = "Chrome_Linux_ASan"; #endif #endif - *version = PRODUCT_VERSION; + *version = product_version_.c_str(); } +#if !defined(OS_MACOSX) base::FilePath ChromeCrashReporterClient::GetReporterLogFilename() { return base::FilePath(CrashUploadList::kReporterLogFilename); } #endif +#endif bool ChromeCrashReporterClient::GetCrashDumpLocation( base::FilePath* crash_dir) { @@ -92,11 +94,14 @@ bool ChromeCrashReporterClient::GetCrashDumpLocation( } bool ChromeCrashReporterClient::IsRunningUnattended() { - std::unique_ptr env(base::Environment::Create()); - return env->HasVar(env_vars::kHeadless); + // std::unique_ptr env(base::Environment::Create()); + // return env->HasVar(env_vars::kHeadless); + return !enable_upload_; } bool ChromeCrashReporterClient::GetCollectStatsConsent() { + return true; +#if 0 #if defined(GOOGLE_CHROME_BUILD) bool is_official_chrome_build = true; #else @@ -122,6 +127,7 @@ bool ChromeCrashReporterClient::GetCollectStatsConsent() { return is_official_chrome_build && GoogleUpdateSettings::GetCollectStatsConsent(); #endif // defined(OS_ANDROID) +#endif // 0 } #if defined(OS_ANDROID) diff --git a/chrome/app/chrome_crash_reporter_client.h b/chrome/app/chrome_crash_reporter_client.h index 5a062082a671a..1de868c356fe1 100644 --- a/chrome/app/chrome_crash_reporter_client.h +++ b/chrome/app/chrome_crash_reporter_client.h @@ -24,11 +24,12 @@ class ChromeCrashReporterClient : public crash_reporter::CrashReporterClient { void SetCrashReporterClientIdFromGUID( const std::string& client_guid) override; #endif - -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) void GetProductNameAndVersion(const char** product_name, const char** version) override; +#if !defined(OS_MACOSX) base::FilePath GetReporterLogFilename() override; +#endif #endif bool GetCrashDumpLocation(base::FilePath* crash_dir) override; diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc index 4625e3d396508..47dbe276497e0 100644 --- a/chrome/app/chrome_crash_reporter_client_win.cc +++ b/chrome/app/chrome_crash_reporter_client_win.cc @@ -43,10 +43,12 @@ void ChromeCrashReporterClient::InitializeCrashReportingForProcess() { std::wstring process_type = install_static::GetSwitchValueFromCommandLine( ::GetCommandLine(), install_static::kProcessType); + std::wstring disable_crash_handler = install_static::GetSwitchValueFromCommandLine( + ::GetCommandLine(), L"disable-crash-handler"); // Don't set up Crashpad crash reporting in the Crashpad handler itself, nor // in the fallback crash handler for the Crashpad handler process. if (process_type != install_static::kCrashpadHandler && - process_type != install_static::kFallbackHandler) { + process_type != install_static::kFallbackHandler && disable_crash_handler != L"true") { crash_reporter::SetCrashReporterClient(instance); std::wstring user_data_dir; @@ -173,11 +175,11 @@ bool ChromeCrashReporterClient::GetCrashMetricsLocation( } bool ChromeCrashReporterClient::IsRunningUnattended() { - return install_static::HasEnvironmentVariable16(install_static::kHeadless); + return !enable_upload_; } bool ChromeCrashReporterClient::GetCollectStatsConsent() { - return install_static::GetCollectStatsConsent(); + return true; // install_static::GetCollectStatsConsent(); } bool ChromeCrashReporterClient::GetCollectStatsInSample() { diff --git a/chrome/app/chrome_dll.ver b/chrome/app/chrome_dll.ver index 910fca21d178a..fccabec864571 100644 --- a/chrome/app/chrome_dll.ver +++ b/chrome/app/chrome_dll.ver @@ -1,2 +1,2 @@ -INTERNAL_NAME=chrome_dll -ORIGINAL_FILENAME=chrome.dll +INTERNAL_NAME=nw_dll +ORIGINAL_FILENAME=nw.dll diff --git a/chrome/app/chrome_exe.ver b/chrome/app/chrome_exe.ver index a2d39013f5a5d..17bb91f1806de 100644 --- a/chrome/app/chrome_exe.ver +++ b/chrome/app/chrome_exe.ver @@ -1,2 +1,2 @@ -INTERNAL_NAME=chrome_exe -ORIGINAL_FILENAME=chrome.exe +INTERNAL_NAME=nw_exe +ORIGINAL_FILENAME=nw.exe diff --git a/chrome/app/chrome_exe_main_mac.cc b/chrome/app/chrome_exe_main_mac.cc index 03dfe09ec0189..ca267506769a7 100644 --- a/chrome/app/chrome_exe_main_mac.cc +++ b/chrome/app/chrome_exe_main_mac.cc @@ -149,7 +149,7 @@ __attribute__((visibility("default"))) int main(int argc, char* argv[]) { char* framework_path = new char[framework_path_size]; snprintf(framework_path, framework_path_size, "%s/%s", parent_dir, rel_path); - void* library = dlopen(framework_path, RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST); + void* library = dlopen(framework_path, RTLD_LAZY | RTLD_FIRST); if (!library) { fprintf(stderr, "dlopen %s: %s\n", framework_path, dlerror()); abort(); diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index 41579ba0d09a1..aa97efb4a5576 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc @@ -46,6 +46,7 @@ namespace { // Note this is currently stored as a list of two because it's probably faster // to iterate over this small array than building a map for constant time // lookups. +#if 0 const char* const kFastStartSwitches[] = { switches::kProfileDirectory, switches::kShowAppList, @@ -86,6 +87,7 @@ bool AttemptFastNotify(const base::CommandLine& command_line) { return chrome::AttemptToNotifyRunningChrome(chrome, true) == chrome::NOTIFY_SUCCESS; } +#endif // Returns true if |command_line| contains a /prefetch:# argument where # is in // [1, 8]. @@ -176,7 +178,6 @@ int main() { HINSTANCE instance = GetModuleHandle(nullptr); #endif install_static::InitializeFromPrimaryModule(); - SignalInitializeCrashReporting(); // Initialize the CommandLine singleton from the environment. base::CommandLine::Init(0, nullptr); @@ -194,6 +195,12 @@ int main() { HasValidWindowsPrefetchArgument(*command_line)); if (process_type == crash_reporter::switches::kCrashpadHandler) { + // HACK: Let Windows know that we have started. This is needed to suppress + // the IDC_APPSTARTING cursor from being displayed for a prolonged period + // while a subprocess is starting. NWJS#4685 + PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0); + MSG msg; + PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); crash_reporter::SetupFallbackCrashHandling(*command_line); // The handler process must always be passed the user data dir on the @@ -219,8 +226,10 @@ int main() { base::win::EnableHighDPISupport(); +#if 0 //FIXME(nwjs) if (AttemptFastNotify(*command_line)) return 0; +#endif RemoveAppCompatFlagsEntry(); diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc index 9ff589299bff3..c3b084187067c 100644 --- a/chrome/app/chrome_main.cc +++ b/chrome/app/chrome_main.cc @@ -66,7 +66,7 @@ int ChromeMain(int argc, const char** argv) { auto crash_on_detach_resetter = base::ScopedClosureRunner( base::Bind(&base::win::SetShouldCrashOnProcessDetach, base::win::ShouldCrashOnProcessDetach())); - base::win::SetShouldCrashOnProcessDetach(true); + base::win::SetShouldCrashOnProcessDetach(false); base::win::SetAbortBehaviorForCrashReporting(); params.instance = instance; params.sandbox_info = sandbox_info; diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 8cd410e6d87fe..e48c5170d7586 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc @@ -4,6 +4,8 @@ #include "chrome/app/chrome_main_delegate.h" +#include "chrome_elf/chrome_elf_main.h" + #include #include @@ -64,6 +66,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" +#include "content/nw/src/nw_base.h" #if defined(OS_WIN) #include #include @@ -158,6 +161,16 @@ #if !defined(CHROME_MULTIPLE_DLL_BROWSER) #include "chrome/child/pdf_child_init.h" +#include "third_party/node-nw/src/node_webkit.h" +#include "third_party/zlib/google/zip_reader.h" +#include "base/native_library.h" +#include "base/strings/utf_string_conversions.h" +#if defined(OS_MACOSX) +#include "base/mac/bundle_locations.h" +#include "base/strings/sys_string_conversions.h" +#endif + + base::LazyInstance::DestructorAtExit g_chrome_content_gpu_client = LAZY_INSTANCE_INITIALIZER; base::LazyInstance::DestructorAtExit @@ -182,6 +195,13 @@ const char* const ChromeMainDelegate::kNonWildcardDomainNonPortSchemes[] = { const size_t ChromeMainDelegate::kNonWildcardDomainNonPortSchemesSize = arraysize(kNonWildcardDomainNonPortSchemes); +#if defined(COMPONENT_BUILD) +CONTENT_EXPORT NodeStartFn g_node_start_fn; +#else +extern NodeStartFn g_node_start_fn; +#endif +SetBlobPathFn g_set_blob_path_fn = nullptr; + namespace { #if defined(OS_WIN) @@ -376,7 +396,7 @@ struct MainFunction { // Initializes the user data dir. Must be called before InitializeLocalState(). void InitializeUserDataDir(base::CommandLine* command_line) { -#if defined(OS_WIN) +#if 0 // Reach out to chrome_elf for the truth on the user data directory. // Note that in tests, this links to chrome_elf_test_stubs. wchar_t user_data_dir_buf[MAX_PATH], invalid_user_data_dir_buf[MAX_PATH]; @@ -413,10 +433,15 @@ void InitializeUserDataDir(base::CommandLine* command_line) { } } #endif // OS_LINUX -#if defined(OS_MACOSX) +#if defined(OS_MACOSX) || defined(OS_WIN) policy::path_parser::CheckUserDataDirPolicy(&user_data_dir); #endif // OS_MAC + // On Windows, trailing separators leave Chrome in a bad state. + // See crbug.com/464616. + if (user_data_dir.EndsWithSeparator()) + user_data_dir = user_data_dir.StripTrailingSeparators(); + const bool specified_directory_was_invalid = !user_data_dir.empty() && !base::PathService::OverrideAndCreateIfNeeded(chrome::DIR_USER_DATA, @@ -447,7 +472,7 @@ void InitializeUserDataDir(base::CommandLine* command_line) { // Append the fallback user data directory to the commandline. Otherwise, // child or service processes will attempt to use the invalid directory. - if (specified_directory_was_invalid) + //if (specified_directory_was_invalid) command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir); #endif // OS_WIN } @@ -510,7 +535,7 @@ bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { chromeos::BootTimesRecorder::Get()->SaveChromeMainStats(); #endif - const base::CommandLine& command_line = + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); #if defined(OS_WIN) @@ -532,6 +557,36 @@ bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { chrome::common::mac::EnableCFBundleBlocker(); #endif + const base::CommandLine::StringVector& args = command_line.GetArgs(); + if (args.size() > 0) { + zip::ZipReader reader; + base::FilePath fp(args[0]); + //LOG(WARNING) << "final extension: " << fp.FinalExtension(); + if (!command_line.HasSwitch(switches::kProcessType) && fp.FinalExtension() == FILE_PATH_LITERAL(".js") && + base::PathExists(fp) && !base::DirectoryExists(fp) && !reader.Open(fp)) { + base::NativeLibraryLoadError error; +#if defined(OS_MACOSX) + base::FilePath node_dll_path = base::mac::FrameworkBundlePath().Append(base::FilePath::FromUTF8Unsafe(base::GetNativeLibraryName("node"))); + base::ScopedCFTypeRef natives_file_name(base::SysUTF8ToCFStringRef("natives_blob.bin")); + std::string blob_path = base::mac::PathForFrameworkBundleResource(natives_file_name).AsUTF8Unsafe(); +#else + base::FilePath node_dll_path = base::FilePath::FromUTF8Unsafe(base::GetNativeLibraryName("node")); +#endif + base::NativeLibrary node_dll = base::LoadNativeLibrary(node_dll_path, &error); + if(!node_dll) + LOG(FATAL) << "Failed to load node library (error: " << error.ToString() << ")"; + else { +#if defined(OS_MACOSX) + g_set_blob_path_fn = (SetBlobPathFn)base::GetFunctionPointerFromNativeLibrary(node_dll, "g_set_blob_path"); + g_set_blob_path_fn(blob_path.c_str()); +#endif + g_node_start_fn = (NodeStartFn)base::GetFunctionPointerFromNativeLibrary(node_dll, "g_node_start"); + *exit_code = g_node_start_fn(command_line.argc0(), command_line.argv0()); + } + return true; + } + } + Profiling::ProcessStarted(); base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate( @@ -685,6 +740,22 @@ bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { // partially-initialized, which the TLS object is supposed to protect again. heap_profiling::InitTLSSlot(); + std::wstring product_name, product_version; + std::string report_url; + + nw::InitNWPackage(); + std::string name = nw::package()->GetName(); + std::string version; + product_name = std::wstring(name.begin(), name.end()); + nw::package()->root()->GetString("version", &version); + product_version = std::wstring(version.begin(), version.end()); +#if defined(OS_WIN) + SignalInitializeCrashReporting(&product_name, &product_version); + if (nw::package()->root()->GetString("crash_report_url", &report_url)) { + crash_reporter::CrashReporterClient* client = (crash_reporter::CrashReporterClient*)ElfGetReporterClient(); + client->SetUploadDump(true); + } +#endif return false; } @@ -759,13 +830,31 @@ void ChromeMainDelegate::PreSandboxStartup() { crash_reporter::SetCrashReporterClient(g_chrome_crash_client.Pointer()); #endif + std::string report_url; + if (nw::package()->root()->GetString("crash_report_url", &report_url)) { +#if !defined(OS_WIN) + crash_reporter::CrashReporterClient* client = crash_reporter::GetCrashReporterClient(); + client->SetUploadDump(true); + client->product_name_ = nw::package()->GetName(); + nw::package()->root()->GetString("version", &client->product_version_); +#endif + } + #if defined(OS_MACOSX) // On the Mac, the child executable lives at a predefined location within // the app bundle's versioned directory. - base::PathService::Override(content::CHILD_PROCESS_EXE, - chrome::GetVersionedDirectory().Append( - chrome::kHelperProcessExecutablePath)); + std::string product_string; + if (nw::package()->root()->GetString("product_string", &product_string)) { + std::string helperProcessExecutablePath = (product_string + " Helper.app/Contents/MacOS/" + product_string + " Helper"); + base::PathService::Override(content::CHILD_PROCESS_EXE, + chrome::GetVersionedDirectory(). + Append(helperProcessExecutablePath)); + }else{ + base::PathService::Override(content::CHILD_PROCESS_EXE, + chrome::GetVersionedDirectory(). + Append(chrome::kHelperProcessExecutablePath)); + } InitMacCrashReporter(command_line, process_type); SetUpInstallerPreferences(command_line); #endif @@ -782,7 +871,7 @@ void ChromeMainDelegate::PreSandboxStartup() { // Initialize the user data dir for any process type that needs it. if (chrome::ProcessNeedsProfileDir(process_type)) { InitializeUserDataDir(base::CommandLine::ForCurrentProcess()); -#if defined(OS_WIN) && !defined(CHROME_MULTIPLE_DLL_CHILD) +#if 0 if (downgrade::IsMSIInstall()) { downgrade::MoveUserDataForFirstRunAfterDowngrade(); base::FilePath user_data_dir; @@ -792,11 +881,13 @@ void ChromeMainDelegate::PreSandboxStartup() { #endif } +#if 1 // Register component_updater PathProvider after DIR_USER_DATA overidden by // command line flags. Maybe move the chrome PathProvider down here also? component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS, chrome::DIR_INTERNAL_PLUGINS, chrome::DIR_USER_DATA); +#endif #if !defined(OS_ANDROID) && !defined(OS_WIN) // Android does InitLogging when library is loaded. Skip here. @@ -911,6 +1002,12 @@ void ChromeMainDelegate::PreSandboxStartup() { // After all the platform Breakpads have been initialized, store the command // line for crash reporting. crash_keys::SetCrashKeysFromCommandLine(command_line); +#if 1 //!defined(OS_WIN) + if (!report_url.empty()) { + GURL url(report_url); + chrome_content_client_.SetNWReportURL(url); + } +#endif } void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) { diff --git a/chrome/app/chrome_version.rc.version b/chrome/app/chrome_version.rc.version index 0ec74bdd42dd5..588068457adbf 100644 --- a/chrome/app/chrome_version.rc.version +++ b/chrome/app/chrome_version.rc.version @@ -10,8 +10,6 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@ - PRODUCTVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@ FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -28,16 +26,13 @@ BEGIN BEGIN VALUE "CompanyName", "@COMPANY_FULLNAME@" VALUE "FileDescription", "@PRODUCT_FULLNAME@" - VALUE "FileVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" VALUE "InternalName", "@INTERNAL_NAME@" VALUE "LegalCopyright", "@COPYRIGHT@" VALUE "OriginalFilename", "@ORIGINAL_FILENAME@" VALUE "ProductName", "@PRODUCT_FULLNAME@" - VALUE "ProductVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@" VALUE "CompanyShortName", "@COMPANY_SHORTNAME@" VALUE "ProductShortName", "@PRODUCT_SHORTNAME@" VALUE "LastChange", "@LASTCHANGE@" - VALUE "Official Build", "@OFFICIAL_BUILD@" END END BLOCK "VarFileInfo" diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 75e3062a93b38..29902e34dc69f 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd @@ -130,10 +130,10 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> Disconnecting $1someone@example.com will clear your history, bookmarks, settings, and other Chromium data stored on this device. Data stored in your Google Account will not be cleared and can be managed on <a target="_blank" href="$2">Google Dashboard</a>. - Chromium + nwjs - Chromium + nwjs @@ -143,7 +143,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> - Chromium is a web browser that runs webpages and applications with lightning speed. It's fast, stable, and easy to use. Browse the web more safely with malware and phishing protection built into Chromium. + nwjs runtime enables writing native application with Web technologies. @@ -213,7 +213,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> The Chromium Authors - Copyright {0,date,y}2016 The Chromium Authors. All rights reserved. + Copyright {0,date,y}2016 The Chromium Authors, NW.js contributors, Node.js. All rights reserved. @@ -617,13 +617,13 @@ Chromium is unable to recover your settings. - Chromium + nwjs - Chromium Helper + nwjs Helper - Chromium Helper + nwjs Helper diff --git a/chrome/app/framework.order b/chrome/app/framework.order index 4f8a71752dc76..55c4c16742e2a 100644 --- a/chrome/app/framework.order +++ b/chrome/app/framework.order @@ -18,6 +18,267 @@ # Provided by build/sanitizers/sanitizer_options.cc in ASan builds. ___asan_default_options +__ZN4node14ErrnoExceptionEPN2v87IsolateEiPKcS4_S4_ +__ZN4node11UVExceptionEPN2v87IsolateEiPKcS4_S4_ +__ZN4node11UVExceptionEPN2v87IsolateEiPKcS4_S4_S4_ +__ZN4node16CallTickCallbackEPNS_11EnvironmentEN2v86HandleINS2_5ValueEEE +__ZN4node12MakeCallbackEPN2v87IsolateENS0_6HandleINS0_6ObjectEEEPKciPNS3_INS0_5ValueEEE +__ZN4node12MakeCallbackEPN2v87IsolateENS0_6HandleINS0_6ObjectEEENS3_INS0_6StringEEEiPNS3_INS0_5ValueEEE +__ZN4node12MakeCallbackEPN2v87IsolateENS0_6HandleINS0_6ObjectEEENS3_INS0_8FunctionEEEiPNS3_INS0_5ValueEEE +__ZN4node6EncodeEPN2v87IsolateEPKcmNS_8encodingE +__ZN4node6EncodeEPN2v87IsolateEPKtm +__ZN4node11DecodeBytesEPN2v87IsolateENS0_6HandleINS0_5ValueEEENS_8encodingE +__ZN4node11DecodeWriteEPN2v87IsolateEPcmNS0_6HandleINS0_5ValueEEENS_8encodingE +_node_module_register +__ZN4node14FatalExceptionEPN2v87IsolateERKNS0_8TryCatchE +__ZN4node9OnMessageEN2v86HandleINS0_7MessageEEENS1_INS0_5ValueEEE +__ZN4node15LoadEnvironmentEPNS_11EnvironmentE +__ZN4node4InitEPiPPKcS0_PS3_ +__ZN4node9RunAtExitEPNS_11EnvironmentE +__ZN4node6AtExitEPFvPvES0_ +__ZN4node14EmitBeforeExitEPNS_11EnvironmentE +__ZN4node8EmitExitEPNS_11EnvironmentE +__ZN4node17CreateEnvironmentEPN2v87IsolateENS0_6HandleINS0_7ContextEEEiPKPKciS9_ +__ZN4node17CreateEnvironmentEPN2v87IsolateEP9uv_loop_sNS0_6HandleINS0_7ContextEEEiPKPKciSB_ +__ZN4node5StartEiPPc +__ZN4node11SetupNWNodeEiPPc +__ZN4node15StartNWInstanceEiPPcN2v86HandleINS2_7ContextEEE +__ZN4node17SetNWTickCallbackEPFN2v86HandleINS0_5ValueEEEPNS_11EnvironmentES3_E +__ZN4node18CallNWTickCallbackEPNS_11EnvironmentEN2v86HandleINS2_5ValueEEE +__ZN4node6Buffer11HasInstanceEN2v86HandleINS1_5ValueEEE +__ZN4node6Buffer11HasInstanceEN2v86HandleINS1_6ObjectEEE +__ZN4node6Buffer4DataEN2v86HandleINS1_5ValueEEE +__ZN4node6Buffer4DataEN2v86HandleINS1_6ObjectEEE +__ZN4node6Buffer6LengthEN2v86HandleINS1_5ValueEEE +__ZN4node6Buffer6LengthEN2v86HandleINS1_6ObjectEEE +__ZN4node6Buffer3NewEPN2v87IsolateENS1_6HandleINS1_6StringEEENS_8encodingE +__ZN4node6Buffer3NewEPN2v87IsolateEm +__ZN4node6Buffer3NewEPN2v87IsolateEPKcm +__ZN4node6Buffer3NewEPN2v87IsolateEPcmPFvS4_PvES5_ +__ZN4node6Buffer3UseEPN2v87IsolateEPcj +__ZN4node4i18n22InitializeICUDirectoryEPKc +__ZN4node7smalloc17ExternalArraySizeEN2v817ExternalArrayTypeE +__ZN4node7smalloc5AllocEPN2v87IsolateENS1_6HandleINS1_6ObjectEEEmNS1_17ExternalArrayTypeE +__ZN4node7smalloc5AllocEPN2v87IsolateENS1_6HandleINS1_6ObjectEEEPcmNS1_17ExternalArrayTypeE +__ZN4node7smalloc5AllocEPN2v87IsolateENS1_6HandleINS1_6ObjectEEEmPFvPcPvES8_NS1_17ExternalArrayTypeE +__ZN4node7smalloc5AllocEPN2v87IsolateENS1_6HandleINS1_6ObjectEEEPcmPFvS7_PvES8_NS1_17ExternalArrayTypeE +__ZN4node7smalloc12AllocDisposeEPN2v87IsolateENS1_6HandleINS1_6ObjectEEE +__ZN4node7smalloc15HasExternalDataEPN2v87IsolateENS1_5LocalINS1_6ObjectEEE +_uv_fs_poll_init +_uv_fs_poll_start +_uv_fs_poll_stop +_uv_fs_poll_getpath +_uv_inet_ntop +_uv_inet_pton +_uv_queue_work +_uv_cancel +_uv_handle_size +_uv_req_size +_uv_loop_size +_uv_buf_init +_uv_err_name +_uv_strerror +_uv_ip4_addr +_uv_ip6_addr +_uv_ip4_name +_uv_ip6_name +_uv_tcp_bind +_uv_udp_bind +_uv_tcp_connect +_uv_udp_send +_uv_udp_try_send +_uv_udp_recv_start +_uv_udp_recv_stop +_uv_walk +_uv_ref +_uv_unref +_uv_has_ref +_uv_stop +_uv_now +_uv_recv_buffer_size +_uv_send_buffer_size +_uv_fs_event_getpath +_uv_fs_scandir_next +_uv_loop_configure +_uv_default_loop +_uv_loop_new +_uv_loop_close +_uv_loop_delete +_uv_version +_uv_version_string +_uv_async_init +_uv_async_send +_uv_hrtime +_uv_close +_uv_is_closing +_uv_backend_fd +_uv_backend_timeout +_uv_loop_alive +_uv_run +_uv_update_time +_uv_is_active +_uv_cwd +_uv_chdir +_uv_disable_stdio_inheritance +_uv_fileno +_uv_getrusage +_uv_dlopen +_uv_dlclose +_uv_dlsym +_uv_dlerror +_uv_fs_access +_uv_fs_chmod +_uv_fs_chown +_uv_fs_close +_uv_fs_fchmod +_uv_fs_fchown +_uv_fs_fdatasync +_uv_fs_fstat +_uv_fs_fsync +_uv_fs_ftruncate +_uv_fs_futime +_uv_fs_lstat +_uv_fs_link +_uv_fs_mkdir +_uv_fs_mkdtemp +_uv_fs_open +_uv_fs_read +_uv_fs_scandir +_uv_fs_readlink +_uv_fs_rename +_uv_fs_rmdir +_uv_fs_sendfile +_uv_fs_stat +_uv_fs_symlink +_uv_fs_unlink +_uv_fs_utime +_uv_fs_write +_uv_fs_req_cleanup +_uv_getaddrinfo +_uv_freeaddrinfo +_uv_getnameinfo +_uv_loop_init +_uv_prepare_init +_uv_prepare_start +_uv_prepare_stop +_uv_check_init +_uv_check_start +_uv_check_stop +_uv_idle_init +_uv_idle_start +_uv_idle_stop +_uv_pipe_init +_uv_pipe_bind +_uv_pipe_open +_uv_pipe_connect +_uv_pipe_getsockname +_uv_pipe_getpeername +_uv_pipe_pending_instances +_uv_pipe_pending_count +_uv_pipe_pending_type +_uv_poll_init +_uv_poll_init_socket +_uv_poll_stop +_uv_poll_start +_uv_spawn +_uv_process_kill +_uv_kill +_uv_signal_init +_uv_signal_start +_uv_signal_stop +_uv_accept +_uv_listen +_uv_shutdown +_uv_write2 +_uv_write +_uv_try_write +_uv_read_start +_uv_read_stop +_uv_is_readable +_uv_is_writable +_uv_stream_set_blocking +_uv_tcp_init +_uv_tcp_open +_uv_tcp_getsockname +_uv_tcp_getpeername +_uv_tcp_nodelay +_uv_tcp_keepalive +_uv_tcp_simultaneous_accepts +_uv_thread_create +_uv_thread_self +_uv_thread_join +_uv_thread_equal +_uv_mutex_init +_uv_mutex_destroy +_uv_mutex_lock +_uv_mutex_trylock +_uv_mutex_unlock +_uv_rwlock_init +_uv_rwlock_destroy +_uv_rwlock_rdlock +_uv_rwlock_tryrdlock +_uv_rwlock_rdunlock +_uv_rwlock_wrlock +_uv_rwlock_trywrlock +_uv_rwlock_wrunlock +_uv_once +_uv_sem_init +_uv_sem_destroy +_uv_sem_post +_uv_sem_wait +_uv_sem_trywait +_uv_cond_init +_uv_cond_destroy +_uv_cond_signal +_uv_cond_broadcast +_uv_cond_wait +_uv_cond_timedwait +_uv_barrier_init +_uv_barrier_destroy +_uv_barrier_wait +_uv_key_create +_uv_key_delete +_uv_key_get +_uv_key_set +_uv_timer_init +_uv_timer_start +_uv_timer_stop +_uv_timer_again +_uv_timer_set_repeat +_uv_timer_get_repeat +_uv_tty_init +_uv_tty_set_mode +_uv_tty_get_winsize +_uv_guess_handle +_uv_tty_reset_mode +_uv_udp_init +_uv_udp_open +_uv_udp_set_membership +_uv_udp_set_broadcast +_uv_udp_set_ttl +_uv_udp_set_multicast_ttl +_uv_udp_set_multicast_loop +_uv_udp_set_multicast_interface +_uv_udp_getsockname +_uv_setup_args +_uv_set_process_title +_uv_get_process_title +_uv_exepath +_uv_get_free_memory +_uv_get_total_memory +_uv_loadavg +_uv_resident_set_memory +_uv_uptime +_uv_cpu_info +_uv_free_cpu_info +_uv_interface_addresses +_uv_free_interface_addresses +_uv_fs_event_init +_uv_fs_event_start +_uv_fs_event_stop + + + # Entry point from the app mode loader. _ChromeAppModeStart_v4 diff --git a/chrome/app/main_dll_loader_win.cc b/chrome/app/main_dll_loader_win.cc index 003a3e52a55a4..cb17def47e883 100644 --- a/chrome/app/main_dll_loader_win.cc +++ b/chrome/app/main_dll_loader_win.cc @@ -52,13 +52,24 @@ typedef int (*DLL_MAIN)(HINSTANCE, sandbox::SandboxInterfaceInfo*, int64_t); typedef void (*RelaunchChromeBrowserWithNewCommandLineIfNeededFunc)(); +#define BUFSIZE MAX_PATH + // Loads |module| after setting the CWD to |module|'s directory. Returns a // reference to the loaded module on success, or null on error. HMODULE LoadModuleWithDirectory(const base::FilePath& module) { + bool restore_directory = false; + TCHAR Buffer[BUFSIZE]; + if (::GetCurrentDirectoryW(BUFSIZE, Buffer)) { + restore_directory = true; + } ::SetCurrentDirectoryW(module.DirName().value().c_str()); PreReadFile(module); - return ::LoadLibraryExW(module.value().c_str(), nullptr, + HMODULE ret = ::LoadLibraryExW(module.value().c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); + if (restore_directory) + ::SetCurrentDirectory(Buffer); + + return ret; } void RecordDidRun(const base::FilePath& dll_path) { @@ -131,7 +142,7 @@ HMODULE MainDllLoader::Load(base::FilePath* module) { } HMODULE dll = LoadModuleWithDirectory(*module); if (!dll) { - PLOG(ERROR) << "Failed to load Chrome DLL from " << module->value(); + PLOG(ERROR) << "Failed to load NW DLL from " << module->value(); return nullptr; } diff --git a/chrome/app/nibs/MainMenu.xib b/chrome/app/nibs/MainMenu.xib index dbe2f9e918770..7de16d66f511f 100644 --- a/chrome/app/nibs/MainMenu.xib +++ b/chrome/app/nibs/MainMenu.xib @@ -1,586 +1,792 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + 1050 + 14B25 + 7702 + 1343.16 + 755.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 7702 + + + NSCustomObject + NSMenu + NSMenuItem + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + BrowserCrApplication + + + FirstResponder + + + BrowserCrApplication + + + NSFontManager + + + AMainMenu + + + + ^IDS_APP_MENU_PRODUCT_NAME + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + 44002 + + + ^IDS_APP_MENU_PRODUCT_NAME + + + + ^IDS_ABOUT_MAC$IDS_PRODUCT_NAME + + 2147483647 + + + 40018 + + + + ^IDS_HIDE_APP_MAC$IDS_PRODUCT_NAME + h + 1048576 + 2147483647 + + + 44003 + + + + ^IDS_HIDE_OTHERS_MAC + h + 1572864 + 2147483647 + + + + + + ^IDS_SHOW_ALL_MAC + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + ^IDS_CONFIRM_TO_QUIT_OPTION + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + ^IDS_EXIT_MAC$IDS_PRODUCT_NAME + q + 1048576 + 2147483647 + + + 34031 + + + _NSAppleMenu + + + + + ^IDS_EDIT_MENU_MAC + + 2147483647 + + + submenuAction: + 36004 + + + ^IDS_EDIT_MENU_MAC + + + + ^IDS_EDIT_UNDO_MAC + z + 1048576 + 2147483647 + + + 50144 + + + + ^IDS_EDIT_REDO_MAC + Z + 1179648 + 2147483647 + + + 50145 + + + + YES + YES + + + 2147483647 + + + + + + ^IDS_CUT_MAC + x + 1048576 + 2147483647 + + + 50141 + + + + ^IDS_COPY_MAC + c + 1048576 + 2147483647 + + + 50140 + + + + ^IDS_PASTE_MAC + v + 1048576 + 2147483647 + + + 50142 + + + + ^IDS_PASTE_MATCH_STYLE_MAC + V + 1048576 + 2147483647 + + + 50147 + + + + YES + ^IDS_PASTE_MATCH_STYLE_MAC + V + 1572864 + 2147483647 + + + + + + ^IDS_EDIT_DELETE_MAC + + 2147483647 + + + 50143 + + + + ^IDS_EDIT_SELECT_ALL_MAC + a + 1048576 + 2147483647 + + + 50146 + + + + + + + ^IDS_WINDOW_MENU_MAC + + 2147483647 + + + submenuAction: + 34045 + + + ^IDS_WINDOW_MENU_MAC + + + + ^IDS_MINIMIZE_WINDOW_MAC + m + 1048576 + 2147483647 + + + 34046 + + + + ^IDS_ZOOM_WINDOW_MAC + + 2147483647 + + + 34047 + + + + ^IDS_ALL_WINDOWS_FRONT_MAC + + 2147483647 + + + 34048 + + + _NSWindowsMenu + + + + _NSMainMenu + + + ChromeUILocalizer + + + AppController + + + + NO + + + + delegate + + + + 485 + + + + terminate: + + + + 647 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + unhideAllApplications: + + + + 372 + + + + undo: + + + + 223 + + + + redo: + + + + 231 + + + + cut: + + + + 228 + + + + copy: + + + + 224 + + + + paste: + + + + 226 + + + + pasteAndMatchStyle: + + + + 696 + + + + pasteAndMatchStyle: + + + + 697 + + + + delete: + + + + 235 + + + + selectAll: + + + + 232 + + + + performMiniaturize: + + + + 37 + + + + performZoom: + + + + 240 + + + + arrangeInFront: + + + + 39 + + + + orderFrontStandardAboutPanel: + + + + 644 + + + + toggleConfirmToQuit: + + + + 688 + + + + owner_ + + + + 642 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 373 + + + + + 29 + + + + + + + + Main Menu + + + 56 + + + + + + + + 57 + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 145 + + + + + 150 + + + + + 149 + + + + + 687 + + + + + 686 + + + + + 136 + + + + + 217 + + + + + + + + 205 + + + + + + + + + + + + + + + + + 207 + + + + + 215 + + + + + 206 + + + + + 199 + + + + + 197 + + + + + 203 + + + + + 658 + + + + + 689 + + + + + 202 + + + + + 198 + + + + + 19 + + + + + + + + 24 + + + + + + + + + + 23 + + + + + 239 + + + + + 5 + + + + + 641 + + + + + 483 + + + + + + + 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 + + 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 + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + + + + 0 + IBCocoaFramework + NO + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {12, 12} + {10, 2} + + + + diff --git a/chrome/app/nw.dll.manifest b/chrome/app/nw.dll.manifest new file mode 100644 index 0000000000000..d068c1366cec5 --- /dev/null +++ b/chrome/app/nw.dll.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/chrome/app/nw.exe.manifest b/chrome/app/nw.exe.manifest new file mode 100644 index 0000000000000..d36f084b65946 --- /dev/null +++ b/chrome/app/nw.exe.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/chrome/app/theme/chromium/BRANDING b/chrome/app/theme/chromium/BRANDING index 4f9ef78ce599d..c41083c5aa0fa 100644 --- a/chrome/app/theme/chromium/BRANDING +++ b/chrome/app/theme/chromium/BRANDING @@ -1,9 +1,9 @@ -COMPANY_FULLNAME=The Chromium Authors -COMPANY_SHORTNAME=The Chromium Authors -PRODUCT_FULLNAME=Chromium -PRODUCT_SHORTNAME=Chromium -PRODUCT_INSTALLER_FULLNAME=Chromium Installer -PRODUCT_INSTALLER_SHORTNAME=Chromium Installer +COMPANY_FULLNAME=The NWJS Community +COMPANY_SHORTNAME=nwjs.io +PRODUCT_FULLNAME=nwjs +PRODUCT_SHORTNAME=nwjs +PRODUCT_INSTALLER_FULLNAME=NWJS Installer +PRODUCT_INSTALLER_SHORTNAME=NWJS Installer COPYRIGHT=Copyright 2017 The Chromium Authors. All rights reserved. -MAC_BUNDLE_ID=org.chromium.Chromium -MAC_CREATOR_CODE=Cr24 +MAC_BUNDLE_ID=io.nwjs.nwjs +MAC_CREATOR_CODE=NWJS diff --git a/chrome/app/theme/chromium/mac/app.icns b/chrome/app/theme/chromium/mac/app.icns index 54ee532d7934dbc0a6a1bf085ec25dbb2f260932..1a03ae29c16fa304769c52951f2e81c06e390bb0 100644 GIT binary patch literal 378456 zcmeFZXINZWb|`w3g(QRmIaJO$N2-b<=bSSlgGeHXC{7g_1QJ06k%Y(~k|cz3YNhU0 z=NZqv9^2!2Gvn*=*uKx<+J4j1U3cw5JsmvrzVY{dz4yIpHBjg5v)5j0ue4VQ_ISxng;4v22&i zHA%@@dFf4y<;hn7MCZW3W{PL6`c=Zab;4e zjLQhA&3`_;-P%{8Wy@r2ZRw?!n?qRL+WiqcUM!9`jo!IYgG~>Vk70Y8a&nqPgt5|| z;dc~x)7SeNQQ#p^VDT@1eJxX|%$WSu=hucU&wv6IYGYQGx4H~b;4hcj_4MGg=W9#D znA(>4zZ|Ng^9`Z-=GLN6t%P1Za4V0e@$?OgjS7rN3*qK0-YI4)H9CbdF#oKNm{S1X zSyBm8(_H0GXUkXxOD?yISRzLFRJSKlC=xLX=GO`sk_sbsx1Bu2L ziiAQjJ!3e&SV{$i1p<*o%9a+zJS?h<;ET1Mo?0<4qAvg0@J(}XsX^@NDKeB@GH(t7 z1?~>xi3)k5X=Hns0#~t9jk&pvD%Mp*frrl@Y+%^ip}`L^Z2jKzN57a{{rTU|7y9`X z%>M09=Ep6sEtdP|{h}+YV*ILiESA@Qy?!x3oP43T&y+6r?p*!rsb--%B&BY2yg9+( zD{Yv*SEBR}j7rT;4$qsaR}^nPtdJW0g1mz&pZu&=DJ|Q0R3Y)yN_{$i`o_RENXj;w z@0W|!;<#%aIa0BwT2#7zyHu#jF-Hr;8l6ThDqdPH5Qg~kBpRLGQ>_u^O{Jal6ezvC zG;l#L_pC^LUT#WM>4L+#x7Ed_Cm?UlaaM%kO??fe-xrmo)73-&%hAHTnvl-&%fcPx>dz zH(%k(zfg()^6mGpE&oO({p(|-8<2jgi!oX_d+0nEG4Z!Q1egjM|3^40EozOwvB z87z=+{p;QJel_U^U-#|7WRDR(55?G?eSjb!g{A!U&ysfWEj){~!cn{xJGo@}<;Hf) z`CG4FZ=LVh-mt`9@4_7BH#b(dF>Lecbbj8{lPwIpv$C~4*M_;QEzizv|IM!!Ufj&` zaB=a-*m|*OvD}`UU7j&x&9gnto6puSJ%4h6<)-rYSGzOnA3Yn`d9!)3e+I+)78WLN zBnCZrHKMT>2SvrkMh8nA6oW4wWS?6ZUtYP`Y-;!q%j)a(=#ykaczkMRW?Djok$NI@ z`PCX`IbU0yJ2=#I_d&VyNs%!)E~B8hxF|Cr)LU}eq44fq^Tb%5xvIHxb%$kkrJ)TK>LWoa?NMzumA6gm413$%Xvt46v+Bvq*OzM(O3(a~`+p?*fajN~R@ zcn#}(0*rB!Myd!6&}j`uqpz>g*GDHM+BvX=G{dOTKiFpq-IvG}YPD4EsW<2(RL3I+ z9oYgAO?TBdDAezokpiMGk;)|^g@{9Uw>^CLhzl1N38?yUzhHEq4B9{_6!65X*eK$@ zBQ}Set?GiJANLOl^_%vl@HuQI6K4gbT)5J9;LuSQ29wF=@F@nkAL5Jdb2)4-ot3vf ze7Oa)qqA6SHirxMulfcD`%D_iJorYJHE*q6%%ItExojQ}=eqDH`cdDY0I#cFBp#PT z_8;50n7};Y!sjt@F3xe|k#!^90e<=sBazEsWKWyCosK%Q`D`YGg>JJsB;BCF*QgmV zl967lilBp!=GWpX$y6Gy~ilk|OBFHc2}H&NoxwRL0)0SP(-)&-`4!-B`XI^`NJ zu{De!B)GHqX6_yq%fz+kaA1hYBeaFc#jwIICPgUb!)gz3I82xt=bq;AMItJ*ClABo zd^8P1Atbg$Y!>d}@yx<_v6M{=8?IFvVz4{U#8p!!1%W3P%V29%YK2TJ<`PsblNG$y z0gU9~iD3zS)5R>Z2uz$>t&~eeWOnJb-e?Rn96u$+u-NKD2hWZS#Zs9qVh)2Ee`UA` z!_G%xm>81=3wf27!X$OWCNDCJ&u5X0=HXhtcUL)?5n#q#d@|!An?GL*ZtN*kFc^x$ zp2mQyk1m8pr1`gD4j~OSXPVLU=d*Kat70(BoKapI(uJLj0EFvZY@-SaA`hLeE3{yd zt(aAqf4;HZR(I>oo11lAcQ!1kv+soY4u);*3iHifVV+0AyfO#E{5Oj)Zk{0#2&9b7 z7fVQ(=a#R7Fwgaxww`TV24Uuqy~4s^?e&kI58ZvU)jMzzHP2j)gjsN$rP2q)^Kkibs$(CwyixFrs0hSyK7V`jln-6F}tR%?R;)>RG^ni zqVw_y7#4yskNI*`3Z+Kx8yuaKnv|HD5*K3B_@+myINrm0pFm^Iqz_vzg8|+~zW@-P zpg^NB?%aiNj)ZL-^$q}G_F>83KFG03>+NmO853)}E2Q8BvAnKYh1G{ClPQ!cjZ&_a z$$iq!<29iqj#4gTdF=|T4^t||WzABtf}ePyye2<}=PFWw0%97+142QVeVGy=pU343 z_-Pl0yN!CX3zx?g2qjE!t1wUbGR2?@L|lHs`tV>c!-FB@3k0A)n8q=`;9%cLABI>c zl5kZx5@vx5Un~%dMIxb?;Wg?P9ALcaLkCsD2(kfbPUJWcBoZDjN=7r%y+(YHIKu!g zH+RbH>vDo1lnVJ=&^-e9kM1?-5(Jfh;;RoNllX|lv;zy zM{Ce36=JGqD@b(vAVwnWO7vMCQ=#$n^7i)f)F_zzvhPXs;X@$N@hra5tm5!liC2cf zbJ!JWSqKv8aB1DJ*@q#JN(FQu^OYZnH2%d#NMlcthRabG_cR8MKSm-Q@LiFv&B?8; zMk1YAQ5(7|(na;I$D;}hqYm5G|6ZhTTRypSZ=m!3+qd^RhVR|6bZme~Z|&T~s!=JsLe)_?ksq1SPcJ;=M`I{x_&pw#&W%y?mo;_Q1CWvVqdGoxw zb#rcQZLFoO<)1CL-`-3j%HncMtLy7)%JUNx#MreD?qC+Yrm}o|qU-UK8XCnnE~})j zwY{UQp)5PWk47$g@VIYornI}MxoLAu;VktHj?1lS>%V+?prfuJF~m>iA|BXiYU;$W zflJOzgRgHO-0vEnnwsdT%TEaQ3-F{ncJ*T}0h*~Ork{_me@IMvVNLh=_{G}dEN~HI z(Fu(3aeYu^@N|gW+vwvT9GQ5gsI;iCtRycf(2%y+A1DhR4~dKkYn};~dKq9qM0iYm zY*I>MOh82A>wmi>*2n`UBV*$tW`iXLy|-TgSlYmda6jMVk)K+AnaI$2N&Tl|;^QOd zg2Z~Am$#3889xm=-AXPd^m9)6nOB2&tgYOOdB2E<3shKMw{>X=5ZIJ-7B zym-~f(ke}=W{oItIyxaP;(Cx!tyFs|yj!+z^rZz#L-T##60QD%FC3v9PF6|IuLZ zwoA)BiDbE#r%bNZ>$F-83=pUU0fT{|0mjRr0)3d0$Wj}<^g5*qymB4DS1DD(pgyC& zlGl?U(D8XHTu0Cw3|g(h0Qa?OwZ@Ad*Tq+1SotNH)ab3(>2S}zpsP)u1f5Rr?JbpE zF2N3^g?gLE<3Tlh8@;`Ke87S7@xi?l{4|1u$!2|ED)#0tR2LSyy!oEqzQIum$;pXP z!M@&}Jl~58^|Hx1jOgx%VP{5{s^nsy;BeTFnDAg9vAkw!Bm={Oj-60oSgOhK)cI=@ z>0-5?KOVsKQ;Rbvuhn2!3;4w{Ockq^U$~lTXr1m36{+=ll`yn>x>XxIJXHOD3hAO=QkIJEr_#5wcC8rg|fLtfEn@YMcEDJZ6mYVS_4C^`D)S3ixor+=A zZEW}SnwoScT5Gih%V@>UTF)W-;T-bKXWu^TWb5Dly6qGOfBmNqI+A4k0{Qd5%-)9% zE8qL<*}n%hP%&xZTa0-=m3FE4L2y(Z2Iy$haWTmU3e+P_G0_6kbi#% z7+wGN^VOG@-^Ii213&%tVDs%=^w)1KKLhg6zWn~x?|%Co9m6=^z3{`og&4;D;k9qS ze{BKB?f>ch{~P$$`TswCUxZ-{D^q<-)bIZF6$8Ug{KoP}cJNEf-=72qXaL^&19PB@ z^>7tD^szLkJI z5CEXBS-BeSBKcS(L3rRh60`?S(_SB0&xTg*QQ1>hq+SA z%6gA!>h_a|4cXv^k$%kM z>iqR<8z0^pT7PvvpXA`?=0M85`)XqtB!6aMX`l}yUK_f!wmICh{Oolr-+?YxD#dh1 zZu86M%NM8at__b}>%pj#mS3%G)SaJw@OIkUktEUi1qS-*BxDEO=!XwyFSKneV?|dx zFy_$Kjd_SGPHca8E7{eBr|}PqjEas5_t)}WontoMZcqBER%UNM8EnNk6T?^Lp4}W; zd;Ow{dWtGFhD66DCMPGwM~8XK>8FWjpS)Qg{PjQ1jE;_v;aGD=fB&T`UEQ-!KkAnq zcjc;l!(tNCvd)~zN>7f9@YnF%?F5}4Je%(x9PR1rZO7WqRWw-ghi`tg5_;+sMWpo! ziB8POEh;D|&dW@W4fXRBQ%|4px&HRn$c2)|(z1^7!q$eC(MOL8-ECbNVznV4A|XBR zY-L$lRcS$HQdE$!StDV(9d}OOc`{-?Z%RB@Syynb^YImttpk}WmMZlD(J8rSE9Z{B0(_@3Z)G{%T;&_bJ{kXk6ue!RXHmUH&MW++)Oz^rTFg_|Z|6D_JeLdb-RhS+V zWN zpq}JzRrv+wW%+rv&Nx$qxI`mG#}uEy@Yv+Miu(GB{M7i!U_Wqq zAsVjI==ENKA>pAxAt4Zb3k~%0GJ1-M#~e6tIB^{6)%&Dm`RNBo9C!ljcyLm5YK_5D zYXm#)sW*Zbz;-%v*oDRB3HbJdm%aSbvi-e=Mjf~iy|4uU;1Fpwa;d^oug7&+8X1ph zclhv87aAK*G(7vkeq%sJPJq|&nDqe&hsxwiaOmOq2d8z7jCT6Sp(96+I?>>~53v#Z z!9f_G8|ZBvk5&Zd2ANDKl**)h8Q0zRkPUvs<)}04j7TKl^X!KPysMB_&tIXoU(B7`ZJ95G*9+cz`jd;r2S zhaKn;))ol)d>+T)%AikRCamYmm=n(RfUpRi&S0{*EN$&*;OGEnzs(^#H#)<5m5oCH zNps|<3X5*}5)Ijs>os^YZoV_*<44k;U87h$9EWGcH^>-Uy4X zZLEy6mHWCK^WgGfn_voblg{PX4_r3-r=Rinx;)~@hO2-UU43C`d9tU>+x4&=h0o_O z&0G`b1l+S9xCC39>8tM>c4VB`>0ep z15FAeF}8{2$aLy$R_kIC^qR&??kuLKKgISWfeB>9IR}^!JmYXo+YKCY0-Rm7*gh^MVzYJA&7zEst+_-p86-^t0S~nXVrUAPL?q;sD5;AZ zEvfA2YEKH4k7Hb3Uye50V(~5>x^>xyzyQ%ivMh(?fN(K9{D*G$7wY@JNLTnp@>(#a z46}rnV_0PM8j$u_nBNk}~X6JPX%c|y5QyQ;d&t{W( zd=t-3z$3A9X0J6Qxw@Bw7jEpvNQz*E>}*GZIt!n<6h@=N4)Cay@cwJf8H(V>LY_FN z5A*O$iwiBc{LC-MG+Jk5&}j@~{V1O8JND>YKv0YkPNLou=0sRkaCTEySzKIsSJRmw z3@c42uJpTtIRxy-(u;(&ko5A}+Vb=u3g>K^1q&R*P6lb!nS};^U~+N*Pm`aa(ga_` z!0sLJa6j1n zi_6bmwF;cMDmdbBU95J$7wrD%)fuq+QZq(O--Jdc#Gt|Bz5fP!jYNj)?`*Y3h z8_Ro3#=-7i*}Sn}wfk>xCA$%%#<19gq@={SFmD;rC3+p~evs$N?5#&vtag8R?&;Rh z+M5@ZR0p;uAUZKMBP%O2Eh#2Q%XK21ee(YL(BJ&#`snDyRj~V=R=eLbhwT1IlGqRu zo1BqTP*_-yo0$?9<|Uz=wA%fi!O@Gz?zf+-XtWer?Y_MuOJNL-O3cVBt|%)zSCXHV z924rJWILY%yMKEGFK;R>>#QhjYivb!-{T~Sr!@G1ku}FS%9X&zBe0=KC3|x5f4> zu>y>l78Z0eHZ`}rx##lbi}<kf@C}NH zOUWv&Gnwnlv(pkHLm(yLsSxXYGWP2KpGhW6Dg4e4$k0GSsK{ zO+Djp7#wjCgM9_3!qZ^%(L-p^7!VW`;O*z{=^2*O(0##+Dv(IU&TfOql4J*XT^V&j zHXHzGb$UqesXV=Xa9^OjHsWkcS9>m(B9ely<1{z`cG+t8(RjJsim|6wp@FD@r$+0W zSZZp!P!;UXfYpKqaT>JRWn}lAA&UYlQb71sEt7(mAk+pWpRLEw7pIGyxk%$c)X@p- zIM`)m_g#eGBj7RzctS3cDW%e~^n}W~%B=W6qN`Yr%aXxa6FCoA?Kragu4udz!kQ4E z6)MDv+ACYvi?V_PRVSUe$OA&2n$QL8eoz+7e`U;7Bo-kr0gNYKBrw#C29NhE^hS<7 zfeWT{4^M!Lj=5N;&p~d2D=6|^<$jtK0#-kLYsaV}I&%3|Z$oGnv0R3%v_UrC6-8ZP zevw4TO}xBvXQiVDmpQ^!v=WG&o`AbT7i9G_tXAJe&>}o3;Y*9(nS75^B(a1qME0On zc+6=4xd&kG`$t>^CZUr^%=T;sYk#rK*WK2EC6S7F;6aK+Ekav?)4(O8e_E!Wp>Nm~ z%#W*3$PDRUp6<++p0su4NTd=W2i9N>`I-a_zVpCEFTYe|@`qf(ZxnGk*jL)PXV>1tU;$HEKTxEyw>iZ?UNhu`gvfUjicCVTz&gCQO=sLS z`R+VEC!ivUb>akpBL=%7=CFb2h!!F+cy4GkpXd6{>T4S>5&3+tK*nh&Dqqwh-Ul}Y zE#f_Bs7YYY^XS{P_^OIwxBo7dFcURIy9~!mRi5@$>cd^YPL{ z216*6O{SA#UgGrPrzzaw&t6wrl%qzOnt6a*^%# zLAKwI!c!oh-&2PIgi3{iM+v+Fw%^eIqYR}#vi&E)_D6hU`;}A?=p&Qzq(UwiQB~hJ z{l}5%uL0BFbp3h`k0CZo?4)8kFV|}MJ<1`)Z?*g(VEH=})mf&QOA#z!42hVge-qZ&V{b>`1lI2{J|JjmT{aedlWE2FYqy+M``I+BX{##o&Z*5FWuD|zuV`O4|^Tz7h zI#~Xjla^aI#|IbhK7ac3`Of0t$mY$d`E{`TD|fcHw$HcB@4UZOU@+w0c(XI#+_1HI z_rW4q{*}%3we8opXKug$xQs{R^J%=22k&ps{^oz(TEBU74lMuL!tD0;_3^Ej?{}+c z>cH^uKs8;_{^r%z#KO+)W$-mH>Wbwjw{Q3M-gx@)TnJSf7@L}rnHn1?qXtZV^z_ES z$gP`!JxgHuuixF?ge2nP{f~FfFxbYZwA_NCqQcztXm2hp<>to^mP)cW*Y7>M4wip$ zZg%zAo$I$hd{xgUDS{Ht6qZ(0R-P*>%1H`VQ8<;)-)_(R^k>WS^NY)1`LB$D3otx> z)LCl%NB{KGXXOl6j>;!A zHZ8BL*3@~qyQjaqrQuvbMtpOapPJ`N&b|M9`m(v_jLF*wan$F?vZN)L?HU~)VJe9%Q$2TZCt)SZ6H!?9i zGC6j+wYE3|q7Xjb2DOmj*11*g!tSh$i)y^5_K@m~KE8edp)o1VIVI;?hh`QQX0Ei? zm*=O)g$Mch`RkN2f^@qfA-Sp~I=p*y7v5Or6>@_od2}c&s^Dx? z=;%0EtJj0shw))i!J)Ac;ce{K1f3YrRJoHQ~V5mQtW9d>nsjI6g8 zWLW}(!@~Uif}*0MV`D>fL5=VIFN=fatuF)eB|0r}WF#`SxHKkge3Goebt*vG&p#kA z5TX{rp#cVC*3?hG`uacqV}`@`f+T}ZLmU~6iaT2t8!<6SQhRy=1VGxy&&z=Om1x77 zc79{A{PREls?tN@?PbtGR)jb@wmTl?S8JiBN(V?A4O%a6FJ1e?Kev4OufO=4_k%t3 zMuQ&et+Z+wA03b8AD^T^r~(yXLE;5UMRdl7iAT%N|M82TEi;_p?4!j!y);@iX$*}o zkBda(H5w(Hhrr=cYBfO(qcQUX$v^trAgiKK zDy7jab9ZtdY@0t%aaO2y{TW_Fdke-q)Ro5wEoqd)y|&I>qa-7 zP67TQO24R-Y8465v#2B{Y;>HYRN+b&P`)Z%*|p8p(e{c!7Kx$PL(s-*8*rtaN<|zQ z2KvJW508`4_){v4%okr;nd&_k%ygqj4SKB-_mpS>G^|slB#sP4#1s}sh76696_8R= zDaFwP%hO%CDi1f7QtxHZ0`k`BO-imxNg5sqk18mP2<{&v1DfEY3`N$Du347LXZXPgNRFkfLQ zmHweZ0#&Hg;yPR}MHK|V-td5RG(t>4AH@9w)6@KY&yNdKS_PD#$btC4av(Q)jar8r zsF3#B9S=L8Vf7xN(n{ z7jD?2)#8S|z|pvO3|uuz`Dsh@8FE!1$;a(-iz@5t-HU!46=HdBKaj(SsPOQph_K*5 z$h~=a8Iam zt4&evWJtg9FtDn=JENN7{(Cph2!uMLZ(wL-OnhQud`x6$ps!IU6y$E)?JJNK^!N}- z0tgB4H|vb$7E5@|k+7NoUvC9BV&dV|>d@I=7JJ5IppbwXvm`Y_ zCJ$e@V>a-$Mx;Fbd?8z?<$Ja5%w2$kzA5&eMF}B+;Nw_{SuM)zSXntM7kL65?ev~P zdCBT>TONzw1SL9Q5E9VEdmGLV6$X~{ERQCLrAV^H!i2Hqu9Cpi?i#Hjp%1eSC_0na zX!&(a`NbJ?h!mF`3u(FDQx?1Q`a)bnRv0)25v!MS8?n8KWnF`H85#9Mou!Ew){s|c ziUY?W&H*c~F-Q}O8(Ui&ixOnI+Orlc0YU-^!GULMB6SHxh4K23b0xu{$rrH#YiiKu zJE=iyrU0rIAy2^^`5(U?;rt-K_wN1=enA@1Vc_3TO5)##oWIR>{9x2KUm=09ujC)U zNg@8vszcvPQ+zY(o8KtE==+)FtKGcc*I#~R`EOy?Ov^U|zW*EYA(Yi`5-cbMgVL0D zdEZa6{QePG`0=)XLus1td>}3J<$(PkSQN^PrvAd3w)xI*_!AOHzbQQMgIo++xct>O z3;+HDU&9lh`F@YKFuC)!Z!)LfAC10!1!!#0zFpK_Y=7l9b)x@yG`a#v{d@b-cbTcZ z80RDF9DjK1?p1i=FVxlt_F~e1viva9`kx>D`b*1ijp%_r*yBHzTmAl1zqPyp;zN@7 zJ4LGBAMyQfz)@txQ1WkUTE9Qwhu^-oC=rn~f9m+JEM925_D>!EJ4+C@e;?*)`2&f> zAFc&`N8_#Y{};x?{M!G@{4oAc#`oR&|NrrSXtUn!*ZCBjRV} zpDHg_dEARJzWh@k_==4|9f-}({xkvjo#p38Q3*O$V)^oqB>%s=(J-bI1|x-K-p#*% z_wEn>1||Jvoi+21RF?SGAJ@+4Nzk6Zn}@}}GcJ&}S3_0&A5)?z_rEE`to8D{PXJZ1 zXjK04g8~;cH!^#l_`v9IX16{9PuNub!ymRsf19@-?b8oF@VxUVl*4>a86iW_d-4yP zZR7~>?}8Ei{S#>6TZ}(qPXQb#Yb^B7zA<}f;Xg2RKUfmj@_pFB(tkiO5bl3h2n+un zn*Zqmbl;%|+8(~P{8RfMS@`!KLTHeCKKZzd@CO%OScOU>daY1zVh;5fHh<&g#?02O z<%OkNtM@;BK7}#5e}%aW-rk;i@73+m<*mEVKlnUiMcQvEyvP+LNi_skyn8&Fy;+9zT9?@Ak&h z?CiCvf%zLlgHu1n>;^4AncEt^I5#`DdguPVM=wn8+r4;v@80&x_1SCYg{KSB$c~?2 zO!M06%(8$wJUhR#^XSoww~xm0l2ZKYgAZRkdbG1TH#0pm^K9bfkMSR2oJ*Z8o9jyx zGYc!*PoBR1perI-Kc6syuix(e! zv6jLhQDH2J23=fiS0;^2AW^9#TFl&MAHIC~aASFH%<}W~p6ko;&oOPUH@0|prf*?+ zZRgp`*PlN+Cx)?P5{1F$qpYA<2q|m|kwT-9ctty(zyIRBduvMzBY*YLaveVO1T!R9 z{{7kw5o>bg#_gvsUVQq&MFWLGqY%jqu0Vnk3sBCWkO;U8GLb^3kyNIapTB)B95kt2ZCMeEIgX>(O)yjY=ZYI6|osqM0UdBE&LPG9i~v zB+}>b*NR7G}oAb|(JX(y@-wXRch?`iqyt%QtR5e)a0ZFV<5TBpQX_ zPG<6@DxJ4~P-u7rq=(GW^r)x^m@&Xdua*he6b}N0P9}v+efG(#SC4M3F3y8kUYlR- zSiu-ASwTy;XFKOsHtxTC_5P0@RR{=FD#4XN=ZNH5FF!P6R7^}P9*4!_ag5lQ=*aNU zV1I8vYI@CA%p_TiJU8w+!@i|ae@y?*`0 z2OVkxg+g$3qp`bJQ+;x{e{_OSZ=i4hw(Gyv#eGNH9%I3pYuiyUoP7Z@WA-g)dQkXo6(i12Q=kpjecS>qndPaIiMtXW`3P4DJ zgj{$?fUiL<6|ku8jxJ;xkrcJ?#m8@6KiOEC8wH~sR-I*poX?ZZya3`M<@F?Lp7Y%CVZ8PPnMN1|AVQKte%r4yY_*?Ry-`;LD8 z*_)S-H|DR8HPz1!O-wZpV8sbv{$yZcsB3z5@%FQqZ+`;ObpnmzeB!h#kniBziVi4#s9WCqYs?Wygj2^)yAr5uo=C3J zLbwH|T(fn7E{rU69ZpR8>=cwxs-gRb@qa=`PUZ#8_Y$h!H`rs7fvta2R9{m(#YV zh)gOeeEy3!Pwp@G_g(qB#=*-y-B@Mo=!mJNzq5Dw{-Y1xcBx2Ay327pM^_>=q4A+3 z54v=8s52leGB!RXEh{^(uo%#+s;Mh4uPCpttwG2FdCx%A0zwr6SpZe3kctId7KpXe ziDM2_7MWf0*~uYtIHc2>T0Sg%S(#$bF$J?-o?+r9-(p>sKo*6 z2voMUb!9S%hRKf~-M!IK)&3kC#yc_hM2q?2#md_GJNMs?Dky9k(AUWwtTO7+5#!Q0 zD_kGHps=X8Bna{6Bd|5K^^FbXHRmfDni}eAtIw5}7UgGWq$b2hfPysYv{2H6(%K@x zm`-+gK6UH_i9=;Ky?L;`Sbw&&9q(=Gz+6gNCdR9Bhi~5d;39{?akoA0;7S0C&J#d3 zQw@1a1XvFU?*h&%EUBohscUFzZm6nnsIJGG8XEv|+1dP@%#?%}D_}ra0TDMh$lfBH zsU%m&6UU$ej9m8m!L70ElKw&S3;@oAj=p$W$?G_;!W3-vYUN(ytK6eBJwY!@zM6<~h>FiLRqxlAh2&B@M|#uBeS z-Reuq`(K~bbYKqWT01gwCvLxKrm{~RcX9`Yg2pg_YLa-OWUm_J7NvZ`qhjJy($65c zbxo$$MssUxOH-@)LVa~bNnuWAYI1x`6pFI~y3i*AIboB;2@zVrV>2io&UVLHl+ri1 zuAWIXwPB7vMY(y2ZJTd9 zsqW5Xq#=L_P*a>FZMO^nYFPkTgAuZYK_TE1#DXaW=`G00FM@Wh{4CHCmK7HjmkcR|UC$7<6?h4y^$?kn^hkxYQwMA)VyKQ3+VYr0 zSC86{Z*?VRB&4OZVYa5E*xZ!9olhGGZs1(w!o5f*if{=TRZ$>xAv*)vK*$~5|3g;L?Ev*Iw~?8_$koe4J4k9k{SUv=)5883*LTcI5^gk z(ZQjirZ84$STMkhj0g`4MPU7*%nD^DftA%NG3~U?;Y0RpsMtk-5A#_RcaNe^?_R`H z_T)lul57EX@NJIR9CqcP0#_)5hW}U;5BL1f?)IgmC7wxW z!xU#zyuo(i(&_f{ZvCaNec1-r%K%mx=iK`vGS|;kqa8i~F5Ic^$pM zFE}V5z|Y^`3!2r8xSnS4lv3@F+8jA{x^5MyJuJ_M)=P*dY;0PNxSuA$0gl09 z1Fi@vmqm4T&HwyCe_C2nHb6a9pBkT=dFA03(b5(wmQXI1q?r8nobB_Y8Ix=Z*XgN{;qn7;5fcBnrx}u&wvgbL zgHcw>`Gk{4Y)nV-BP5%n_HG^|DjnenT!Lt8MKkyFNB!v;pq<*VSA77etA+fkb`Rv_HJH|ye3*c@p+di2N$@!`DWosC?ne?Z0_d|2Qo5JK^0@CYtj;OGe@5M=$r>&X{EjZO1ch$DurGGsY#A0 za3!ufq*O^kQ_IyYsy&cWhV;EHqPT+XVt2#_0WzZ>$4)u9k?2s11_fk$ghJ2|0FUD8 zmiNUYfM>s)IK-Ui0VYxyspx9gYspZI#qlk7y8XJ5ZTx=HMf)h{(2|%1Z@;-Ys1nA@gI`*b_ zKq?6?WK?Hw)eC0fLBy26nI_P7AQC(%*aUy_IC8OoQ<1H3vOR3md8EbW@Uc@aL^`yz z01=Q`KxD(Y$CzXU$BGPsV{1xJEC6IauR_RhaNbd*`K)>kus4ZLAlD7zS7ISZ1yXeq zllZ8V&E*qL*c`S2h1q_@WOEd{TTY?J;YonCA60MyN1Q}>ahQNu{^yUbWM-ryfOd^( z33*u~k3Xvi`o6ezSb0Xz&!Mq#+Mg}?>g z0|3-Ty)*DnB48IkyMF?+wZRSoUf7XV8~pHrBPZQx92gIHfweIS_k(N+0N8OZn@MpY z=D&jm$en(-YXHp!kVD!W7!mk>Kd1nNC4mpmFz5^@owZsmp_nUan7?WEzWnG`HQ@k2 zYq2pOK6nhm3_wkg7J(aLF7z-Tl$Vv92;!q5U`FfynN#EQvPK_%T15tksL=xuJPZ_p z2LKdKKLqL>^?h)0;VHn8ZD{EmZwtKl-+uY?&&R0;0pK3c$%k!i?3@T>8l6U?!=Au` zk?inKLxC<2-b=!yx{wM#MKnz>04z@;nw}Yb^jQ_q6ovx%{HlaAwuu|q9@;88ml0)=K~9Hmn!R661uAgYOX0u~Be z=t3;`^dX>V<(OkuqK-WNyqXM((hN8rVY3)CDwT#Bk8p+=UJ&C5RklLtP-(|I#>Z4q zxxJq~I2U7dKZqYPA3ku*9tD$34Cp~IGY-?xldv~1&k5AO0?3gI5kY}r5P!ad_E{Bz zhV%&c0Gm#MMjIUP@_=Gp785#lI06A%THI#t9bFn^2!x8hD%2oiI)ooSXmi}bgG7Si z(AC6XG8iW2A?StzsB~znImQB77JQ22d{-QBBBI#rs1$y@F*;pZ{GI0~7PNXE{M>T_3&Qk{O6F1XF(WgcFfLr=kad9Ck1ooC)A|;6KnDfWkYl z50SRa2U7qvjnB&*ee`KH1xx{MZKgVgb{lOtn++3~Ss2jOiOph%UNCnIO|RU3@Y+9b z;qFiW{O){`ofWKA=D7@-b$KliBi{?~%)Gq-()14ECyxfw0a1WxYeI}V42((vrhzsj z)W5YCcpB#&wCV{q3un3l1{?-6wWXzJcxHX)@uU0Qn#Di+AAkSfuW$~U4jnrNQ8ZA` zfEp0T+A{`h&4cbI_<`P)1BJ#&!yyWP@(=)9Q9XeGX9D0#5^`c-$4%Tlh-1Zwabd+k zBA_;#A}nfayL5Ga^Zt`NOH;GwgWJ|_)N&3SI&|=`tpfopIiCw#34LlD;B~;!Dr@`E z6fhyuI{@|L2jEepps0Ba$W`!w zE_lf!W3x9U=^JR1@8dDsp>eKZF15F z?tNTIb|FENA9U9NO>r)T$DBx3`xk$AxZ^&W{$@VS5f)g%Ie)Kf
    v|C-k1@zj#Qcx$UrGhU0FE7klQwYgBR~w`APxZyj{5mfvm(sFjBM^4 zxW2i)IyC~onrqHgv#goD+G171A9z^u!pBFB*kQ>UcU2jCB+#*gb`?AW-bG|D)||$J)_IF*QbXE0a$%)MXK^7 zAa=~|w6g~a1%Yw^DjtOs0~<()s0a^saZaIaW3v&Y{Ev6~QqyA70g^3(lyZ6JEutZv zWoE-3aEF)}MR8zOZdsbbwj-_D)}NYD_AE*_0TaopR~UM^>1izhIb|O+#Z(iQ zQ3;2#Y}_!&whlhlMi^Gog#vx}iAgRs|ge zUjRCy9P1dJ>`cyowb_-B6p?^bOha5`W7WSV4;$bFL?*EQIO{kYIM$h5_#e}8Dwyiv^vw}nv01k9Fn7eDM z%cI#x_t_k`J8{~{4Z4D05=17Pa~L+7N&;%qaQYq^Kt$>V#E}P^iy_#cso2iDK&?L! zP-^kxWm8OCL_%~M#;%PDO^r4$KCY$1adCGDjTGP2P?T=(96N*D6E$Melmv5`sPZJ1kKWN2Dc^ZbKarW?uX z8?cDnVpCS2$jR0YKXt^x*$wj40DujC0>*6v7GOdm9`*}dmlj|O=%YsJ8kvG40B%?G zz#U=lL1Jyoq?24}=kL!oL82Fur+ZWg#Bqr=G(-d@4X@YXhrp-oLl46PjByd)q17!JHjfJmaE zk_mS=cSw5z16nm`E7u-49B@GY0UY#?0rbLAPdN`P>+T}JDY8NW?rh`OLi)^|*RwfR z5u6wm2OL46CMTwZl#Z;9D~SLMdgH-wrBO&wXhEXD@dJS}1D63HRZwo7? z(@fMu=$!=!l+|tNuzI8W5M@lPeXvi!3W%uSk-)qrjxFLtpdSJP|HB!JYs02{5CfOy zE@ube(e0QW2VTh)klr)7ewKnf1|E3BNDdkMkT8MOf(JWbgW6y}7&vP$s6w23aF?2J z8M&nJ1FZnABj(`kgEJ;_XIV4?rF3($E5$!3Dje#-{epu0V_U8+j>(89yaW%M;WZ1$ zn}#X6fGk!w?0|K97-nt@@CPsg{Kk1LaP-Cbc3|b0WP);XVHA(@3k>puN#X449ddqT z>P8J2;$K{NDJ6In=uBqytl?z~)>VNw11m(H(_wVJV8Gs6x5~OBum-q+d^p%Pew*MF zGB_L%4odTliNSM0K5+VktP2~%bbh%PuU=ctgVGcL1;YW5NoW>;58uK)WZie5GdPAI z|18iMkPdq1T!Mq&28RYXWuW#t)86#-Z_< zwK5t7Y%;QbD6Rorp?eToIJX6M(Zo3nPAGr?(L}q@1qTUO%N__{h@4RL2OYUtEDvt; z`t-y=O@tS`u$bF{xw2V~E^7ar_Th<{t!|YEL@BvoW34em9C}?*zaEG`0m@+x z7uXFMKLi!$qjL&>FRZ>*w6xj`x>Tft^`VnnG&QWf7bs;p~x;@Z;fem^3Oi(=mh4{Pw#485EC(4QT`Ln1!F zgg;;6fJ^Yk*gVFp0$2={pP4lS3`}p(?h0F@@8GxpNk&mg9VN zL~-lT#I@P2tvV@zft(gNd7*8`Af*ZU3g~lek?uonrDkc1^=%F<038}!cXxovq`2vN zb~a|OjrZfZ!E&yvg+^s{V+3$44C@?eK+c8BS7+vy?<{0P1|CEXxDfC_!5UyYNDYYh zq4*ejui`<7hk*B6$y?{w(h!6^Zk0C5p6ID|55sACpa>;bIQ2Ou^smqU>F0D`Cl9QQ+}4(*eP z?~a%OHj3mPF!W$+5$d9PYm>eBB#xX1Zq8-QjqNGt@v-AnRYXbqFqDbh*x9HMxLeH` zs3eFD0z061AcUuZeh?hquYn*uibzA4n750cHP;J*iBLmaL3Nd1xN~QDaeit5&j}Q} z(F_9EeAXaF;ZTVJD2t>U603X1X6BdH?p;r%d4Og?iWc4!0A=W5H=v8uulYH)cF04rN!BazM5no zn#JP9b0@OLF*b)xQW`K!9$wUbWqN*T`S$G#%H4fJjE=}=%|HSS9A1Kmc1p?KWd}%# zTJZp#2h<|F>AH4qE-uYa4K`;5i2#5EJIS8HNKD}|4?}>5gD&oWv-cigaa~9M{{_^0 zL7m>q(%S+{@4YwCdy}XF0YY$hmo5RK3QRy5b3m4C(wEEI)hP0 zQ8&cd6j3xr-pOoRAD%gRvcXAFl`I_^SQZ)<>t4nb4;GuKPzTTVu#SqNd&{X4!^1;; z2TJ2Sblv0Kb#+b07-c<%vGrcK*eWQiy5sPXp^@nmMP>>b-1FvFdM%Wb689WZrW)HU z%crM@hlcvw*pvVZM&e`P6Q?`DY%y57&c#=8lS5=d!@M2*zV7@Zjz9PIC`$qu!XlM8XmDm9p4wwP(D`=&YRxW|?>cJ&Pmj83)s zLl=9ID4h5BK*TY%GcMF$^dQgfc(NDDZOP z?LE;$!5Qp<&YqsWV?#TPmB`#C1E!XzKz0l4eT{9#`6I`AdwM#X_a+BeOC$jZIWxS# zY%toe&MiTGi*xu+@qv!6Lw!d(qI6VHyP!s2kv4ofD`+Wd#&jR=?doc8s>}>=T(c&` zCB4}A3bVyhLp31LPTymDesyzOM`!PFji)-Deh~GK8(r!_U2PQ=&xX;y&W`pb(as1r z9g`%V^_$JEGaGqMj@I70(k#5=ifS4Uw6^s07TKz3K$nVet%pO6ytw*1M z`O)5HKCynL<~FY|8;w&U9D*4};Gej=x}mA*z@fHOGgVEPR~z*-mCZ5_b{}YJY^d55 z=WBcA_fa+uZf3U`6Q~-G2u*dTz?2eEZ9{$I!TqtOYVgBAQR!-^nkF6Tn*{yJk|sio;3XKm;bl3v1ARae!w)+XBPsjI1}>)EF^wAJJ6Te&+W*u}ui z-+P0y^*u(<(4KD|m=$K>9+p`QI)<&F}9VHAu7R_305jz)GKA#o|`8JX!Ru|Y_OXY1!>VrKITW{Wv;9(Z}%@C3*< zotO~e?`Es-HuTX2&}#H)ailiubl1~n>lym^*3HRKYQXZ%2SLS9XJlGy&QL+Cr*tY zIW|gI`&B8{KG1dSGKx}YdN%NFT8F!^6kx?=c&ye07drpX#Ls z0BgT@rVv=Wsw(>wY`=E(^w{WN>)3_kY(x9&jQpW9XGW)rb`CxZw&V9@R8@s)>s6Gk z_DZ?-vC-k4p}AqkV&84x{}ZDCL;MkG}P&HD$Y-^_5rWxY4q`qR~Y{O z(!!%>hWm$)Pd&lf@hS4TK(&M1(I$_Gibm*TtbL^C(|4zuj*P_sYd_%496LMIa&+uj ztX-3UKQrtiGz4vt%!^q+W&wX3rlI)K2< z`N*#0>N^AjUxvS&b)KI>p83)o;7VlGixMO@(TL5j-Ah;YKWz;fG~8|jey?J3wkb`0HqdT?~SVT{qJN%cQ|YIy(1W3auzNJ$Mb z4VwBUmI7oh0MZ&B6~#u2Vzi?HaC1J|qY7`iNH+96D1``*>q2cif!g%et*cgtc4&YuFAU;5j=cx99@wp>WI~tEL z(ffu64ozOTGJNa=sP>yus$ET0k)U=J5X{Hlq;+rJwC*S>FW@z|Mjjn8rI;Db~^u(!RrMhHI;*nxq&WNCN=eEx%O^w?HvRC&EVP(NF+li20D%$ zeU@ui+=>Pukid!KY9l~_$0ZPLo{^EsW*H)rSQ;>CDF+V3)C2Rxn5U@>KuP@>u6<l_H z&C!?uUxY>Q&A>-(12CcX4A*|7vFF6#Yah3RYd_Sq@5sqxog+`Ub`4bxmCb~;Bb3C> z32^{{^Wb-KS_UxloZNzp^n%~hQB+vKk>=?s zXc^`Kpg(UhGVZ$axF2unW z+x0v|Pr!FtM)uCU0>Ib1v$IQf7XkUs1p|%t0psLQdgvTmYjX~4m*1+UA?4a%0@u#= zF6i!WZax66eP3No-)v9+GhDl-@HT9n#ZK*|tGmK~sa{+HYJvbL8NmzW!FBs1jUze&L?|t%uscwO@YB zwQpXJCTby^2r0|#!EJg$1%yY%Bw+l2To)FVl$KSL<^vrqFN4&Ayq(0DqhD$ELq{X} z$O_wqHVFRp8&w{2?H7n^e^k_dU_ZF_>W)KfertW>vGW(_xpsy18x#mLGC^Vy;G&K$ z2p9+ieoUNq7I^C-7)^VHyNilBPsHrp;X>q`{v-|gTHY4n(bnK` z)3Pv}MZ{aPVnF7*#lp&p@-oN;$Pe-vNGHU)0OQAzpGvC$HB;WYew_kw?T5j&Pt@(I zy~%V5!L>(A#Ep&M+Rt2gt;1_l*a^&gPlZriT_-MOg=ONpnko@o zcEyFc+387fQ5fBM)SKmRqmwz>3UY5><+$(6!#aP6nTwQK8a zUQ1p@Jwv4BgkT}r6KJptQu~BNL?cV$&ita%y{x#VcAvPSs+tw=udl5ZRqokcNDbx? zb8io>qmlMx3mv7A)>J3L0)3+3d0U} z2?SjuF2u{nKR9fATw-cgPQmVSwyL(iQCwADS1oSZS6@SrdESl;%qzrcUt%dwe+)WEI9XSuI9ke$vRpbdq@A6%7vB7b%m{Tx#zySjtDz*nRm=I(1(5AK z@s>5r`n0r^d9r<@0w{B8E1K#-7hkxNqKq=gZsGx3i^z7w7bT@-=k2bjtKZk&+1b9o zzMd^DKx-4@skt2A4i1_m(@Mfcnuxy^0Jfo?hJyUFbUP|$fo`vyxH+H?=1P|)G0kBH zf1NpCljNew98!;3$EQ6TY(o~>mV+MD~@*Yl$fMMVG=(kB`pQbjHM7R zgjAuO9vtq?2}N9}3EwBRC;|zHKrZU3D$b+r;ZZH{#Xd#bmDFLoV`PDDs$sFCeiVil zMT3yJ#vNnJ#X2I00A^M~a$IDzaQl|%h}dLl@Et`F1VFHtJ5q-^*#n|KLdIBgp@l3~I%}oKHJBn7&|swJL_Y&;=b{Ru zV^06eMxd?SUBPcf`Y}N>LEef zVPO+iPgK31w=25Y#TkbIzDH776}zW=yO9C1Q-a@IX=13Qq6DZ zUw46{hpVfLy^T|NzNlKbr+kke!alg`)Kz9MZd4T0@1Fyx5t#^|_nMtC;mI7<4jskA zm%^>!T-En+#oo@^4#tL;BW+8FCJ=gTa(8n_n2&=eKz=uSTL(w9)h(((T*Hc$D))#o4Asf2 zB)xMrr7+uVX>VRQ5EB=f1af0-QFK^JJn`iU%39dGGGu%F)r>yh5rh0Zd|R z8>GT=MhpY%qvefB0LSdMOXK{gosZ}+iJ>_h;x;k=KbMZARVdyAtO?v>U zT`G0m9w1Xsq|zn2shQARo|{r!bEPS_FvLz+7?#$2^t=N~b$K9+fc|)RxH%#XJ>M4j zD;>h~g;f9`>Z&SA_w06}`+2~`^hBV*CdNE1rEMJC9v_ti$Y|YTxIJG%S)0dQ-(!R~ zN@p`C8io~SG)*sC+_5jVu|=^OoXu;TEnHlkkju-`$~|E>;(@R|)v{&9Wf{D!@TViN zhER1}#KQ|^prxe1!R-m#Qy^2}3Ea;0F?acmU!{$nb`cxO=p~SW3b2=T5a4cqG2aFY z)4|a}=qQI5aTGe3IUzP9Afv2u?_TW1wL;h%MPZ6t)WMQaHe8a6i*v-)Ybyf-2iPbT zync5qf(M9kSHj?;v2YWBY+uAVV@UD>TWDvbD_bf+I0WCy#=*``XfJj^#yAHDY|9=o zxn*T!?o`(Z5zUsn(@}n#8tvRjz)OKgtl4T@*YmW|S`KuNN+yi!Dd?`GNs&&hsVrU) zaRMaP3T_exT4Ol^Tx@N~nSnw?tUzpwf zR(zL;Og4W*;qEfnRcr}TS0*LAgC`GL5d0qId~!$O zuQt*onAry;WTdCVjDu9f%;jVx$ApE28?M|)xe&;Cg)zX=BL@;%3L{DZazVsHE?~n| zM8qe7h%Z!Dq~I|jr>ljCAHeGhEtiw&g?!1>a4Vsu4&T7ScY9KDLSkB0ZUGF|ijwT) zxTuhT5I^M=Anf$Hz*v%q7dKlc^^GBPOo>C{6QWZ{;u9oZ1)XaM$A~Q6O^DxLgU``s zOUuR-F}7A1Up-p5x=8~~!kmn(bmSl{Dyt~Tir*dvTP@gW!>X++xL%_+VqwxV7Zo?d|_OIL1Ig}p^8Kxih56)A))p~))h(RpDBF=@0so>1{53?m6?rt7Ht z>9a`1j{r>++%qx~S!kPE8C&fgKFPZ7KR;U_sBEs-8I9`(Y$~4KYI4igZlcK!qX#jT z3rPW>n@m>Y7E>ybAZ~7TV7i7QMC0Q9U24=k*0{=K1;!mBk+&ND2(S=xv>%GhbuA2B zszAhhU;gPIe*2?#yIpaCWC6N3c{*)b2y#>%j2C_%A-{<0fcLA4#DS+(QqACic&>pf zMRD^$yc#qtyyGGghkV)wg!jNbCpOT9G|0EGFbu4%sv7ZTCvW`nos&nxO#KkW>FnU( zVYzzMx(#&bgzpGU0z82f$}Jr}Y9aI-L;{MJ_UX#UQ2Z`VBp1a)F9u)<(HT;B23{k$ z9x1swVt?a-#`hkw3D0c(!PVW7E(Y#SuyGw+be6B#rl6<^S5Fl%1$e69y`tKNLgSSX zsWeZ<$E0E3-29k~FH}?Jh7lu)7+22q&5_qEPZlDD1{yeW81Z*hi<$t(>zJ9@w3VXn zGtUv0yn~(MGWo6Qnjk-jS*g-r3g-*87Q2aPUL;4y&yV9%I-W#|jhB(8fUA&jqk02P zBXgc}u~^E)^ZXK<9=uVP=FLO(We4;1D>f=>p#SmsS~$-ZO05C$6B)E)aLqzbf)57@ zkDi1%P-QGb?oN2<$%8F4kkTe90UQK>0ua1M_K8bB|JkMSNJBJ7Z^f$3%Gw4d@Ks5v z4lWvq+W}Y;sW3&=45HxCAoL*zqZ0*Rs7}H#t|F|4C8UYSlMQ)VM*6(?C;a<`2Eq7` z|MY}O(W!zgENRGsy13l z(XXoMz}@4e0dySQj{v&6yHt@%!myU4U_Bcf5G-J3s_*zb>E2i#>Fep^YiGQAIpAzg zxuc9a!gx&aZX#nu%b;sSM(dyxfJu-nz}W}p1Lsygq1{zUUDiPs3yef)qGxPstRM6Y z=-x%3dmcddFn6t`D>o{^$V7uMScaxTaz7g*ZV2Fq5#oVXb8-|^q>wvjC$4+~xpQ(F zC|-#C)9geJ?3^^jT~GR`4=Nb0H#IRTH z!i{8z(OS8ME7opM(1g{*nl3RhHNveMdW)McVhpEY13g}28$BMjbQqEO94H^#0)U+! zZ(vAp6}vk6!q*GZ+|?G#Ed`alO;rb>?_yIqWagk8@g`Un`O zu%aBZ9v2b|A*(B*5b;aQx;iIhK75PIYOiXnZ<6>dwO(3M5X)aLyKvI<9DqW$gp`e<f~CvXfyY(Rf!!cBh2AqU(1Bc#77G9ZQbmC(tbi(zSl|?; zlGM_lqUfuhqUbaeP}6{j4Wmuk0x5}JT_eu-Ra+t_yLkD^b=x!${5s z7!PJf#8c>Fx}kWsF=WY7k)`>77q+(KEnyv+L9!6ry z!UCkkxjI}UuoS4IgN|-YV@E@!uxeMJ<`TJOYu0aAvr$Yd`%N6 zcAh5KxN!06b@H1Owt{KIgV1kO!X4HK2Py08VVMF3L`@J=1Kh_L*HHK+NfMJJbpr4=YQ z4tog(lfFLoG;B2sY5zcUvGD>ToM^-huwsa;;l$08=Ke&QuauJJ$1d;IQqrIbQd@XP zhZI#`mKE=;vTEh}jhl$f#w<6W^etFGCMzLSpQ3IsA@q6B4}?tOXk)yHVlyF+HL5n0 zC5mufTEXQ}HdqRs>y`#_(D}s@9h@q7WNB#{?Gz^Zm@Av@6fq2 z9Tg3I)?k^wmSbMLjjrMr1qBur&M10?6NFx5!Bm-6n=nu;vWEIl8~BknI!?oqaw6?q zjfi8YH>7XVE1fLSJ1;chBj*;(5|sQxF>&<+rPM zrr8KNpa8y_Ss(!cVn7LG0FppO<}l7xP}+pEk#d7+DFPjeD0K`M*AN;Q>QZTI*21Pi zt`&6^gMBmIfXo9!ser9UbYu(%ne){&vFl^?BN`Td{Urc#(OZyGh3>C1mBVV{2@My} zK8hdl{w7thKj@h(3>`Az^wm@>y2m@SytZ$THLYP(f`a_L(%OcPd8y&753`L<6tqAn zp#i-;x?zd*Wzi)yuxRjn8GU2=j>g-hhMUMis4Anb4r;t%o*Lgo z)OeV<=V-S%nGR${qnIDwmNk~6cNI$KDD}x=GvI_6{rNGi!hfTklME~taw)vsluS)k ztHYy**dTW=Z}(b;HCf@}TheuSVmEH`NVn6(!yN%Sl;B&8mKYW)Rcte$)lEfrfa{qo z#gO9KivHqsg&PyIb#$sTHqh5luN?1dFZ7mDY?A+2ojgO~c@1XaGUZ}>2Q;6AK zixdV3PY0M=2Qh#O0rb*oR(g3t=LHSbLZZVHUF{ed(BW(J9UMT1@9pRvoXFAC#!JwJ zjfG_ut_6fu%*`#NjWydMMNTLFj{N&)e{!Q-b6xU1>n zH>n;JHDm!@fY99!{?=J8gliW}P@QG1)k1nY-LP!p4mBuA7utVjbfB-JD#Mqrw=t8b z@U41d>XOw4)`8ho9a1XXLJiv+77yKu3c0H&I8(&dLYsxSfV4rUA?bw(V6Gh1hoH+I zA#PN*;cUSj)U=fB8_rCF4sT`Cp3>o4i4LD5I=qtT@UhcJlM#N1)kL}qa+aZ&a6!l2 z`m%O1sMhHq=jdd^XXz4>YIiP0u?&#g(w@Q<2PX7ZLXLU5%0|0pPagvwzP}{a$ymo^ z9uMEj;o%wvf{0y@@$f(m5{Z_HOt;W=2Sjqt3+XL0F4kS$>;!JC%R1b+;%1rrUF5*! zMo)xHVOXdLR zr7R+k8wXE4uI{OAs4kDRLJ;PJ3tsXy5tWX+Db`d0O@p4%R5Z})c;-`;g@RVWxa@qNCJGvBi z?^2hJUA4Uq-ds8w&;xij4ZV(%;S)qW`x!)BQ^!nS*J<#qCJ^xh^N4tuI)(x(i5%(N zEjQh+v$)u1ZDsMsEEcIEU;u7?V*U~)J~9eSyfD&fn{JTvBErN~<}q<&@06#QxQZst zCoaao%1XqqwwB@JJ{eD=vUuEb&{XyyMtnrdi0gSIc<2x#u8Lhk;In8k{~1QyLYY!T zQ3rFXo3*OOlT=B?qRD78k~}H#2^2pvbhwR8B~aYg(k}s^xB>@?Z`RP?2Q_+cp^z97UYdk+BdtsEfksN)`2(gaOCa1?+zv;p@* zw3i|`3~Q#qZN`Y8QB$91#1A$UM!Bl$B}o}^MUD~w{QhG`y#Lq<)&Z%$U}4ejS&eN& z$f*fhOq$A$Rr7p!X}pvV*8?A}%*#ud=fj2I!+ZOV4em5mql8YJxn%-_O93Vi%r>5m zvPs^^@!noS#8U!oo*?2IpCIBnQbhb%$96ppRF}gBDMSbmF0b@dwWWl3M>7%Pt3ilo zlzX8mgm`CrGYD~a9g}1qc_PFWI6}NA z&C(|xgm?=G@t$1*4IE23!+|x~OmD5DCMfCeYb8j$0FbzMte=^=EkWXGkq#jQi6==R z@$R-XbGQJ+#+zZ@>#3V(9_(o$OuQ)0Pw?{l^O*QXs2tA-Ep?}$loBzAiSLUw)6&5u zG6KSMG|UJSZvZB~J1M|%!^SALlwB5tiEDG1xNAsyDO^X@4Xw3F4m?DdYVjOW8`>MH zYk`TU0uwh6@OcIk-w|c$0Zbe$(GyI3PXjP+>AUIC^Cc3$DhJJ{ScdAS6_C5L(lc%a0$Xj+33H$p;LPd{f9JI|0fpnzHFsj1{i-rlwbb{>IINr{mG?gE~xzdMrpS%DHa33ay)2wp31<*_}|-Fodh zR}UMnNMnu?-_I~}b3eR!?&{^a*;CiA-}}>@2_~=)l=#sLS0-P(eFX&fm7DkP-@1C? z?4;z;<&(3=&Vv$fm>L^CbM?~P+|>BgnJd?CTsb>^Vq*OG==AOW$r&*y@h(xtxtGRH zj8BYBoIHQ&%JpkkE}c6$etdlLxVX0e@@ubLxq5DL zY<%kVH(ncm?S~z}#0Pr2F3!zOPEJgoy?*1)y)$f}6$Q#!22`HDd;9vevlHXf6B5ap zsZ-~=?=kDz5}i-IdVT8T)D)70-+A-=UN-{@zF(%RqwidH;r{I#*Uz$(i$>1eINjPi z{5rGY_~ol7&ox#}ot!*%?WJ39-mLd9fG177(km|F{q`dH zdC$J;lUJr@re{uGLfYnsGijFkxYq!uZ3`#uR^(|#qD7v*Y5egwU%z$p^2zDx@ekj+ z(0B4|_H|}$fAXSJH_naC&CZ^G>E`VRSIZq)o)$ybJbYDhWOnxC+3UA%-MilxW=t_uCZLXe0>eS9 zrKF^Z)78^b!A?a-1p6Ynpcyo|zP@MkYY%VVdig8{^~~v)CVnmH0VqCuoKi6zpF4T_ z+O6Afymd0e90yDTBMX7Er++A=&rJhaEY8vdSqv-|Zp9#P7l9?^Zq+l4IP&2B?ORt* z&zw9X`R%otQy03&7|r(G38$}|Iy`f7?&7Umuf27p%nnCZR6gZ9xcdZ05FMJHm6grz zWOHK?CkW>8<$SEoxPkiiVKW~w~n5D z_0`##ljmQ#ef!~SP44=1HDqXEix)+nU+`2}0C{us^7Gk(b@@o73~(6vo8z~KN~=$>zb(2l_MMl{ zPR~u%51gI4|A!fX;)fb*PhWkx|K!QJE4T05{lU2$bGWy(bqvgGoIL!3BV!Yi(=)S? zce-F#(e9Fx($bQW-O$gRgbX4%!vZ{=1r}5mR#)2~_QYHF?%cVK^)@E?=+el{ z5rG|(Cr^$|Pt9Jq`Rc20->i1R{R7fZpaCvkz(om;%>?8O3K)1S(n(aH?j+J67w-bl zkPSBi=1CBMbiOH)Eg`A|!f770o1)gZXG{ZlH|} z587Hzb+_Jn75z0iH8V7GX7b^uM*xbC_Vr95Ez$Jk%;j5m?!7&eWQ<@lbqyVk+UEp; z*aQBWhXmHZZiOOo?VdfgVlna!1H9!pW6CML9ilv(?W{}??y04#tryt$;K8f6uFZ~5 z96x?+dicadD?srK$xjAGM|#IkjGuY=)*J6!E49(l)z(l!N_W1!vnLSW2;>Eq3fo;; zUcrj1s%!U^@7Y&Z3+NT{N{Xpv;EM_L^+R?~8#6#n>KI?6l$jsgzl9|7$H%8mojhS5 z*@y(_LmJGnyZgtEADzB(^Y&YJ4|w3FNJB*pwFXEr`TEb})0sQ+kT|*=_q{cB_4^wu zDqxf#jf+@Vfuz|5xdavyMjZr!&=kn+5Aa)8n_qh4omXGEHak3ee0pO1@Zo-d;#~*Z zk6#}f8yY=*{pGuFAB{B9LjoYe9?U6`Jg85CO_5|bn^*-xPJmxFwloPvO)!MOxmH1B zNl|`Ib{eo#=s74}H}LSr`kM3B{A8u_OzjXDr zHx9TWL{S5zp1v`K6`|&ymp7yWUQSNmky}_yG*9im#^#o`gZt|n8oN5$4m39+ReWW6 zX;HyEJxwhovttWCaJ|g{s81R8Rw{GBj}QV=uc^7h{{$6M-{qAW@Cq3-g%$oBrmVOO4k zuBrmM1$7!JgbD=%0bXJ%%`?-*Wfdg0xwWJ7(4qaUZHK}xo-GCEwj0zZF;J5NAKxNueI{wCD;Z> z2!b~NzOl{>YMfgVzbtL=P87FgtLpYcZdZ3-*MZK?mafA{%n!*8wc-kp%=6GT31(eZ z((&1Ws*xaEbDJ72wM%YaK65y$WaMbunOdf(u%WRoqjKWh?ZegvJQXBEMEZW@TBiz+ zINoywW3eMs67n5+#buRMb&V|@hkAMkyV|>ZI=hAr_jVs_Z*Hg&0-?^GPe@LJ>CVF$ z7ZDDK34rHGT|p6^^oBdmX3o}x^`>`HE*yLQo!r>_Kz+0fJqx%8cc&a8_K zCCTQ34}fcD=N6Xi71i#C*uMTFUEPNd_jIAoPS3%%=K3lya``(c8US!SRT6M_WnEb3 zjg;eO_Pb~LXj9e4zA zZK$SPBwZKP>~HDp?mu#9U}$Kt`^Z4=!Pchws>-tBLPR0Z%H_yyWRiAs6}oJsuEr>X zgH+na(<{Amrav?NU`I7r@yhDD0K3d- zs4}*?p#@0~4j+X^?LRVjsC9p>upBAwDfEGobyENh@LtSlq3b5;HH^RtF>s2iy8c%$ zjTR>EW%rcUFtG)@@)Ig1UpnQagR{Q5bQ&XPG1yL;%+MKBB7~x;5|SY~7jXa;Rr}fw z_Ya+zm^d-i-{0O?gDx(Fn#w@r4hO0SkYEpLFs^{)F+uFC?GZMlsie)HeCfoV__E^S z8fK01?xOO9s+n7(7Mkija~nI1t1JYwuJ#}-v5b%)8+7EOfG`p|k zK*#=?%CaI(F80va?Esq5U}UiNVBHzW-RSOWV-mgt+^vOynubC5ttnyLp5jsf#j8V$ z@(L3h=3Z~nNA7#Roukl6)*1CpU1I5q3`R0?RD&Z9MK1Dqifq}DTY#Vowz^z|b6$fmH=ZHhcY^{>y=#1&`mD1+oZ*=dD| zO{d?e*V52O-4fhi;f~YUiFHvWmKJl1AaxRr`V1+gI?J6oQ&D~X0%og!;OG>ew z!~BsJjG$;a8f9vdhjgdwm0!94AQYZpf|D&KNFEfYTskpP%$EF9+u~F z!9%pSr>B<--!^{er;_(~8K8iy!%Bgrp_ZEH-kIivoW%58I0HM9V)K*R&fl-r&@#5N z6*??%bO58yI;(K{l4~?1hlG<=AD@(*3QGnSUq)(1x-f&Enx3D7m^TVTqi_UNfF^L= z&)3fz(dz6gA4?>!2N?q#1v6@AWvs1Me(&soq>S|Zc(l0Sy#J`kzvP^BXgTCG7^ zOFFYD4?0dX0TJ6lnj=&&1%ZMYI}#I;l9Gi!4Cg2a^6`0c_tCLV{H=oAX>1En7u9TOeuzQJC|y&e!0 z6z1jT85$h}4_bUosDD6&FpAmEMromm(bU%MF)?92o<0#_f$r`Zqd)&b^2tYkmi%9; z4z7ynMig>kgXk#dKDgYGoE?+01O2=wB`zoJ5ag;tu8o}-xzw>6&i6CM*Vhk-d`KWz zKJU<|?NI^HW>lM77{-QJBACWM0xuKl>*3=U?C%y<{qkQVk3RnRqYovwU39GhTT(i8 z+{2i5^sRWTT~zM^Yd}{5A{KqrI(X$_UO+(|Kj7ne)6{uK9UUbcvj}pYi3jo z7ofc)`Ep0<&V&rKcXeY*Ts|bDpS6uGxjxabM|ypTcAi%uUfx*A=xl$SxDmqw1@0Fb zj*?TtP)!8?hWfz+=<4O;BJdNx`~f=n<42$T^-rIEP^@YUvYBhJ&~BB$#?n|zCFkMg z&eWapBzNt;l(@X~o-1$dA-U)l!lgHGVrhhFn?Rc>!G55p$YX)KXFy0W8^{ES1Fa}7 zA^=8}oqfW<|9txBqYwY~*`tp?eDCvj{1lO0oWiaUTR<1+kA+@6mIxpe07RhD37eKJLE9<_%)f4)k^<(^N{S*QMy#=1-m;dQ? zt*yvz8CEy-F8m5^LU&mb=(W_-#|`_MyPuDDt&axP74UL&PVRr_<4->L^G77?FCYBj z{Xf?#sFO5`0&=hy+pV&-CTY13uXfG1ZzY=+pPSKp{h_pdtY9TxiU9O^c|y09;Qk@e z!_&jj#o5)T#!H*)XB=#O%P;&MZTjG^5clave}4b}-v6K24X{D6_K2T%qzc@t;byTg z(o%)UgK0U5S=6Qb(-R9bd#}G$uBvHhfklOTdb_2lzRl?f7Z%2j0R7`#0;s z!`RY0c)8ix#~ym?!;jv7|3k?9{Lx2$e($%xc<-|HMnsnJDJTU(QH+`upq&;7Xvsl4 z({q!uA#`nLYJ6cvAGK496Dq&}$l@bHClQQ{rP#Tg1rDf`;9BiwkEYsqmYn(ZM}PYL zdyw?$=b!!cPk;E$&wui}E;R+*PgrC49pE72TrOB3D34)jq)AOYl%A82nFAfzj#-ll zY31r@BE_zV&_)@1XkZ~W`W0k2qMMyCg03)&bX*Z17TJF9{XhTiw^D&${OwP_`}NO% z_|u=}$*b`&3ut*^+u$meuZF7x=7d`AgKJ$GIb7=$+R_rJOCe9o09}gtO#c(u(X58h z)lTSJ?vJC5oq)Dn)H7Fgv2iJy{n>lJ`Sow#!<6~tvoAh*|2Mz<>5m@%@>Q=jIKW^S zS%<~aRtnImYf%W^8vUxNmiM%!s}G>18NJsY?A4G;79y5FXvaY5%Q!l*j!T^!T@Y(v z=ZruKCmm;JtJJ#^$=^Qu_>b@X<>OCKd;0xf{rty2eEZ?ACwTHY`li^W95DCD-zi6L zFS1>Qwi;@x=RLT3C?hv13wa+#6~m=)09Roq;MH4TrDDPqt>4jT4Ow$7sAIiY9W>{w3Z zPb8oHVI4c~z& zo7s1Tq+-%>1s4z#gUwH9XGT?{OgVobqF8LuV`#aJe{EB5P2elPe*cfZY!CXw|GoRp zTMr-Hd+jHe?G|xW)r6*t&8YGi6dfy|1Xh?yd<$a;ee>F(^juEpnl@@`?-leewiTL5 ztc^X*Bvceah7GBYjhyNvmJ5@yj;yV&8TH$D_V%ydy)Y9h`rkJn+`sqw>p$&PmRCmc z8H83KV2v<-lyRU%AVBA>wzVcjgw|f+`WUTU*_oEOE2HP?g99Gd-tX|!!zQ4?%lil>b-Z0*KR=`K#Ha%JOVDU#i-_G zgpghaB8dvGjZR#v8Zaz7@Cv8L^BJHV6kVLQpua!h$gaYhrGNah108 zO{gO1KS-Tltk)h?XlfanV>VG#D&~L<=eZRTa8PBXW$nQCDXpq*J$&@^uxU)rp|>Bl z7X?KA;Lh!LCyZ99>lon{9D`t4g90Gr6vph3CEu(yrja3yD7T+v!z|j=#;wq+Z=z#q z@{-dV|A+Y`kh4XpH3|)a*ObDZRjtD-#dRG6GN5q{MKLT^Ad8V?`D^KksQIUG(SuD!Xrl^C%u zoIjdkj;WRF5z0jLg*i>4`&Y2FB<~=R?J!L+iQX*7>?M&Rsv9D*mL)62-UOdUJ5B9! zYHC}0MrSTuJv-JvT;jj~x{(*~!pum2S8Ic4cm9s#*l>@eEgLYJp!n?s z_7-N=_Cni*q=W=m>M{UYtP!?FSPSH@FgMUp%e(u;1Y6UZ9GjPZ=+eD%O${DQL_Xr( z~K#t&5Of1uRgfGg%x}A0*yAV!e)sZYT7t( zs#@&eU||7Z2i+=z!=3Fy8b-o0D2>4?t{*k?-#Fivl(jtxYIbEyVsvg&`?)vvYGc|! zyUAj}tE^P4`KG?5^_|Bjk$t_fMkLykB-p%Y@n#hj!~vpV0=p`EIY&DLFj_4%M|dQT znphVLXw1+z@-*#e=rCP0^It#Ll9&~h0AZ_|6QgsITF<>k!b}keXsJ!z&2>B9!aQo8 zbKh4}#pVZSFGn4a4f3i6s8K~KhH((uuW^JY2ZtYg#DW$h4jMM31RxXpfzWCV%{@~C z5{jFJtf)ljfi+E>&@-=<>re}6a-t`k@lU>)bw({^U~j0atu9Y;+=|)?ND8B(rm1fs z;LK#QCsCow0vE!{$0PX0E=5g9!CnKtpfE^Ze(mygn>H)yn3!V=$9@Vu4kHC-xhb-z z*x|mF>qt@tu(!b0k;1`WktG62)OGT1pKOXxkBG|z3)~bJwIjay)a?q$L(kIZ@QZ4E zE0aJ`XLplGTvM51ue4^p;ue%4&^IF^0ki;I%z!;v(`DwC)`%L%iOt@YzNh!s?<> zgY~O7VuEf})wf`67YlF(c7lJ2@JtTVvUkP_Xc^Xsqa%FQux4o@$s$vk$a<5s8Km=2 zNLEcJ@8y|>nAETsT%WAm9}|%syKnmC3VjU}-DRzmxCLcov#YHhuB}WLm9;1$tD>%_ zrHe9L0y33xJalwI=qiC*EMHD~PFPGPAxe;8wa7v7aC4Xj7utkIi?v#byLNTm!j~rN zVv-}`lW;EEhX%(qOx{2R2CO-nb@CQGFEMhm7etwFmEWSIqKYUJ6Em0^upwC(`K;X{ z2TP8+VzJRWRMCEk_QEb$F14hgp0P-4tX5-&ndqzQ6^ofaKY+YGaf~VfrtsLkLKHc1k+q<#ih4!oM1P**8w;;5SCM*nLG!vI2uuoaR zQW6Pi_#=kJu*w2cS3_^l)v@ZR#Hd6BAQ|kB3eAYBI(}Jfq6KS>roACQw=&7!7P(ZZ z4jjdE)3%SD5swwxFU6zn>;+g_SXXkE7-1n6tH^#4w~0wL1E=$7sbk3qY4&OuR9-qJ zj)+Uh1pKX46&;ZoDL#6k%2eBcmbZnmM}C5X3011mM13Pf(4lgxt$=!t)WAXqdzfg@ z^oSs~r(PC1EI|X&LbOo`6AyLQus_q%Tt^C>_AL#=%8Mfv;R!KR7;r;&LQF<@#qilW zGtSzxvht0xrG(OJx$sX=6iAdo4a6T7!RD;Jj3XIHd@D>=5#C@iwGDqb!j*-bwa`M= zd~=?LY1P@m^3d$Cs6HyGnUS0lS~f6u&{_xktF@KD9t;@pb^T>P+)>jFtM5HgqnIKm0hVYpvK0cxSm0xJQIfMN&0v_jOz zqih0F^@i@1!*@7Kt+X-I({db~>dp(!%G_a9!>A$sMbM6e$0ovbagHYZm7q<6!m+rd zjlyOp;<|3Bqa%9K))t4(Y6r%i>hCQklZK=K4yKj~@n$Rdrn)*I6UREU0+HpdhS_2m z6CW9v(lRt#tWPoo=v_=7vV|#Jol6UV5fEW=i_n@y$l`)7;)^jhVmn#L6VhfYvXO&q z^e`@w$iA>L(beC5a;P~mFf=Y2S=9YQLjq#z2gU{+bm1iv*j6FW0lI)eqv>RguCboLU|i$I}IQ2t3hBxcmRAh(6T-u zdwY*evwDVPE!$FMQPv&0(cJE$Vi%P=-Mu?)lr1q->kMj8rYa80oR zTrO=x7-NLWP7fX`4e~?J!xsje(#?NIYyZe}o{kAwj$}5|mBJ!UmYsby_gI{bMYtHo z{KXBMr7cZzT3P~XhLG-xbHzy8Qj0oErvrC<{4Rbv?iquK#B}Y%ysHlw3stb#OO9zN8EuqZvop( zUM~~^wzSkUubCYl?5YU&HFtI60sq(4TE5ybFnfRR;K->~XI)G5`2vnu7P~BkG<*AZjrzq3*OSciqpF^snKI15Wpgr&0KOKI?S19`wyHtGT2j}9B8*;m8M}Wqing{ z(n!}eqOj%gkczE>4 z#qrVM-hFvdjyjw6s`Ba?p580U5;=Xxm|gpkM0@Pa8KFQIDKR+3MmLv`$Tg1h?BK3c z#v2J!guYAMTq#Qo61A}2j2G*v2Opi3J*N-gehrfx>mBE3x0Xw%jvpQBuFZ?I)m4zF zsUg4nHXcvQ?Imr?klfm?p<^eeFHU5e=o4^^^@&LzLW4zp$~oW3w-OkHWIUl^5dr=Y z;h~`+$iah~VR($-gGGuZC@I>gG2JOSg}I5A)t<8#Cr^wHvN-MMa6E;A?hL#WLe`2kxuPd0GLz zH_lB@9v|uuXZjdzR<}m!4&-{z*0r=SCXe6<8jlQeDAe8MVe z{b_SkEu*}->vPjn#|N6r65SLfAM>U8-c67_-#n6G%))Z&yGO>Sr_WvM3Dlqv) zBvM1_rU^p3!jTs>ij6cxi)ga=`I1+a%TEP4$fIYbrxSVP`q`PO@sUnpW{|E#;>+8t zfQ;`b2(Mrtz%cePyPFRmo0y)tc(KMoI$&6UT*@(&J@)fw17(AQL)cJZi2i)dV;^{` zrKz{*Lebn%!>#4Y`RVD2qrG*xQ38p?--=m)jPE>c6K1nlxaua)l#2EvV-r&|muB+K zw8?b>0n}ga@Xch#iJ|t2j6h|xv_NLD@hGFMn;B#k&oKOmy!swIc;fVhRxfQs@-Ru$bxFNO zUS1*;W7Z%iGEpelgShTC(Dpxc=_I`TBVAQH!YyLUB6Rhv#uz=?iehBtoa2j|`bJM6 z8}VF)KpRCIr1KODgZyvgj&gTr-PEzvNw;w897h%{hpMw@Cr*rw_S6?9I5UzsyTl5; z2}aF$$&$c0wJm;Wd)o#^kB?29JDzQ#YmP~RJ%yYx&}r4!w3JC@;3^hpHgg@5+{tqQ z%8njx+MVJnyD&ST>6q~hqhO_}7E=*q9FisK96<8_$um9SP#E*qXJq3s*uz+R1x^pZ zAl286>_0bg?AU03Yh^~Tu4P%o!sX_3jDjJYAjuMm{r0??E(F+&PM@sz&^4ORLJ7m4 zGfQb(-Nxw?)RoopXgoDJdUSZ8L$ou-HmxC%XY7E4@P;j=o>&83iA4?F1H&VuGvmcJ zdZu)aBWo6x8*~b5yA4VG=rp8lT{<~CGBP~SRa=ngEs-R;1q2vhV78d9ULKrps2Z4B zvj0&3Ad>DMPBP(fmtU-n2&bE^bf05krfZmdWM+79@NidMQA*HO#jN1^A+sxtf}NIH zVo4xBEWNy`tM_pK$aqtrfe|bc*j8j%Z-qw0$9cMety3e1`}?{YO41^%TzAK=lDE0e zY%uiqbBV4ibKRa@*?h3Or)PMi!d2gd%r%kC7W$;6k&X*{e6*+MP-o+wtQgn$T?qmQ zk5`yYW;F%AsSM*2o5MD>A3S*INMDXE{2Va3H^b^P(Y4JV814oY)mV`o7x2H5o!-Hb z*2oWUgVnLqgclT_E8O4G-ga=XBhA*p7&8~s-B{l`qigVBdwa`%c4vH$9xo?c)NK#& z-+`wWm+LJEPAm}ZYd+B2*4vWpZbsGC%sh6sA8v1MX{u*)6G9z5QsOphx+6clsgJ9D zia6IjJgJbaZP?e))Y&G^OHIwM?m%3@zJ{90yu=94gz^+eC*OyRwpn+fH=5!Zo?K8V zMqokp{sTyck1LIuYVqE@#Bg7RNe&1LcL4Y=V3@EZ8zbL{y8=pPZEk(ZkuAMWoI86Sn@*Pa0X`Gs+w zN#%TF- z@H>73nFX?p-QA}>|7;h0@!1!WcVK^fhl7BDS2*$oHT6rs=nXCzF|rH3n`wZqUs3k{ zKb20egh}yf+xqWh5M&lGOvsPFWZ<9giqAfi{9pEB=G$J2H1N6?B-F$I=8G2NLl01)x-oYeRh2LS`WDE(Lew(Fn10S4i3`__F+Z$Le1e^2toV{P|T z%)j^!OXT;-GT+8Dz)aFOCXrxNzt$JM?rqu>{3^eXaF&Nb`1jfX1232K>u+J;pGv3iFbzIw-N2x2 z|N0AW=yd1H4V>p6__co`m7Igd{j0SoyMR#~;cU6D{rG?X0kYKJu>V&pL5`8hdhc8B z`loM3YjI%xKeG^F;b>j>me$-;na_WRwfMjOU;Y9RAOBa$*V<*DfA&}V34_osEAu7m zK$hA69XDS3f}cNr=^R5 zb_U2Ys(*cP-A@DXh2gUUAjdeo$mT=COM;#qfCWtMiyVHK^O8yi2g=7^3mEoA%isUJ z{N@)ezwLSXEiYPr)AuZY@cH@og4_R@J{l4}8|6}t1JN_^5_(S&h|6}9--}U$3@&Bf$ z>2L74|IYvauK#B)puUIm*MIx}zy1IC`UzJd|K0!oyZ?QIee9cl2(f zGM{a~9Ap1t{ePcJT%Vo)vW(#ib3V`avgxz_4;g03k6vU4083l(tp68%QS~Axz-N-W zXS<)lyKMf&i|c^TB|p`Cw)IhJ+`Qx;nvV{UVG2L~t_d7suznrM$o@m~X$0gLV+2(YB=sGAQQQC4z2)zw z9*sWtg%^-`C;EuG@2#M3$e*Jl@CKV&Kl#QaGP?ec#owI2#|zLzG{5l8^bxxL zQJ>g%q#=fyt#iKc<(%vaS%H1ORDUw_3vmG_U|5jpSj@T+j? zv~yiD|7I)xALTy%H<*Zv(*N(@Y6A??yTRYqz(18v-(e8e*CPn*UsxyjZ+|LX^6d@$ z^DjWtKzHh&PXi46X9M5zz(4;6Gz}bXf4OZyEB>1Gx3S`%m-+lpm7=)*O!>`O_V?HCJB9D)+$O=?ZS-Grs8NQcK+f|yEm1nAg@0t032H>9= z_;F)qMoIyU1AL3W3l=Y?-(glK=k6$w4#67ysFsXc3iEeN2*iB++cCO5#{a5^{yuOwFvsdqtBYRWAe(7;$jrtn}ac`VIX4C%5 z&HM&_;0CAUa9;4ks6YBnm);+AuxK}W`jpF}(TE8n-8O|^{xsd^%&ph!fB4eC?|xP+ zvH8U(_X08>mXqx_=K4Viqk2-gJ_l|u1pNbsk-{neTW}y9C zz@2Mb#~ptxe6-AM89#62<-aIdytC2t&o@>no$GsdcaHCpVdXm(?l-&Y-1om`qx)#5 z?4yozO`abwQCoWDry~B^@^?#WTxSceg=?(d;%@g=@rk!@{0UVNig(1mGql=f_uW5U zURd{uL*~OJA1>7!y-}Rr;{0<5&ALB#{Hok_A?XYO=Q+!uLjtmLQ(DB5>Bh6JkJr_)25rrhdGeZSAW^y2p)RN5>R*cn!`D ziDw!Rt-VOB$IR`<&bxc<2L{q9YJZ|=C*^KEZhF$c7NNWOjE9XNTSkAWm9;@SG`8?< z?LfhN9)v0xImyE&j&11FeBfkA!=2u}k5lNHGg$3R6cevU3Ha|L>eZn8&+YDDKhMDS zeg~8DMmm!(ZEX=TpQ@=#6tmL_;3i&MlprSp|1c2GIvTYY4XIU4`Gxr_$xWI~bmsm~ z%L~ZGClpkFzq`qhNk1ZR*2H6*Tkw<6G7c)!EK2JJrXNQi#f#N<%`YK}t)f$!dGYSL zM=5j^Gtg!iKbxX$MMzt>=F6DePOlcByZMZVjUZb_Xaxh`y*rvO9-t`iqQc>heq#j? z78sIJ5?yq`{)XR+g`-aGiFE&GL_Q@oAddvakeRUas<;IpV1Y2#&%pkE2lMkr1S?=y zyyCbt<`zIyHxXk!hclu%FIVUpI69`c$4Gnxk#|rPm^D_}-iT;*^9Bi%W3jniDzt_8 z?|kq{b=1=$aE-1K=M;{cc`g{Z+R+m!xS+RbcZDjcB1P4m`O>1io|~A8FnQ$|a->$p zyxIw59z3mS)yMVWNL*t}NoN+JyZJk{wePAmd=fOup~sHm>Z^YN#eop82SYkY$ygWD zER=>2y>ClPNY3Nbi?E3M;$n;wv_j%lWYEVZY}d5@T-@$W<)7rF-4}>mK;9n5ep28^%k$ zG<7+0Oq6F9w;{%U zbYeQefT(85w{yENOe>^c+{kVtB;23zuq`OkfeHGpY%{ zKc=rdpq02VBqTnVbi*e zgoul0=Jlh#(4TP5;)GJo@;Arl2Rk0M1U0ETJ&}|G_vDNDJ_!g>a}$&rth>64=T1M} zhPSB->u}dG4QnMU1cZ7TM^(G%Kc95}e^+w_mwD2{mbpDGsY2D**IuRW>DBNT%88yw z4w4sm=U29~H}T@|_gREWZH2T-^F#5P@yLW!y%AV^&Lw0-{?4rDm4@E&U*X%GLdwUV zEUNzRJ)45~!aQ~f%^6MysTQJ#2X(#Te`F~SobNIc`I@~k+p0Twd!1~H$7t&=AFE!@ zvST_5Y|G^jH6-``LXrPy9i62mM%r2M-zQ({+@0CZQN9+6eZsdX8+S*FK+M}k@|vZd zOu$naiqFEspM`-Rg?NetZ4EOpnp$mcJF8nyAnx5RlnHmQmA=Rser^>wy_ddStiKE62R|fGGk$!T7q?tevGX_9_ZRZ z+9xJQ{4?&Nes%9+v65;|pPpGmyq@?_wa|YMwbO9O@g5m;{|JAvgs*OU)!5>ILhL{3 zs~+T3%&Dynnys-Pf6U#y`!r6CRDb0An;9kOlfT1Y471gloNH!Ag4VEWK>AjUv3Ku? z@OnJM7}L#sl?OfHM;$@@7p}fu_%26f$wu)akG^G%A^Efg0;b_F%_pu@oFWj<0~9v# zRQgaMMaH<~1`Y4>V)Br=8H6A8%I9k@ta$*0qZtN3`_+TV?W^H)q)&(;Du-NDx3BJ% z_vo4bMD=Gkp2ELtMd-?D?mHiy4=v?CS7EXE%ryQ>ny>5oAD^ny;}K3x?)3)btu&ng zR6y>A4Ll?xuTtFFCw75uLamYyisTFYn>SEoTDt{%5bO5Gz@W~{U;7N_e;vf7xGgB% z3RW)KOWGa5?!p(3Te&T4oDG0u06ZdQ z+zkWE;v~n+77)|*xh!4+S5-5ZS|lJaVDf5+6r&oG`sV@XOOy6w9M`bmVFn21!BD05 zGRy6)9cvXPUGvvlX2f9&UB}yH&%(uz!o@r0WpWi2lEC{i&|kX_L0d*yx+TRmN%b%d z9<0KHE1+ZkFhWx%`DR@~^B;TNFwcEu(#U4SP$Wq|8RAvfczzsEC;zXQ%+3I zfSo*G<#Iin>-m~rRb%%6s@r<{-IA5QQ>Vfbu>B4Dew)d0)=5e zv93XTv$jO@#D3rS>(puq>Dc*Se;(vi%&Dyb^#;4}+z=*&*yZPj$`zzD7E5g6{>bY!A_PGOUw8itfa0u3BJ*pwg3e;Ohlx=<=8x=-OGSiH*hik+Gv3>$I-F%Y98lae zA9!ohdg4tcQvJsWQQxm8qFX1B&!m=Vr~ubO6{+WKBaNDq*-q!o+OB%^aaTfJ_LS9Y z^Hx>sp$biVabyez>%vc|$_GR(4AJJV3eUTJQndvc?UdZMx9e4z318U8{*zh4ZN+cT z!hxTIe0~lel@x)BB(RQk>d}UbI_Yz$iI@0KOW>|oGtPDF>VnD^<^ z1W09%@TR`_WB76*CAp9&XXDNNqiKhCX}*i9DA&ytFjW_*A=zrCd~W0s7fJ zxn1Y0R_^7C5S#C)oW9>nXZOgS*&bmM|Hyn4Si7frT>6Q&=f>3l#h_A=n z(MeBiP&Qn*L0IlSv;aDYX}^8 zdEG!jFxG+}p+lbk1>2ANWbvkFMoH3ar6 z4R96kZ}63QbKgR?e2!9xzV+<=R}#>gpRm8Cu-ycs24}TsN#$aO$zqBmFP@kHvomJH zlqMa`Z!S){L?{$5`)7UchD>k~>dcM;7n276VTcGU%tifY_M9cvkL3R#Y+=NJd>+K; zFa&cE%0DQAO4ijmnR!i*>>h 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�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

    R?bd+lpKX5hGGZR}j1l_x{!MIPw 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%0DpcCLzD`7|D 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%0A_D8To2O;xUGH!#E1{T0zoqgFVAF;y#Ul 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

    oLgY>8?jv+SvrVi;KjlbxqBCv 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 OlNZs4$e#9AfB)I3=OO|C literal 111762 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
    =b<-lLR?Kfrf-^13gm_-AeyMmx z8v|I@ajQzZTZJBnqW^8M^WaB9ul`n_>m?F1xcf zfxU98(VNIV)~qLBe1FSg&&ZECWNe&EDuT4Y6Z;J^oZ<`IAdl}s5h=@`RgSB?2!O?0 z$?Qq)Lx^kiaDZzvpE9hmy%$a>#UF>gHakG}ka7R+Q2Yq5okEW#J=i#eU6a50E=8*5 zzUbeo*TdOH7`F*wOyF$YS#Y6tOigB3OzE7#oH3N!aKyY4nNOjQs%EiEJb)|g2j^Np zt?ppH3GO*loU=+ati3t+>V>w;N)S9YBo4QytUt{OYNR@&c_y$@`EkOlJzkaY+LP*G zd(uyDc)L@7ZGIp+b?oonD|-$=1zclwf{qcKMsYcL{`T3Qt<0<*W9!{4DnEq{mIH_n zpyEL{!yfsjrVA5kLqs8vL-i~#=+7!&O5kN={ahq91@a48JLaH+)UZwPGw2^wf!fAw z1=}G79ekl6lH*-TDE>LBnypCTn}Kao!@rTF+SRk)t6{m}wP~nmur?^qIAf#r+2?ih z$9?HSJ8GL;-dZ~sGkBwxJO&~-OzJU$Oi$r-_6BPho4uet7vw(+rw0yPQ4{mr1-vT) zT;>2Q;UkKQ9>16P>uZyOLwl&5tH_U1a;MnkEsl(pTP*eEDyD^d&O|RffVxjs%&goh z5Z)xLbR4w}#vyM{wLt&)o~equxA-L&!c*PSsTlD4p}&H^UZ)4a(tY}ZJV)M%deH!N zWyDd3xN~f}1+hB@J;ZrPm56OKblwtHBq_NSj1NyE;2TW2IYW zomd?sx^*0J-7T};!@jU`H}CJC2Di)?woj`kuOcq|#TJ>qZ-P~TmktflGR~iIrbDD< zMO|MaCZ}q%VA*gkW$6*IlZ~8LA5P2ZO!M|QWnw9!PHl_d+qe_wx@sNkICI(ISDNI_Oo$HwL&tJlsh$4a=PZQsO@cm$dMdp z(gvzU5$RLlx|~XKGP@~m=ykpzJrJ}ogFPIH*V120#Qeru{{H(X+xSj#l*{>>ft;uB zo^V`zZ!W@>#c%TCO2m}LrEe~sNlm9ZgxQYos!ewJjnND|gEgB>U9(Fd(+HfcVk1P+ z9_9WQdd5T_-d%8=f%ReEQP?Rdg9tO3wqt9ZI(&kMbJF}mCCJNl9F)oC7Q9b$%M?=M z?g)Q%W831j_01i}Yq^Vay{OaYBYqXD|FM!RRiGr3T5f-~ihtif#xe5@<4Z^GCqKj< zu#D!^mWSs0G?s_atG&Lyo~#IS@og?YaB+sNc|+Q)=`3yj{#=~teafMt_O(_UJ@0I7 zTUawsqi>+Y>yY6vlO$ilxHdY(S8_bnO&OYfhn905Wi*yb&>u9K9yWjVF11r*i1F<9 ry-)}Q(xD?Nw*0Wo-vIpl|2(Y2_V43XHT~Eo`@WOI>7(U`{S*EV(M4Xj diff --git a/chrome/app/theme/chromium/mac/document.icns b/chrome/app/theme/chromium/mac/document.icns index 73fd43dfb87b00a1bda69297a58da32cb8e23db9..1a03ae29c16fa304769c52951f2e81c06e390bb0 100644 GIT binary patch literal 378456 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%0DQAO4ijmnR!i*>>h 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�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

      R?bd+lpKX5hGGZR}j1l_x{!MIPw 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%0DpcCLzD`7|D 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%0A_D8To2O;xUGH!#E1{T0zoqgFVAF;y#Ul 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

      oLgY>8?jv+SvrVi;KjlbxqBCv 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 OlNZs4$e#9AfB)I3=OO|C literal 97120 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

      }t&_EdOdO;Q!{4xx0IWkel4%jWb?NP1V@Bm4O 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 diff --git a/chrome/app/theme/chromium/product_logo_128.png b/chrome/app/theme/chromium/product_logo_128.png index 9f88fb10a2b4ac59e088471670317961b803f8b1..7e63ba7f8c2b1226c85a270fa32ea0d31c8552b0 100644 GIT binary patch literal 22073 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 literal 8366 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 XnA%>kmfk=J00000NkvXXu0mjfNd)d~ delta 992 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 Hu0mjfSaC>2 delta 1001 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 Z{~O9OhEk(C*t7ru002ovPDHLkV1nI1l8XQU literal 19849 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 uii(Pgii(Pgii(Pgii(Pgii(OJ c #222634", +", c #222835", +"' c #1A1D29", +") c #5C5C64", +"! c #C1C1C3", +"~ c #B2B3B7", +"{ c #B1B2B9", +"] c #BEBFC2", +"^ c #909094", +"/ c #1B1C28", +"( c #2A303D", +"_ c #3A4050", +": c #444B5B", +"< c #444B5A", +"[ c #3A4151", +"} c #1A1B28", +"| c #8A8A90", +"1 c #BFBFC2", +"2 c #B1B1B9", +"3 c #BEBEC1", +"4 c #AEAEB3", +"5 c #32323B", +"6 c #1F2431", +"7 c #343A49", +"8 c #474D5E", +"9 c #515869", +"0 c #545B6C", +"a c #545C6D", +"b c #525869", +"c c #484F60", +"d c #343B4B", +"e c #1F2430", +"f c #2E2F38", +"g c #A9A9AF", +"h c #BDBDC0", +"i c #BABAC0", +"j c #BCBCC0", +"k c #57575E", +"l c #10141E", +"m c #282E3B", +"n c #3D4352", +"o c #4C5364", +"p c #565D6E", +"q c #5C6376", +"r c #61687B", +"s c #60677B", +"t c #5D6477", +"u c #585E6F", +"v c #4E5566", +"w c #3F4655", +"x c #292F3D", +"y c #525259", +"z c #BCBDC2", +"A c #A7A7AF", +"B c #C2C2C4", +"C c #85858C", +"D c #161820", +"E c #1C222D", +"F c #2F3542", +"G c #3E4553", +"H c #49505F", +"I c #555B6D", +"J c #5F6579", +"K c #686F83", +"L c #6D748A", +"M c #6C7287", +"N c #697085", +"O c #61677B", +"P c #565D6F", +"Q c #4B5262", +"R c #3F4654", +"S c #303643", +"T c #1D232F", +"U c #16171F", +"V c #7B7B81", +"W c #BEBEC2", +"X c #A6A7AE", +"Y c #9B9BA0", +"Z c #A8A8AE", +"` c #2F2F36", +" . c #11161F", +".. c #222934", +"+. c #303641", +"@. c #373D4A", +"#. c #414755", +"$. c #4E5565", +"%. c #5D6475", +"&. c #697084", +"*. c #747B90", +"=. c #757C92", +"-. c #777E94", +";. c #747C91", +">. c #6B7287", +",. c #5F6578", +"'. c #515868", +"). c #424957", +"!. c #383E4A", +"~. c #313642", +"{. c #232934", +"]. c #111520", +"^. c #2B2C33", +"/. c #A2A2A7", +"(. c #75757D", +"_. c #ABABB0", +":. c #14151D", +"<. c #1D232D", +"[. c #2B303B", +"}. c #313742", +"|. c #323844", +"1. c #353B48", +"2. c #404654", +"3. c #4E5464", +"4. c #6E768A", +"5. c #7D859A", +"6. c #7C849A", +"7. c #7E869C", +"8. c #7E879C", +"9. c #70778B", +"0. c #5F6779", +"a. c #505667", +"b. c #424856", +"c. c #383D4A", +"d. c #2C323F", +"e. c #11141C", +"f. c #A8A9AD", +"g. c #696970", +"h. c #84858B", +"i. c #5A5A61", +"j. c #1C212C", +"k. c #30343F", +"l. c #333844", +"m. c #333945", +"n. c #353B47", +"o. c #393F4B", +"p. c #404553", +"q. c #484F5D", +"r. c #5B6275", +"s. c #6E778B", +"t. c #80879D", +"u. c #80889E", +"v. c #71798E", +"w. c #5D6577", +"x. c #535A6C", +"y. c #4A515F", +"z. c #3A404C", +"A. c #363B47", +"B. c #343741", +"C. c #313A4A", +"D. c #2E3847", +"E. c #212530", +"F. c #62636A", +"G. c #87888E", +"H. c #8E8E95", +"I. c #3E3F47", +"J. c #2A2F3A", +"K. c #313640", +"L. c #333843", +"M. c #3A3F4A", +"N. c #3E4551", +"O. c #464B59", +"P. c #4C5161", +"Q. c #52596A", +"R. c #53596B", +"S. c #565F70", +"T. c #4D5363", +"U. c #474D5B", +"V. c #3E4756", +"W. c #3B3E49", +"X. c #393A46", +"Y. c #1E63B5", +"Z. c #1D4C87", +"`. c #2E3644", +" + c #2B313C", +".+ c #505158", +"++ c #919197", +"@+ c #939398", +"#+ c #393A41", +"$+ c #2A2F39", +"%+ c #2F343E", +"&+ c #303440", +"*+ c #333742", +"=+ c #393E4A", +"-+ c #3D4350", +";+ c #3B414E", +">+ c #424857", +",+ c #414654", +"'+ c #454C5A", +")+ c #434B5B", +"!+ c #41454F", +"~+ c #3E3F48", +"{+ c #33557F", +"]+ c #1F70C2", +"^+ c #0B88FF", +"/+ c #1A4373", +"(+ c #2B2A2F", +"_+ c #2E333D", +":+ c #2B303A", +"<+ c #4C4D54", +"[+ c #94959C", +"}+ c #95959B", +"|+ c #393A42", +"1+ c #292E38", +"2+ c #2F333D", +"3+ c #30353F", +"4+ c #323742", +"5+ c #353A45", +"6+ c #373C48", +"7+ c #3A404D", +"8+ c #3C4250", +"9+ c #3D4250", +"0+ c #3C414E", +"a+ c #3D424F", +"b+ c #363D4D", +"c+ c #275A96", +"d+ c #0F81F7", +"e+ c #0B85FB", +"f+ c #0B71E9", +"g+ c #1A2536", +"h+ c #282E3A", +"i+ c #2F343D", +"j+ c #2F333E", +"k+ c #2A2E39", +"l+ c #4D4E54", +"m+ c #96969D", +"n+ c #96969C", +"o+ c #393B42", +"p+ c #292D37", +"q+ c #2D323C", +"r+ c #333944", +"s+ c #353945", +"t+ c #353A46", +"u+ c #353A48", +"v+ c #3A3536", +"w+ c #30476C", +"x+ c #1860C3", +"y+ c #0D76F3", +"z+ c #0981FF", +"A+ c #0A6FF1", +"B+ c #0B49AA", +"C+ c #1B1F29", +"D+ c #2C313E", +"E+ c #30353D", +"F+ c #2E323D", +"G+ c #2A2F38", +"H+ c #98989E", +"I+ c #96969B", +"J+ c #3B3C43", +"K+ c #282D36", +"L+ c #2D313B", +"M+ c #2E333C", +"N+ c #30343D", +"O+ c #2F353F", +"P+ c #2C313C", +"Q+ c #313641", +"R+ c #2D333F", +"S+ c #545358", +"T+ c #2F7BC6", +"U+ c #1A6CDE", +"V+ c #0A78FA", +"W+ c #0A67EA", +"X+ c #0951DF", +"Y+ c #082D79", +"Z+ c #1C1E23", +"`+ c #2E3441", +" @ c #30343E", +".@ c #2E313B", +"+@ c #4E4F56", +"@@ c #3C3D44", +"#@ c #282D37", +"$@ c #2B313B", +"%@ c #252A33", +"&@ c #272C35", +"*@ c #292F39", +"=@ c #2F333F", +"-@ c #55575E", +";@ c #818183", +">@ c #9297A1", +",@ c #898988", +"'@ c #0540C3", +")@ c #0840CF", +"!@ c #0C1E46", +"~@ c #1A1F2A", +"{@ c #262B34", +"]@ c #272B35", +"^@ c #292E37", +"/@ c #2C313A", +"(@ c #4F5156", +"_@ c #97979E", +":@ c #292D36", +"<@ c #2B3038", +"[@ c #2B3039", +"}@ c #2B313A", +"|@ c #2A3039", +"1@ c #252B35", +"2@ c #67696D", +"3@ c #A2A2A2", +"4@ c #A3A3A5", +"5@ c #868B92", +"6@ c #818793", +"7@ c #0433BC", +"8@ c #0F1934", +"9@ c #272D37", +"0@ c #2C3039", +"a@ c #2C3038", +"b@ c #2A2E37", +"c@ c #4F5056", +"d@ c #96979D", +"e@ c #939399", +"f@ c #3B3D43", +"g@ c #282C36", +"h@ c #2B2F38", +"i@ c #2C2F39", +"j@ c #2B2F3A", +"k@ c #7E7F82", +"l@ c #A9A9AA", +"m@ c #A7A7A8", +"n@ c #8A8A8B", +"o@ c #5B5B5D", +"p@ c #232C48", +"q@ c #11161E", +"r@ c #2A313D", +"s@ c #292E3A", +"t@ c #2D323D", +"u@ c #282E36", +"v@ c #4D4E55", +"w@ c #95959C", +"x@ c #909096", +"y@ c #2B2F37", +"z@ c #373B44", +"A@ c #969696", +"B@ c #A5A5A6", +"C@ c #8E8E8F", +"D@ c #69696D", +"E@ c #1F222C", +"F@ c #0F1421", +"G@ c #1E232F", +"H@ c #2D323E", +"I@ c #272D38", +"J@ c #2C303A", +"K@ c #2A2F37", +"L@ c #4E4F55", +"M@ c #93939A", +"N@ c #8E8E93", +"O@ c #3B3D44", +"P@ c #232831", +"Q@ c #53565B", +"R@ c #9F9E9D", +"S@ c #8B8B8B", +"T@ c #45474C", +"U@ c #161822", +"V@ c #060C18", +"W@ c #1F2531", +"X@ c #2C313F", +"Y@ c #272D39", +"Z@ c #262C36", +"`@ c #29303B", +" # c #2A2E38", +".# c #8E8F96", +"+# c #3D3E46", +"@# c #262A33", +"## c #696A6D", +"$# c #757678", +"%# c #33373E", +"&# c #060B18", +"*# c #161C29", +"=# c #29303D", +"-# c #272F3B", +";# c #212833", +"># c #242A36", +",# c #2A303E", +"'# c #2B303E", +")# c #2B323F", +"!# c #282F3B", +"~# c #282E38", +"{# c #4C4E55", +"]# c #88888F", +"^# c #7E7E85", +"/# c #43444C", +"(# c #262B35", +"_# c #2F333B", +":# c #4C4E51", +"<# c #21272F", +"[# c #141924", +"}# c #1D222D", +"|# c #292E39", +"1# c #2B313F", +"2# c #262D38", +"3# c #2B313E", +"4# c #2B303C", +"5# c #292F38", +"6# c #52535A", +"7# c #808087", +"8# c #6F7076", +"9# c #5D5D66", +"0# c #252B34", +"a# c #1E222D", +"b# c #242832", +"c# c #272E37", +"d# c #2A303C", +"e# c #2B313D", +"f# c #2C3340", +"g# c #272E3B", +"h# c #2B3340", +"i# c #68696F", +"j# c #707178", +"k# c #9F9FA4", +"l# c #2A2D37", +"m# c #2B323B", +"n# c #2D333E", +"o# c #2F3440", +"p# c #2C323D", +"q# c #2B323D", +"r# c #2C313D", +"s# c #2B303D", +"t# c #282D3A", +"u# c #282D3B", +"v# c #2C323C", +"w# c #2E343E", +"x# c #2F3441", +"y# c #2F3540", +"z# c #2A303A", +"A# c #9B9CA1", +"B# c #4E4E56", +"C# c #72737B", +"D# c #A2A3A7", +"E# c #4C4E57", +"F# c #262C35", +"G# c #303642", +"H# c #313743", +"I# c #2F3642", +"J# c #2F3644", +"K# c #2F3643", +"L# c #2F3543", +"M# c #2D3341", +"N# c #2D3340", +"O# c #303743", +"P# c #2F3640", +"Q# c #50525A", +"R# c #9F9FA5", +"S# c #6A6A73", +"T# c #62626C", +"U# c #9F9FA7", +"V# c #8A8A92", +"W# c #363942", +"X# c #232932", +"Y# c #2F343F", +"Z# c #313744", +"`# c #343C4A", +" $ c #363F52", +".$ c #394258", +"+$ c #3A455D", +"@$ c #39435B", +"#$ c #394358", +"$$ c #373F52", +"%$ c #343B4A", +"&$ c #323744", +"*$ c #222730", +"=$ c #3C3F47", +"-$ c #909198", +";$ c #9D9DA6", +">$ c #61616C", +",$ c #7D7E88", +"'$ c #ACACB5", +")$ c #717179", +"!$ c #2A2E36", +"~$ c #29303A", +"{$ c #323949", +"]$ c #353D4F", +"^$ c #3A4256", +"/$ c #394256", +"($ c #373F53", +"_$ c #353D4E", +":$ c #333A49", +"<$ c #272B33", +"[$ c #75767D", +"}$ c #A8A8B0", +"|$ c #787984", +"1$ c #8B8B95", +"2$ c #A1A1A9", +"3$ c #575861", +"4$ c #1F252E", +"5$ c #303847", +"6$ c #313948", +"7$ c #313846", +"8$ c #303742", +"9$ c #1F252F", +"0$ c #5B5C64", +"a$ c #A6A6AD", +"b$ c #8A8A94", +"c$ c #6A6A75", +"d$ c #93949D", +"e$ c #8F8F98", +"f$ c #3E414A", +"g$ c #242932", +"h$ c #2E333E", +"i$ c #2E323E", +"j$ c #2D333D", +"k$ c #3C3E47", +"l$ c #8F8F97", +"m$ c #90909A", +"n$ c #666672", +"o$ c #6A6B76", +"p$ c #73747D", +"q$ c #292D35", +"r$ c #75767E", +"s$ c #92929B", +"t$ c #696A75", +"u$ c #686974", +"v$ c #82828D", +"w$ c #6B6C76", +"x$ c #6A6C75", +"y$ c #81808B", +"z$ c #666773", +"A$ c #474855", +"B$ c #5E5F6A", +"C$ c #5F606C", +" . . ", +" + @ # $ % & ", +" * = - ; > , ' ) ! ~ ", +" { ] ^ / ( _ : < [ ( } | 1 2 ", +" 3 4 5 6 7 8 9 0 a b c d e f g h ", +" i j k l m n o p q r s t u v w x l y @ z ", +" A B C D E F G H I J K L M N O P Q R S T U V W X ", +" Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.Y ", +" (._.:.<.[.}.|.1.2.3.q 4.5.6.7.8.9.0.a.b.c.|.}.d.<.e.f.g. ", +" h.i.j.k.l.m.n.o.p.q.9 r.s.t.u.v.w.x.y.#.z.A.B.C.D.E.F.G. ", +" H.I.J.K.+.L.A.M.N.O.P.Q.P R.b S.R.T.U.V.W.X.Y.Z.`. +.+++ ", +" @+#+$+%+&+*+A.=+-+;+2.>+,+'+'+b.)+!+~+{+]+^+/+(+_+:+<+[+ ", +" }+|+1+2+3+4+5+6+M.7+n.c.8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+ ", +" n+o+p+q+i+K.4+r+s+l.~.t+u+v+w+x+y+z+A+B+C+D+K.E+F+G+l+H+ ", +" I+J+K+L+M+N+O+k.%+P+Q+R+S+T+U+V+W+X+Y+Z+`+k. @2+.@1++@H+ ", +" }+@@#@$@:+p+%@&@#@*@=@-@;@>@,@'@)@!@~@{@]@%@^@:+/@G+(@_@ ", +" }+@@:@<@[@[@}@$+|@1@2@3@4@5@6@7@8@K+{@9@$+[.:+0@a@b@c@d@ ", +" e@f@g@h@h@i@j@ +&+k@l@m@n@o@p@q@r@s@:+t@ +j@[@h@h@u@v@w@ ", +" x@@@]@h@y@<@[@z@A@B@C@D@E@F@G@t@H@I@D+ +J@$+h@K@h@:@L@M@ ", +" N@O@{@p+h@P@Q@R@S@T@U@V@W@X@X@h+Y@Z@`@[.j@G+h@ #^@&@+@.# ", +" G.+#@##@}@##$#%#&#*#=#X@-#;#>#,#'#)#!# +J.:+$+^@~#]@{#]# ", +" ^#/#(#_#:#<#[#}#|#D+D+1#( 2#2#3#1#D+D+4#$@J.5# #^@]@6#7# ", +" 8#9#0#|#a#b#c#d#e#e#d.d.f#m g#h#d.3#e#e#[.|@:+[.P+$+i#j# ", +" 6#k#l#m#n#o#n#p#q#r#e#s#3#t#u#e#s#r#v#e#p#w#x#y#z#h@A#B# ", +" C#D#E#F#}.G#S H#I#J#K#L#M#N#F L#J#S O#H#G#P#b#Q#R#S# ", +" T#U#V#W#X#%+Y#Z#`# $.$+$@$#$$$%$&$Y#%+*$=$-$;$>$ ", +" ,$'$)$!$~$I#{$]$$$^$/$($_$:$L#*@<$[$}$|$ ", +" 1$2$3$4$+.K#5$6$6$7$K#8$9$0$a$b$ ", +" c$d$e$f$g$h$i$H@j$P@k$l$m$n$ ", +" o$e$p$q$/@/@!$r$s$t$ ", +" u$v$w$x$y$z$ ", +" A$B$C$ "}; diff --git a/chrome/app/theme/chromium/product_logo_64.png b/chrome/app/theme/chromium/product_logo_64.png index c8f9c190c8e974767d4905a7edf79230ffd817d8..8358e5d2e0a325ba2efa0601042d94327a78df91 100644 GIT binary patch literal 7342 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 UWE1q`9{>OV07*qoM6N<$f(=MSnE(I) literal 3634 zcmV-24$bk2P) z(D6-IlkWiASwQ5zFS>+QguMcp$Sb%xX%X^$T5o`8-dXqPzw@_D-hjXqba z^L}6x3xFIq&jeJ)hDt$FeQOdYFKW7=0HAal>1t}~-0TVHNLW6SYGBNVuBhv~fClqG z_M1ln?o`wVXe6I*#O$F8D9k$n19VI&r&nNt=K_CVj>x@VJ$M2d#p}b-WW`6UH7|@4 zP!XUb0UgF?uj=3l@aN>hL`{@`|JarLy#cTch&<|1${_4map}@rS%1}Ny2DjL#em%U zhN9?gnt;yplwvOUN4;8q2rxd_8t}Yx=$B$Cw|72te`vrc>`)V~mnu^(EWdefb>Y4xRVO+_!sNiV&GnHY+z_h|<1x6TO|0D}lGxu$49qLQ2iaHQgRKfRwYBr+2 z3;cX1y6~;w&3DDRP*mg3Zn-(hrJ|e6OcP_vlV9bRt{p2#9n`hWDbOCZ9jPLzKyj+b zt*X1Zm zXeyZ$fBxD@f16|0F@xAMZw*>-5SF}$uXUBSon%l0idvWEo0?PjPGm^cq$Fk(PJjI?4A2ttF3!L$oiH0E`{i?Q4jItyc0hQegq5&|d?}8T6(xPGIiT4=gK1WmrYUi^rnczTOoOv^N6 zu?YkN7-L!@2rx!4fk6;Zz(24_vZG-3SOx543SqId7gNdAw!hB>IbkZr3M*HYx#5PL zKm(J@?KUh5YS5`&(7q@R+9$`W9=n{%aENE33g=u4S8ai9Ra%S`VXq}{&|0XJK!EiJ zRM>xQnVr(UVJ z85T(qIAR~+F^9wIF&HWaJnnug_{HBhbH$BG%V-cqgh7CaH|R&fUz_;C8y^dxIKvaB zCqO>=t1Wo`eZ5&fmMfg8N>_H=d>vO_d?QGJgaIbXgNUz6JBEYz%k#FUuWp%F;Fo8@ zcTZ8A>v1n!0(cB`u zN-lh^Q&757Ua^Lu;T)h~EjDSQPI2shLL3{0S3Pc}H_uo90pH%(X}%{4*1^~R4PX5y z9`14I5XGEejLF(QFs)7q!!&MR_r?f8XtLs@W8lx5JT?Im=1t!0x<@L!Ovi!9J!qrd zq_AecwUAjxtV3-RboVadDfby;bSQv!<$r&kc2;?o>U$LU^*QjXv+-M94&6U$n`#?Q zC5D#SFf-bkPve$hGkF|k=7S(hNEAdTrNYZhJwSAgDm}@KjIm_-D2Qa1twZBxmYl`H zJr7^xulcm?2Q;tTif?XEZk$j64p^O|T+)`Quw_Wv329Y4ReLm9XSB|lH1FqvR7MX= zh4J#i(@xBrFlxWl)J{!j*`8|=b*NK7a9Gq@?(1)LWDA~ib1>f-l34iOsk;}p{gww9 zX;;5(-d8uw#>}i~CBmQAIu;`&)*YA%FXMyf|A1wxLN`=9WpYJU?zz0(1?~H^OE~&Y zL;hCRTJ3e7=KZ7K#>GTwZ(TJf`NJUFNXjZo_ zW&jqgT1h@1W~MAu$|0+k6@ctM?-ZETe1Dsq#7+Lr?0C_zp_I=m?@fEdAbsr-av{Z3 zOv?Bmih}|JASPh--fQv8-Va64k@GvqYoz)!>Ycxv5q>K-&b43Nb z`eAr+h4SbSIvJNjJpKt!bpZ1{c8314@`M4?>3{pJ5GrAqjTj$HNBfWiR_(hMQ9z{g zXSK&aM*B0bx5HQ3#s`5hHD9qo$Q6q$UA>s?yJ9?}#hJYNg8|KJwny;9Zf@20Btnvk zNf{sPQd_5u>R?*7W)(M$$9VQy(qVkw<^lFyiic`_es4_zCvhq!WqdGP8QTKNoCpK* zl_lJ?r3qxaIwQSXeh~AafpvQb0NZOyJ&`$8-_uN}rD9UX2cLcvx2P)6sop4Fqsy1D z@q(QIR7%;d4((O-+0A>7+7E{Fw76lbfEaIn;OaMQygi{>PsOB+55Dl%s*4**eX!-Q z^R%;XEcky^YfBrLo>lM5d>FuEjs$P`+HpfKbe0cuMlMc;mzjE?Cb(uU3!!SJ@ub8l zS2Sw?tH-h}t@fY8ZSCjpzpi)HdzpXGdbsa80btuM%cVCl3NokG_bB!+sqivW52_M>R#lk~6IJ-u zMo==Idfa3cmB93-g72F>x?rRPhX4eT^H==8At!g_nHc-;Swl zICIywFdvLCPY&N(dEAj8LW^`u+uGG_xJ za9f?}?3C(LMs@hSK!SnIc0*fh0Q}?(`1x5vxj-ukrHB^Q7;c%cY~EVKs-TI(TFbfv zMo=-J1Do%_HR2tGLg{04LB915r5nFJbK+n5V*VKBPhT4s*KA^&F={PIDzQx-a^fmt zmBGz-hQv+xTHt+j!PFWJx~W*z`&(O27S4F4nRdm_IY6;ER2|12R9O)7Nh7|{R`MTC zMK_t5CJw#lqHXaG-lopY+jKAE9;XhgiaKSqI2GMwe9%pI zKYaL|^+x^lK@EFBZ{r?kEjR^LT;e$TE=x$9%*(v0;*5E#YVwa%%p~K3nbcgd_?RTN z+XsCl_NZ5nNmYlUtwij-A|zjk{Pe))J+|5S{WT{Q-<679GP9j^qhlV&46t0<-8fSc(PL*Hac2)0k$p}DiU9qnOO`zW5TejJ0d z9J6l3FMM6;{Ynk$wfY~VSUjOx;O12HE8~NHb^P&rUe#DLy0lrXpQ6@+&V4;lby%xZ zhLy2OaZWAonhh5>lQ-XR@A7@GJyv$4Vi3t&RGBN6esIg{G~jK;QZYgVrGL~~T$0eN z)w$mh6(kH`z_-ZFo$*DcV4ef~ojGFG{<+3nb@xL`?E(ZY~{AWzZ1Ou_|7lRTb_$qUJlI2 zijn5lh|ranEUxCla;-2tu@k6qd-9?0UGslg|DS;W0vhwQy2=Jp`2YX_07*qoM6N<$ Eg4PWPTmS$7 diff --git a/chrome/app/theme/chromium/win/chromium.ico b/chrome/app/theme/chromium/win/chromium.ico index b15783ccbcf1b3f843007e5a45f23b9c15dd5cc2..173a8f4e8f8aaecb82aec344718824d1c78c6747 100644 GIT binary patch literal 270398 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

      |>WSPl{lEj> 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%0A?+dK@+42L&<#Aq*;<@vD<)C;C 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

      qc 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 a&g%xU+q=GQpuN+Yf`o(b{_c3|%l|)|GwLA# literal 42219 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 F{|~!NDZ&5% diff --git a/chrome/app/version_assembly/BUILD.gn b/chrome/app/version_assembly/BUILD.gn index d9151bcbdfe59..ca0252d960f88 100644 --- a/chrome/app/version_assembly/BUILD.gn +++ b/chrome/app/version_assembly/BUILD.gn @@ -24,8 +24,7 @@ windows_manifest("chrome_exe_manifest") { sources = [ as_invoker_manifest, common_controls_manifest, - default_compatibility_manifest, - version_assembly_output_file, + default_compatibility_manifest ] deps = [ diff --git a/chrome/app/version_assembly/version_assembly_manifest.template b/chrome/app/version_assembly/version_assembly_manifest.template index 9bd1fc58f9fb1..8478d639e0689 100644 --- a/chrome/app/version_assembly/version_assembly_manifest.template +++ b/chrome/app/version_assembly/version_assembly_manifest.template @@ -4,5 +4,5 @@ name='@MAJOR@.@MINOR@.@BUILD@.@PATCH@' version='@MAJOR@.@MINOR@.@BUILD@.@PATCH@' type='win32'/> - + diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 054c6e2a52628..6125baa2b3daa 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -613,7 +613,7 @@ jumbo_split_static_library("browser") { "invalidation/profile_invalidation_provider_factory.h", "io_thread.cc", "io_thread.h", - "language/chrome_language_detection_tab_helper.cc", + #"language/chrome_language_detection_tab_helper.cc", "language/chrome_language_detection_tab_helper.h", "language/language_model_factory.cc", "language/language_model_factory.h", @@ -1508,18 +1508,18 @@ jumbo_split_static_library("browser") { "tracing/crash_service_uploader.h", "tracing/navigation_tracing.cc", "tracing/navigation_tracing.h", - "translate/android/translate_utils.cc", - "translate/android/translate_utils.h", - "translate/chrome_translate_client.cc", - "translate/chrome_translate_client.h", - "translate/translate_accept_languages_factory.cc", - "translate/translate_accept_languages_factory.h", - "translate/translate_ranker_factory.cc", - "translate/translate_ranker_factory.h", - "translate/translate_ranker_metrics_provider.cc", - "translate/translate_ranker_metrics_provider.h", - "translate/translate_service.cc", - "translate/translate_service.h", + #"translate/android/translate_utils.cc", + #"translate/android/translate_utils.h", + #"translate/chrome_translate_client.cc", + #"translate/chrome_translate_client.h", + #"translate/translate_accept_languages_factory.cc", + #"translate/translate_accept_languages_factory.h", + #"translate/translate_ranker_factory.cc", + #"translate/translate_ranker_factory.h", + #"translate/translate_ranker_metrics_provider.cc", + #"translate/translate_ranker_metrics_provider.h", + #"translate/translate_service.cc", + #"translate/translate_service.h", "undo/bookmark_undo_service_factory.cc", "undo/bookmark_undo_service_factory.h", "update_client/chrome_update_query_params_delegate.cc", @@ -1612,6 +1612,7 @@ jumbo_split_static_library("browser") { "//base:i18n", "//base/allocator:buildflags", "//cc", + "//content/nw:nw_browser", "//chrome:extra_resources", "//chrome:resources", "//chrome:strings", @@ -1626,7 +1627,7 @@ jumbo_split_static_library("browser") { "//chrome/browser/metrics/variations:chrome_ui_string_overrider_factory", "//chrome/browser/net:probe_message_proto", "//chrome/browser/profiling_host", - "//chrome/browser/safe_browsing", + #"//chrome/browser/safe_browsing", "//chrome/browser/ssl:proto", "//chrome/browser/ui", "//chrome/browser/ui/webui/bluetooth_internals", @@ -1645,8 +1646,8 @@ jumbo_split_static_library("browser") { "//components/captive_portal", "//components/certificate_transparency", "//components/cloud_devices/common", - "//components/component_updater", - "//components/component_updater:crl_set_remover", + #"//components/component_updater", + #"//components/component_updater:crl_set_remover", "//components/consent_auditor", "//components/content_settings/core/browser", "//components/content_settings/core/common", @@ -1718,8 +1719,8 @@ jumbo_split_static_library("browser") { "//components/profile_metrics", "//components/proxy_config", "//components/query_parser", - "//components/rappor", - "//components/rappor:rappor_recorder", + #"//components/rappor", + #"//components/rappor:rappor_recorder", "//components/renderer_context_menu", "//components/resources", "//components/search", @@ -4570,7 +4571,11 @@ proto_library("resource_prefetch_predictor_proto") { } grit("resources") { - source = "browser_resources.grd" + if (nwjs_sdk) { + source = "browser_resources.grd" + } else { + source = "nwjs_resources.grd" + } # The .grd contains references to generated files. source_is_generated = true diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index e87cd2323a3e4..25c7c98ac77fa 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -109,6 +109,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" +#include "content/nw/src/nw_content.h" + using apps::AppShimHandler; using apps::ExtensionAppShimHandler; using base::UserMetricsAction; @@ -149,7 +151,7 @@ } Browser* browser = chrome::GetLastActiveBrowser(); - CHECK(browser); + //CHECK(browser); return browser; } @@ -376,7 +378,9 @@ - (void)awakeFromNib { [self initMenuState]; // Initialize the Profile menu. +#if 0 [self initProfileMenu]; +#endif } - (void)unregisterEventHandlers { @@ -519,6 +523,9 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app { return NSTerminateNow; } + if (!AppWindowRegistryUtil::CloseAllAppWindows(true)) + return NSTerminateCancel; + // Check if the preference is turned on. const PrefService* prefs = g_browser_process->local_state(); if (!prefs->GetBoolean(prefs::kConfirmToQuitEnabled)) { @@ -700,7 +707,11 @@ - (void)setUpdateCheckInterval { - (void)openStartupUrls { DCHECK(startupComplete_); - [self openUrlsReplacingNTP:startupUrls_]; + if (startupUrls_.size()) { + base::CommandLine::ForCurrentProcess()->AppendArg(startupUrls_[0].spec()); + base::CommandLine::ForCurrentProcess()->FixOrigArgv4Finder(startupUrls_[0].spec()); + } + //[self openUrlsReplacingNTP:startupUrls_]; startupUrls_.clear(); } @@ -772,7 +783,7 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notify { // If enabled, keep Chrome alive when apps are open instead of quitting all // apps. - quitWithAppsController_ = new QuitWithAppsController(); + // quitWithAppsController_ = new QuitWithAppsController(); // Dynamically update shortcuts for "Close Window" and "Close Tab" menu items. [[closeTabMenuItem_ menu] setDelegate:self]; @@ -1179,6 +1190,8 @@ - (void)commandDispatchUsingKeyModifiers:(id)sender { // browser windows. - (BOOL)applicationShouldHandleReopen:(NSApplication*)theApplication hasVisibleWindows:(BOOL)hasVisibleWindows { + return nw::ApplicationShouldHandleReopenHook(hasVisibleWindows) ? YES : NO; +#if 0 // If the browser is currently trying to quit, don't do anything and return NO // to prevent AppKit from doing anything. // TODO(rohitrao): Remove this code when http://crbug.com/40861 is resolved. @@ -1267,6 +1280,7 @@ - (BOOL)applicationShouldHandleReopen:(NSApplication*)theApplication // We've handled the reopen event, so return NO to tell AppKit not // to do anything. return NO; +#endif } - (void)initMenuState { @@ -1396,6 +1410,10 @@ - (void)openUrls:(const std::vector&)urls { startupUrls_.insert(startupUrls_.end(), urls.begin(), urls.end()); return; } + + nw::OSXOpenURLsHook(urls); + +#if 0 // Pick the last used browser from a regular profile to open the urls. Profile* profile = g_browser_process->profile_manager()->GetLastUsedProfileAllowedByPolicy(); @@ -1413,6 +1431,7 @@ - (void)openUrls:(const std::vector&)urls { : chrome::startup::IS_NOT_FIRST_RUN; StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run); launch.OpenURLsInBrowser(browser, false, urls); +#endif } - (void)getUrl:(NSAppleEventDescriptor*)event @@ -1494,6 +1513,7 @@ - (NSMenu*)applicationDockMenu:(NSApplication*)sender { if (profilesAdded) [dockMenu addItem:[NSMenuItem separatorItem]]; +#if 0 NSString* titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_WINDOW_MAC); base::scoped_nsobject item( [[NSMenuItem alloc] initWithTitle:titleStr @@ -1518,6 +1538,7 @@ - (NSMenu*)applicationDockMenu:(NSApplication*)sender { [item setEnabled:[self validateUserInterfaceItem:item]]; [dockMenu addItem:item]; } +#endif // TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit // tests which use the mock in place of the profile-initialized model. diff --git a/chrome/browser/apps/app_load_service.cc b/chrome/browser/apps/app_load_service.cc index 5d10150c92296..c8131a820efd5 100644 --- a/chrome/browser/apps/app_load_service.cc +++ b/chrome/browser/apps/app_load_service.cc @@ -4,6 +4,8 @@ #include "chrome/browser/apps/app_load_service.h" +#include "content/nw/src/nw_content.h" + #include "apps/app_restore_service.h" #include "apps/launcher.h" #include "chrome/browser/apps/app_load_service_factory.h" @@ -71,6 +73,8 @@ bool AppLoadService::LoadAndLaunch(const base::FilePath& extension_path, return false; } + nw::SetMainExtensionId(extension_id); + // Schedule the app to be launched once loaded. PostReloadAction& action = post_reload_actions_[extension_id]; action.action_type = LAUNCH_FOR_LOAD_AND_LAUNCH; diff --git a/chrome/browser/apps/app_shim/app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/app_shim_handler_mac.cc index c7b50eee1a122..6ec6af72856f6 100644 --- a/chrome/browser/apps/app_shim/app_shim_handler_mac.cc +++ b/chrome/browser/apps/app_shim/app_shim_handler_mac.cc @@ -22,13 +22,15 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" +#include "content/nw/src/nw_content.h" + namespace apps { namespace { void TerminateIfNoAppWindows() { bool app_windows_left = - AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile(0); + AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile(0, false); if (!app_windows_left) { chrome::AttemptExit(); } @@ -64,7 +66,8 @@ class AppShimHandlerRegistry : public content::NotificationObserver { } void MaybeTerminate() { - if (!browser_session_running_) { + if (!nw::IsReloadingApp()) { + //NW: #4164. browser_session_running_ never set to false // Post this to give AppWindows a chance to remove themselves from the // registry. base::ThreadTaskRunnerHandle::Get()->PostTask( diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc index 55d1449538e5b..ee9ee000f3973 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc @@ -327,7 +327,7 @@ const Extension* ExtensionAppShimHandler::MaybeGetAppForBrowser( } // static -void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { +void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window, bool user_force) { ExtensionAppShimHandler* handler = GetInstance(); Host* host = handler->FindHost( Profile::FromBrowserContext(app_window->browser_context()), @@ -338,7 +338,7 @@ void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { // App shims might be disabled or the shim is still starting up. AppWindowRegistry::Get( Profile::FromBrowserContext(app_window->browser_context())) - ->CloseAllAppWindowsForApp(app_window->extension_id()); + ->CloseAllAppWindowsForApp(app_window->extension_id(), user_force); } } @@ -643,7 +643,8 @@ void ExtensionAppShimHandler::OnShimQuit(Host* host) { const AppWindowList windows = delegate_->GetWindows(profile, app_id); for (AppWindowRegistry::const_iterator it = windows.begin(); it != windows.end(); ++it) { - (*it)->GetBaseWindow()->Close(); + if ((*it)->NWCanClose()) + (*it)->GetBaseWindow()->Close(); } } // Once the last window closes, flow will end up in OnAppDeactivated via diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h index 486d41487c363..959a85330ef3e 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h @@ -93,7 +93,7 @@ class ExtensionAppShimHandler : public AppShimHandler, static const extensions::Extension* MaybeGetAppForBrowser(Browser* browser); - static void QuitAppForWindow(extensions::AppWindow* app_window); + static void QuitAppForWindow(extensions::AppWindow* app_window, bool user_force = false); static void QuitHostedAppForWindow(Profile* profile, const std::string& app_id); diff --git a/chrome/browser/apps/app_window_registry_util.cc b/chrome/browser/apps/app_window_registry_util.cc index d8702debf325e..571bee28832f3 100644 --- a/chrome/browser/apps/app_window_registry_util.cc +++ b/chrome/browser/apps/app_window_registry_util.cc @@ -43,7 +43,7 @@ AppWindow* AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( // static bool AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile( - int window_type_mask) { + int window_type_mask, bool check_visible) { std::vector profiles = g_browser_process->profile_manager()->GetLoadedProfiles(); for (std::vector::const_iterator i = profiles.begin(); @@ -59,7 +59,7 @@ bool AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile( continue; for (const AppWindow* window : app_windows) { - if (!window->is_hidden() && + if ((!window->is_hidden() || !check_visible )&& (window_type_mask == 0 || (window->window_type() & window_type_mask))) return true; @@ -70,7 +70,7 @@ bool AppWindowRegistryUtil::IsAppWindowVisibleInAnyProfile( } // static -void AppWindowRegistryUtil::CloseAllAppWindows() { +bool AppWindowRegistryUtil::CloseAllAppWindows(bool user_force) { std::vector profiles = g_browser_process->profile_manager()->GetLoadedProfiles(); for (std::vector::const_iterator i = profiles.begin(); @@ -86,8 +86,13 @@ void AppWindowRegistryUtil::CloseAllAppWindows() { AppWindowList window_list_copy(registry->app_windows()); for (auto* window : window_list_copy) { // Ensure window is still valid. - if (base::ContainsValue(registry->app_windows(), window)) - window->GetBaseWindow()->Close(); + if (base::ContainsValue(registry->app_windows(), window)) { + if (window->NWCanClose(user_force)) + window->GetBaseWindow()->Close(); + else + return false; + } } } + return true; } diff --git a/chrome/browser/apps/app_window_registry_util.h b/chrome/browser/apps/app_window_registry_util.h index 8fd6b358cc8ca..5dcf02ecd612d 100644 --- a/chrome/browser/apps/app_window_registry_util.h +++ b/chrome/browser/apps/app_window_registry_util.h @@ -21,10 +21,10 @@ class AppWindowRegistryUtil { // Returns true if the number of visible app windows registered across all // browser contexts is non-zero. |window_type_mask| is a bitwise OR filter of // AppWindow::WindowType, or 0 for any window type. - static bool IsAppWindowVisibleInAnyProfile(int window_type_mask); + static bool IsAppWindowVisibleInAnyProfile(int window_type_mask, bool check_visible = true); // Close all app windows in all profiles. - static void CloseAllAppWindows(); + static bool CloseAllAppWindows(bool user_force = false); }; #endif // CHROME_BROWSER_APPS_APP_WINDOW_REGISTRY_UTIL_H_ diff --git a/chrome/browser/apps/browser_context_keyed_service_factories.cc b/chrome/browser/apps/browser_context_keyed_service_factories.cc index 73955307fb649..e1144eace4e1f 100644 --- a/chrome/browser/apps/browser_context_keyed_service_factories.cc +++ b/chrome/browser/apps/browser_context_keyed_service_factories.cc @@ -13,7 +13,7 @@ namespace chrome_apps { void EnsureBrowserContextKeyedServiceFactoriesBuilt() { apps::EnsureBrowserContextKeyedServiceFactoriesBuilt(); - AppShortcutManagerFactory::GetInstance(); + //AppShortcutManagerFactory::GetInstance(); apps::AppLoadServiceFactory::GetInstance(); } diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc index 7a6a105a639b3..2e2aa4b248192 100644 --- a/chrome/browser/background/background_application_list_model.cc +++ b/chrome/browser/background/background_application_list_model.cc @@ -249,8 +249,10 @@ bool BackgroundApplicationListModel::IsBackgroundApp( // manifest. // Not a background app if we don't have the background permission. + // NWJS: nwjs_default_app is listed as background app and prevents + // quit so we need to disable it here if (!extension.permissions_data()->HasAPIPermission( - APIPermission::kBackground)) { + APIPermission::kBackground, true)) { return false; } diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc index 52f0cd2c58b66..42cf3e006c185 100644 --- a/chrome/browser/background/background_contents_service.cc +++ b/chrome/browser/background/background_contents_service.cc @@ -387,6 +387,7 @@ void BackgroundContentsService::Observe( } case extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { +#if 0 Profile* profile = content::Source(source).ptr(); const Extension* extension = nullptr; if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { @@ -421,6 +422,7 @@ void BackgroundContentsService::Observe( // Restart the extension. RestartForceInstalledExtensionOnCrash(extension, profile); } +#endif break; } diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 8aab172c63189..09b22530ec203 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h @@ -263,10 +263,11 @@ class BrowserProcess { virtual net_log::ChromeNetLog* net_log() = 0; virtual component_updater::ComponentUpdateService* component_updater() = 0; +#if 0 virtual component_updater::SupervisedUserWhitelistInstaller* supervised_user_whitelist_installer() = 0; - +#endif virtual MediaFileSystemRegistry* media_file_system_registry() = 0; virtual WebRtcLogUploader* webrtc_log_uploader() = 0; diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index a5237f650fa0d..e35631cb3d1a1 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -342,8 +342,10 @@ void BrowserProcessImpl::StartTearDown() { // that URLFetcher operation before going away.) metrics_services_manager_.reset(); intranet_redirect_detector_.reset(); +#if 0 if (safe_browsing_service_.get()) safe_browsing_service()->ShutDown(); +#endif network_time_tracker_.reset(); #if BUILDFLAG(ENABLE_PLUGINS) plugins_resource_service_.reset(); @@ -981,6 +983,7 @@ net_log::ChromeNetLog* BrowserProcessImpl::net_log() { return net_log_.get(); } +#if 1 component_updater::ComponentUpdateService* BrowserProcessImpl::component_updater() { if (component_updater_) @@ -996,7 +999,9 @@ BrowserProcessImpl::component_updater() { return component_updater_.get(); } +#endif +#if 0 component_updater::SupervisedUserWhitelistInstaller* BrowserProcessImpl::supervised_user_whitelist_installer() { if (!supervised_user_whitelist_installer_) { @@ -1008,6 +1013,7 @@ BrowserProcessImpl::supervised_user_whitelist_installer() { } return supervised_user_whitelist_installer_.get(); } +#endif void BrowserProcessImpl::ResourceDispatcherHostCreated() { resource_dispatcher_host_delegate_ = @@ -1075,8 +1081,11 @@ void BrowserProcessImpl::PreCreateThreads( #if BUILDFLAG(ENABLE_EXTENSIONS) // chrome-extension:// URLs are safe to request anywhere, but may only // commit (including in iframes) in extension processes. - ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeIsolatedScheme( - extensions::kExtensionScheme, true); + // NWJS: Upstream: Remove command line/field trial support for + // disabling Isolate + // Extensions. https://codereview.chromium.org/2850793005 + ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( + extensions::kExtensionScheme); #endif if (command_line.HasSwitch(network::switches::kLogNetLog)) { @@ -1227,9 +1236,11 @@ void BrowserProcessImpl::CreateSafeBrowsingService() { // Set this flag to true so that we don't retry indefinitely to // create the service class if there was an error. created_safe_browsing_service_ = true; +#if 0 safe_browsing_service_ = safe_browsing::SafeBrowsingService::CreateSafeBrowsingService(); safe_browsing_service_->Initialize(); +#endif } void BrowserProcessImpl::CreateSubresourceFilterRulesetService() { @@ -1333,20 +1344,24 @@ void BrowserProcessImpl::ApplyAllowCrossOriginAuthPromptPolicy() { #if !defined(OS_ANDROID) void BrowserProcessImpl::ApplyMetricsReportingPolicy() { +#if 0 GoogleUpdateSettings::CollectStatsConsentTaskRunner()->PostTask( FROM_HERE, base::BindOnce( base::IgnoreResult(&GoogleUpdateSettings::SetCollectStatsConsent), ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled())); +#endif } #endif void BrowserProcessImpl::CacheDefaultWebClientState() { +#if 0 #if defined(OS_CHROMEOS) cached_default_web_client_state_ = shell_integration::IS_DEFAULT; #elif !defined(OS_ANDROID) cached_default_web_client_state_ = shell_integration::GetDefaultBrowser(); #endif +#endif } void BrowserProcessImpl::Pin() { diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 3c9e7851741b3..be71c993d135c 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -154,8 +154,10 @@ class BrowserProcessImpl : public BrowserProcess, net_log::ChromeNetLog* net_log() override; component_updater::ComponentUpdateService* component_updater() override; +#if 0 component_updater::SupervisedUserWhitelistInstaller* supervised_user_whitelist_installer() override; +#endif MediaFileSystemRegistry* media_file_system_registry() override; WebRtcLogUploader* webrtc_log_uploader() override; network_time::NetworkTimeTracker* network_time_tracker() override; diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 58912721f986b..b63fdc0a608ac 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -73,6 +73,8 @@ + + diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index b4b88534d0210..7f2ab1b251660 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc @@ -152,6 +152,7 @@ base::OnceClosure UIThreadTrampoline(base::OnceClosure callback) { } #endif // BUILDFLAG(ENABLE_NACL) + template void IgnoreArgumentHelper(base::OnceClosure callback, T unused_argument) { std::move(callback).Run(); @@ -254,12 +255,14 @@ bool DoesOriginMatchEmbedderMask(int origin_type_mask, // Callback for when cookies have been deleted. Invokes NotifyIfDone. // Receiving |cookie_manager| as a parameter so that the receive pipe is // not deleted before the response is received. +#if 0 void OnClearedCookies(base::OnceClosure done, network::mojom::CookieManagerPtr cookie_manager, uint32_t num_deleted) { DCHECK_CURRENTLY_ON(BrowserThread::UI); std::move(done).Run(); } +#endif } // namespace @@ -644,6 +647,7 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( // hours/days to the safebrowsing cookies since they aren't the result of // any user action. if (delete_begin_ == base::Time()) { +#if 0 safe_browsing::SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); if (sb_service) { @@ -666,6 +670,7 @@ void ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData( CreatePendingTaskCompletionClosure(), std::move(cookie_manager))); } +#endif } MediaDeviceIDSalt::Reset(profile_->GetPrefs()); diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 4a477cf3003ea..22cc511d2e320 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -13,6 +13,11 @@ #include #include + +#include "content/nw/src/browser/nw_chrome_browser_hooks.h" +#include "content/nw/src/browser/nw_content_browser_hooks.h" + + #include "base/at_exit.h" #include "base/base_switches.h" #include "base/bind.h" @@ -517,7 +522,9 @@ OSStatus KeychainCallback(SecKeychainEvent keychain_event, void RegisterComponentsForUpdate(PrefService* profile_prefs) { auto* const cus = g_browser_process->component_updater(); - +#if 1 + RegisterWidevineCdmComponent(cus); +#else if (base::FeatureList::IsEnabled(features::kImprovedRecoveryComponent)) RegisterRecoveryImprovedComponent(cus, g_browser_process->local_state()); else @@ -588,6 +595,7 @@ void RegisterComponentsForUpdate(PrefService* profile_prefs) { RegisterThirdPartyModuleListComponent(cus); #endif // defined(GOOGLE_CHROME_BUILD) #endif // defined(OS_WIN) +#endif // disable component updater } #if !defined(OS_ANDROID) @@ -598,6 +606,9 @@ bool ProcessSingletonNotificationCallback( if (!g_browser_process || g_browser_process->IsShuttingDown()) return false; + if (!nw::ProcessSingletonNotificationCallbackHook(command_line, current_directory)) + return false; + if (command_line.HasSwitch(switches::kOriginalProcessStartTime)) { std::string start_time_string = command_line.GetSwitchValueASCII(switches::kOriginalProcessStartTime); @@ -972,7 +983,7 @@ void ChromeBrowserMainParts::StartMetricsRecording() { group_name); } - g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(true); + g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(false); } void ChromeBrowserMainParts::RecordBrowserStartupTime() { @@ -1147,9 +1158,13 @@ int ChromeBrowserMainParts::PreCreateThreads() { // should be deferred to PreMainMessageLoopRunImpl. TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreads"); + result_code_ = PreCreateThreadsImpl(); if (result_code_ == service_manager::RESULT_CODE_NORMAL_EXIT) { + result_code_ = nw::MainPartsPreCreateThreadsHook(); + if (result_code_ != service_manager::RESULT_CODE_NORMAL_EXIT) + return result_code_; #if !defined(OS_ANDROID) // These members must be initialized before exiting this function normally. DCHECK(master_prefs_.get()); @@ -1486,6 +1501,8 @@ void ChromeBrowserMainParts::PreMainMessageLoopRun() { result_code_ = PreMainMessageLoopRunImpl(); + nw::MainPartsPreMainMessageLoopRunHook(); + for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) chrome_extra_parts_[i]->PreMainMessageLoopRun(); } @@ -1818,6 +1835,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { #endif // BUILDFLAG(ENABLE_BACKGROUND_MODE) // Post-profile init --------------------------------------------------------- +#if 0 TranslateService::Initialize(); if (base::FeatureList::IsEnabled(features::kGeoLanguage) || language::GetOverrideLanguageModel() == @@ -1827,7 +1845,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { ->GetConnector() ->Clone()); } - +#endif // Needs to be done before PostProfileInit, since login manager on CrOS is // called inside PostProfileInit. content::WebUIControllerFactory::RegisterFactory( @@ -1844,7 +1862,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // (requires supporting early exit). PostProfileInit(); -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if 0 //!defined(OS_ANDROID) && !defined(OS_CHROMEOS) // Execute first run specific code after the PrefService has been initialized // and preferences have been registered since some of the import code depends // on preferences. @@ -2007,8 +2025,10 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { PreBrowserStart(); +#if 1 if (!parsed_command_line().HasSwitch(switches::kDisableComponentUpdate)) RegisterComponentsForUpdate(profile_->GetPrefs()); +#endif #if defined(OS_ANDROID) variations::VariationsService* variations_service = @@ -2181,7 +2201,7 @@ void ChromeBrowserMainParts::PostMainMessageLoopRun() { // Some tests don't set parameters.ui_task, so they started translate // language fetch that was never completed so we need to cleanup here // otherwise it will be done by the destructor in a wrong thread. - TranslateService::Shutdown(parameters().ui_task == NULL); + //TranslateService::Shutdown(parameters().ui_task == NULL); if (notify_result_ == ProcessSingleton::PROCESS_NONE) process_singleton_->Cleanup(); @@ -2229,6 +2249,7 @@ void ChromeBrowserMainParts::PostDestroyThreads() { process_singleton_.reset(); device_event_log::Shutdown(); + nw::MainPartsPostDestroyThreadsHook(); // We need to do this check as late as possible, but due to modularity, this // may be the last point in Chrome. This would be more effective if done at // a higher level on the stack, so that it is impossible for an early return diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index d59e1ab892cca..5d5d63aac42ee 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm @@ -120,6 +120,7 @@ void EnsureMetadataNeverIndexFile(const base::FilePath& user_data_dir) { // The framework is only distributed with branded Google Chrome builds. [[KeystoneGlue defaultKeystoneGlue] registerWithKeystone]; +#if 0 // Disk image installation is sort of a first-run task, so it shares the // no first run switches. // @@ -139,7 +140,9 @@ void EnsureMetadataNeverIndexFile(const base::FilePath& user_data_dir) { exit(0); } } +#endif +#if 1 // Now load the nib (from the right bundle). base::scoped_nsobject nib( [[NSNib alloc] initWithNibNamed:@"MainMenu" @@ -150,6 +153,11 @@ void EnsureMetadataNeverIndexFile(const base::FilePath& user_data_dir) { [nib instantiateWithOwner:NSApp topLevelObjects:&top_level_objects]; for (NSObject* object : top_level_objects) [object retain]; +#else + AppController* delegate = [AppController alloc]; + [NSApp setDelegate:delegate]; +#endif + // Make sure the app controller has been created. DCHECK([NSApp delegate]); diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index 8ff0d2d5244fb..d67b708cbc1ff 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc @@ -393,6 +393,7 @@ void ShowCloseBrowserFirstMessageBox() { l10n_util::GetStringUTF16(IDS_UNINSTALL_CLOSE_APP)); } +#if 0 void MaybePostSettingsResetPrompt() { if (base::FeatureList::IsEnabled(safe_browsing::kSettingsResetPrompt)) { content::BrowserThread::PostAfterStartupTask( @@ -402,6 +403,7 @@ void MaybePostSettingsResetPrompt() { base::Bind(safe_browsing::MaybeShowSettingsResetPromptWithDelay)); } } +#endif } // namespace @@ -544,6 +546,7 @@ void ChromeBrowserMainPartsWin::PostBrowserStart() { // complete run of the Chrome Cleanup tool. If post-cleanup settings reset is // enabled, we delay checks for settings reset prompt until the scheduled // reset is finished. +#if 0 if (safe_browsing::PostCleanupSettingsResetter::IsEnabled()) { // Using last opened profiles, because we want to find reset the profile // that was open in the last Chrome run, which may not be open yet in @@ -556,6 +559,7 @@ void ChromeBrowserMainPartsWin::PostBrowserStart() { } else { MaybePostSettingsResetPrompt(); } +#endif // Record UMA data about whether the fault-tolerant heap is enabled. // Use a delayed task to minimize the impact on startup time. diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index ec54b365d46d8..5b4359d176da5 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -3,12 +3,19 @@ // found in the LICENSE file. #include "chrome/browser/chrome_content_browser_client.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "components/crash/content/app/crash_reporter_client.h" #include #include #include #include +#include "content/nw/src/common/shell_switches.h" +#include "content/nw/src/nw_content.h" +#include "content/nw/src/nw_base.h" +#include "chrome/browser/profiles/profile_manager.h" + #include "base/base_switches.h" #include "base/bind.h" #include "base/bind_helpers.h" @@ -398,6 +405,7 @@ #include "extensions/browser/extension_navigation_throttle.h" #include "extensions/browser/extension_protocols.h" #include "extensions/browser/extension_registry.h" +#include "chrome/browser/extensions/extension_service.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" @@ -657,7 +665,7 @@ breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost( base::PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); { ANNOTATE_SCOPED_MEMORY_LEAK; - bool upload = (getenv(env_vars::kHeadless) == NULL); + bool upload = !crash_reporter::GetCrashReporterClient()->IsRunningUnattended(); breakpad::CrashHandlerHostLinux* crash_handler = new breakpad::CrashHandlerHostLinux(process_type, dumps_path, upload); crash_handler->StartUploaderThread(); @@ -740,18 +748,17 @@ class CertificateReportingServiceCertReporter : public SSLCertReporter { public: explicit CertificateReportingServiceCertReporter( content::WebContents* web_contents) - : service_(CertificateReportingServiceFactory::GetForBrowserContext( - web_contents->GetBrowserContext())) {} + {} ~CertificateReportingServiceCertReporter() override {} // SSLCertReporter implementation void ReportInvalidCertificateChain( const std::string& serialized_report) override { - service_->Send(serialized_report); + //service_->Send(serialized_report); } private: - CertificateReportingService* service_; + //CertificateReportingService* service_; DISALLOW_COPY_AND_ASSIGN(CertificateReportingServiceCertReporter); }; @@ -806,6 +813,7 @@ void GetGuestViewDefaultContentSettingRules( std::string(), incognito)); } +#if 0 AppLoadedInTabSource ClassifyAppLoadedInTabSource( const GURL& opener_url, const extensions::Extension* target_platform_app) { @@ -827,6 +835,7 @@ AppLoadedInTabSource ClassifyAppLoadedInTabSource( // The forbidden app URL was being opened by a non-extension page (e.g. http). return APP_LOADED_IN_TAB_SOURCE_OTHER; } +#endif #endif // BUILDFLAG(ENABLE_EXTENSIONS) void CreateBudgetService(blink::mojom::BudgetServiceRequest request, @@ -1403,6 +1412,9 @@ bool ChromeContentBrowserClient::ShouldLockToOrigin( return false; } #endif + if (nw::PinningRenderer()) + return false; + return true; } @@ -1599,6 +1611,24 @@ bool ChromeContentBrowserClient::MayReuseHost( bool ChromeContentBrowserClient::ShouldTryToUseExistingProcessHost( content::BrowserContext* browser_context, const GURL& url) { + // PDF extension should use new process, or there is a loop of IPC + // message BrowserPluginHostMsg_SetFocus and InputMsg_SetFocus + // #4335 + + if (url.SchemeIs(extensions::kExtensionScheme)) { + if (url.host() == nw::GetMainExtensionId() && !content::RenderProcessHostImpl::main_host()) + return false; //other extensions could load before the main + //extension NWJS#5483 + if (url.host() == extension_misc::kPdfExtensionId) + return false; + } else if (url.SchemeIs(content::kGuestScheme)) + return false; + + if (nw::PinningRenderer()) + return true; + else + return false; +#if 0 // It has to be a valid URL for us to check for an extension. if (!url.is_valid()) return false; @@ -1611,6 +1641,7 @@ bool ChromeContentBrowserClient::ShouldTryToUseExistingProcessHost( #else return false; #endif +#endif } void ChromeContentBrowserClient::SiteInstanceGotProcess( @@ -1868,7 +1899,10 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( homedir.value().c_str()); #endif + command_line->AppendSwitchPath(switches::kNWAppPath, nw::package()->path()); if (process_type == switches::kRendererProcess) { + command_line->AppendSwitch(switches::kNWJS); + content::RenderProcessHost* process = content::RenderProcessHost::FromID(child_process_id); Profile* profile = @@ -1984,6 +2018,7 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( // Please keep this in alphabetical order. static const char* const kSwitchNames[] = { + switches::kEnableSpellChecking, autofill::switches::kDisablePasswordGeneration, autofill::switches::kEnablePasswordGeneration, autofill::switches::kEnableSuggestionsWithSubstringMatch, @@ -2278,6 +2313,22 @@ bool ChromeContentBrowserClient::AllowSetCookie( return allow; } +base::FilePath ChromeContentBrowserClient::GetRootPath() { + std::string id = nw::GetMainExtensionId(); + base::FilePath path; + extensions::ExtensionSystem* extension_system = + extensions::ExtensionSystem::Get(ProfileManager::GetPrimaryUserProfile()); + if (extension_system) { + ExtensionService* extension_service = + extension_system->extension_service(); + const extensions::Extension* extension = + extension_service->GetExtensionById(id, true); + if (extension) + path = extension->path(); + } + return path; +} + void ChromeContentBrowserClient::AllowWorkerFileSystem( const GURL& url, content::ResourceContext* context, @@ -2689,6 +2740,13 @@ bool ChromeContentBrowserClient::CanCreateWindow( DCHECK(profile); *no_javascript_access = false; + auto* registry = extensions::ExtensionRegistry::Get(profile); + if (registry) { + const Extension* extension = + registry->enabled_extensions().GetExtensionOrAppByURL(opener_url); + if (extension && extension->is_nwjs_app()) + return true; + } // If the opener is trying to create a background window but doesn't have // the appropriate permission, fail the attempt. if (container_type == content::mojom::WindowContainerType::BACKGROUND) { @@ -2728,6 +2786,9 @@ bool ChromeContentBrowserClient::CanCreateWindow( const Extension* extension = registry->enabled_extensions().GetExtensionOrAppByURL(target_url); if (extension && extension->is_platform_app()) { +#if 1 + return true; +#else UMA_HISTOGRAM_ENUMERATION( "Extensions.AppLoadedInTab", ClassifyAppLoadedInTabSource(opener_url, extension), @@ -2735,6 +2796,7 @@ bool ChromeContentBrowserClient::CanCreateWindow( // window.open() may not be used to load v2 apps in a regular tab. return false; +#endif } } #endif @@ -3007,6 +3069,8 @@ void ChromeContentBrowserClient::OverrideWebkitPrefs( for (size_t i = 0; i < extra_parts_.size(); ++i) extra_parts_[i]->OverrideWebkitPrefs(rvh, web_prefs); + + nw::OverrideWebkitPrefsHook(rvh, web_prefs); } void ChromeContentBrowserClient::BrowserURLHandlerCreated( @@ -3294,10 +3358,12 @@ void ChromeContentBrowserClient::ExposeInterfacesToRenderer( scoped_refptr ui_task_runner = content::BrowserThread::GetTaskRunnerForThread( content::BrowserThread::UI); +#if 0 registry->AddInterface( base::Bind(&rappor::RapporRecorderImpl::Create, g_browser_process->rappor_service()), ui_task_runner); +#endif registry->AddInterface( base::BindRepeating(&metrics::CallStackProfileCollector::Create, metrics::CallStackProfileParams::RENDERER_PROCESS)); @@ -3311,7 +3377,7 @@ void ChromeContentBrowserClient::ExposeInterfacesToRenderer( base::RetainedRef(context))); } -#if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE) +#if 0 if (safe_browsing_service_) { content::ResourceContext* resource_context = render_process_host->GetBrowserContext()->GetResourceContext(); @@ -3860,9 +3926,11 @@ void ChromeContentBrowserClient::InitWebContextInterfaces() { std::make_unique>(); +#if 0 // Register mojo ContentTranslateDriver interface only for main frame. frame_interfaces_parameterized_->AddInterface(base::BindRepeating( &ChromeLanguageDetectionTabHelper::BindContentTranslateDriver)); +#endif frame_interfaces_parameterized_->AddInterface( base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver)); @@ -3962,7 +4030,7 @@ ChromeContentBrowserClient::CreateURLLoaderThrottles( base::FeatureList::IsEnabled(network::features::kNetworkService); std::vector> result; -#if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE) +#if 0 //defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE) // Null-check safe_browsing_service_ as in unit tests |resource_context| is a // MockResourceContext and the cast doesn't work. if (safe_browsing_service_) { @@ -4186,7 +4254,7 @@ void ChromeContentBrowserClient::CreateUsbDeviceManager( if (!base::FeatureList::IsEnabled(features::kWebUsb)) return; -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if 0 // WebUSB is not supported in Apps/Extensions. https://crbug.com/770896 if (render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs( extensions::kExtensionScheme)) { @@ -4212,7 +4280,7 @@ void ChromeContentBrowserClient::CreateUsbChooserService( if (!base::FeatureList::IsEnabled(features::kWebUsb)) return; -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if 0 //BUILDFLAG(ENABLE_EXTENSIONS) // WebUSB is not supported in Apps/Extensions. https://crbug.com/770896 if (render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs( extensions::kExtensionScheme)) { @@ -4437,6 +4505,9 @@ void ChromeContentBrowserClient::SetDefaultQuotaSettingsForTesting( safe_browsing::UrlCheckerDelegate* ChromeContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate( content::ResourceContext* resource_context) { +#if 1 + return nullptr; +#else DCHECK_CURRENTLY_ON(BrowserThread::IO); ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); @@ -4452,4 +4523,5 @@ ChromeContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate( } return safe_browsing_url_checker_delegate_.get(); +#endif } diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index d392303a78492..05082380d168b 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -198,6 +198,7 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { int render_process_id, int render_frame_id, const net::CookieOptions& options) override; + base::FilePath GetRootPath() override; void AllowWorkerFileSystem( const GURL& url, content::ResourceContext* context, diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc index cbbba67286ea6..c327697ff4bec 100644 --- a/chrome/browser/chrome_quota_permission_context.cc +++ b/chrome/browser/chrome_quota_permission_context.cc @@ -205,7 +205,7 @@ void ChromeQuotaPermissionContext::RequestQuotaPermission( // The tab has no UI service for presenting the permissions request. LOG(WARNING) << "Attempt to request quota from a background page: " << render_process_id << "," << params.render_frame_id; - DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_CANCELLED); + DispatchCallbackOnIOThread(callback, QUOTA_PERMISSION_RESPONSE_ALLOW); } void ChromeQuotaPermissionContext::DispatchCallbackOnIOThread( diff --git a/chrome/browser/component_updater/file_type_policies_component_installer.cc b/chrome/browser/component_updater/file_type_policies_component_installer.cc index fa8634812d554..68ce28f6b3b4b 100644 --- a/chrome/browser/component_updater/file_type_policies_component_installer.cc +++ b/chrome/browser/component_updater/file_type_policies_component_installer.cc @@ -38,6 +38,7 @@ const uint8_t kFileTypePoliciesPublicKeySHA256[32] = { const char kFileTypePoliciesManifestName[] = "File Type Policies"; void LoadFileTypesFromDisk(const base::FilePath& pb_path) { +#if 0 if (pb_path.empty()) return; @@ -52,6 +53,7 @@ void LoadFileTypesFromDisk(const base::FilePath& pb_path) { safe_browsing::FileTypePolicies::GetInstance()->PopulateFromDynamicUpdate( binary_pb); +#endif } } // namespace diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index b7129778ef694..2396d44f1ac63 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc @@ -88,6 +88,7 @@ bool is_sw_reporter_enabled = false; // is complete. This is used only in tests. base::OnceClosure* registration_cb_for_testing = new base::OnceClosure(); +#if 0 void SRTHasCompleted(SRTCompleted value) { UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Cleaner.HasCompleted", value, SRT_COMPLETED_MAX); @@ -124,13 +125,17 @@ void ReportUploadsWithUma(const base::string16& upload_results) { UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.LastUploadResult", last_result); } +#endif +#if 0 void ReportExperimentError(SoftwareReporterExperimentError error) { UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.ExperimentErrors", error, SW_REPORTER_EXPERIMENT_ERROR_MAX); } +#endif // Ensures |str| contains only alphanumeric characters and characters from // |extras|, and is not longer than |max_length|. +#if 0 bool ValidateString(const std::string& str, const std::string& extras, size_t max_length) { @@ -140,6 +145,9 @@ bool ValidateString(const std::string& str, extras.find(c) != std::string::npos; }); } +#endif + +#if 0 std::string GenerateSessionId() { std::string session_id; @@ -349,6 +357,8 @@ void ReportUMAForLastCleanerRun() { } } +#endif + void ReportOnDemandUpdateSucceededHistogram(bool value) { UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.OnDemandUpdateSucceeded", value); } @@ -388,6 +398,7 @@ void SwReporterInstallerPolicy::ComponentReady( const base::Version& version, const base::FilePath& install_dir, std::unique_ptr manifest) { +#if 0 safe_browsing::SwReporterInvocationSequence invocations(version); const base::FilePath exe_path(install_dir.Append(kSwReporterExeName)); if (ExtractInvocationSequenceFromManifest(exe_path, std::move(manifest), @@ -396,6 +407,7 @@ void SwReporterInstallerPolicy::ComponentReady( // |safe_browsing::OnSwReporterReady| to the UI thread. on_component_ready_callback_.Run(std::move(invocations)); } +#endif } base::FilePath SwReporterInstallerPolicy::GetRelativeInstallDir() const { @@ -415,6 +427,7 @@ std::string SwReporterInstallerPolicy::GetName() const { update_client::InstallerAttributes SwReporterInstallerPolicy::GetInstallerAttributes() const { update_client::InstallerAttributes attributes; +#if 0 if (base::FeatureList::IsEnabled( safe_browsing::kChromeCleanupDistributionFeature)) { // Pass the tag parameter to the installer as the "tag" attribute; it will @@ -437,6 +450,7 @@ SwReporterInstallerPolicy::GetInstallerAttributes() const { attributes[kTagParam] = tag; } } +#endif return attributes; } @@ -472,6 +486,9 @@ void SwReporterOnDemandFetcher::OnEvent(Events event, const std::string& id) { } void RegisterSwReporterComponent(ComponentUpdateService* cus) { +#if 1 + return; +#else base::ScopedClosureRunner runner(std::move(*registration_cb_for_testing)); // Don't install the component if not allowed by policy. This prevents @@ -499,6 +516,7 @@ void RegisterSwReporterComponent(ComponentUpdateService* cus) { auto installer = base::MakeRefCounted( std::make_unique(base::BindRepeating(lambda))); installer->Register(cus, runner.Release()); +#endif } void SetRegisterSwReporterComponentCallbackForTesting( diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 06da21758e186..ab6613926bf2e 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc @@ -508,7 +508,8 @@ bool DevToolsUIBindings::IsValidFrontendURL(const GURL& url) { return true; } - return SanitizeFrontendURL(url).spec() == url.spec(); + //NW: webview.showDevTools in container; webview-localfile case; changed in c2db881506f + return SanitizeFrontendURL(url).spec() == url.spec() || url == GURL(url::kAboutBlankURL); } bool DevToolsUIBindings::IsValidRemoteFrontendURL(const GURL& url) { @@ -835,7 +836,7 @@ void DevToolsUIBindings::AppendToFile(const std::string& url, } void DevToolsUIBindings::RequestFileSystems() { - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); std::vector file_systems = file_helper_->GetFileSystems(); base::ListValue file_systems_value; @@ -846,20 +847,20 @@ void DevToolsUIBindings::RequestFileSystems() { } void DevToolsUIBindings::AddFileSystem(const std::string& type) { - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); file_helper_->AddFileSystem( type, base::Bind(&DevToolsUIBindings::ShowDevToolsInfoBar, weak_factory_.GetWeakPtr())); } void DevToolsUIBindings::RemoveFileSystem(const std::string& file_system_path) { - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); file_helper_->RemoveFileSystem(file_system_path); } void DevToolsUIBindings::UpgradeDraggedFileSystemPermissions( const std::string& file_system_url) { - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); file_helper_->UpgradeDraggedFileSystemPermissions( file_system_url, base::Bind(&DevToolsUIBindings::ShowDevToolsInfoBar, weak_factory_.GetWeakPtr())); @@ -870,7 +871,7 @@ void DevToolsUIBindings::IndexPath( const std::string& file_system_path, const std::string& excluded_folders_message) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); if (!file_helper_->IsFileSystemAdded(file_system_path)) { IndexingDone(index_request_id, file_system_path); return; @@ -917,7 +918,7 @@ void DevToolsUIBindings::SearchInPath(int search_request_id, const std::string& file_system_path, const std::string& query) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); + //CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_); if (!file_helper_->IsFileSystemAdded(file_system_path)) { SearchCompleted(search_request_id, file_system_path, @@ -1317,11 +1318,15 @@ void DevToolsUIBindings::SearchCompleted( void DevToolsUIBindings::ShowDevToolsInfoBar( const base::string16& message, const DevToolsInfoBarDelegate::Callback& callback) { +#if 1 + callback.Run(true); // #4602 +#else if (!delegate_->GetInfoBarService()) { callback.Run(false); return; } DevToolsInfoBarDelegate::Create(message, callback); +#endif } void DevToolsUIBindings::AddDevToolsExtensionsToClient() { diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index 2b93acddaea6f..feb4ed03a542f 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc @@ -717,6 +717,8 @@ void DevToolsWindow::ToggleDevToolsWindow( // If window is docked and visible, we hide it on toggle. If window is // undocked, we show (activate) it. + if (window->headless_) + return; if (!window->is_docked_ || do_open) window->ScheduleShow(action); else @@ -827,6 +829,8 @@ void DevToolsWindow::Show(const DevToolsToggleAction& action) { bool should_show_window = !browser_ || (action.type() != DevToolsToggleAction::kInspect); + should_show_window = should_show_window && !headless_; + if (!browser_) CreateDevToolsBrowser(); @@ -915,7 +919,8 @@ DevToolsWindow::DevToolsWindow(FrontendType frontend_type, std::unique_ptr main_web_contents, DevToolsUIBindings* bindings, WebContents* inspected_web_contents, - bool can_dock) + bool can_dock, + bool headless) : frontend_type_(frontend_type), profile_(profile), main_web_contents_(main_web_contents.get()), @@ -926,6 +931,7 @@ DevToolsWindow::DevToolsWindow(FrontendType frontend_type, owned_main_web_contents_(std::move(main_web_contents)), can_dock_(can_dock), close_on_detach_(true), + headless_(headless), // This initialization allows external front-end to work without changes. // We don't wait for docking call, but instead immediately show undocked. // Passing "dockSide=undocked" parameter ensures proper UI. @@ -935,7 +941,9 @@ DevToolsWindow::DevToolsWindow(FrontendType frontend_type, ready_for_test_(false) { // Set up delegate, so we get fully-functional window immediately. // It will not appear in UI though until |life_stage_ == kLoadCompleted|. - main_web_contents_->SetDelegate(this); + if (!headless) //NWJS#4709: keep delegate to web_view_guest so the + //shortcut is handled there + main_web_contents_->SetDelegate(this); // Bindings take ownership over devtools as its delegate. bindings_->SetDelegate(this); data_use_measurement::DataUseWebContentsObserver::CreateForWebContents( @@ -984,7 +992,7 @@ DevToolsWindow* DevToolsWindow::Create( bool can_dock, const std::string& settings, const std::string& panel, - bool has_other_clients) { + bool has_other_clients, content::WebContents* cdt_web_contents) { using DTPH = policy::DeveloperToolsPolicyHandler; // TODO(pfeldman): Implement handling for // Availability::kDisallowedForForceInstalledExtensions @@ -1019,6 +1027,20 @@ DevToolsWindow* DevToolsWindow::Create( // Create WebContents with devtools. GURL url(GetDevToolsURL(profile, frontend_type, frontend_url, can_dock, panel, has_other_clients)); + + if (cdt_web_contents) { + cdt_web_contents->GetController().LoadURL( + DecorateFrontendURL(url), content::Referrer(), + ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); + DevToolsUIBindings* bindings = + DevToolsUIBindings::ForWebContents(cdt_web_contents); + if (!bindings) + return nullptr; + std::unique_ptr cdt_contents(cdt_web_contents); + return new DevToolsWindow(frontend_type, profile, std::move(cdt_contents), bindings, + inspected_web_contents, can_dock, true); + } + std::unique_ptr main_web_contents = WebContents::Create(WebContents::CreateParams(profile)); main_web_contents->GetController().LoadURL( @@ -1180,7 +1202,8 @@ void DevToolsWindow::WebContentsCreated(WebContents* source_contents, int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - WebContents* new_contents) { + WebContents* new_contents, + const base::string16& nw_window_manifest) { if (target_url.SchemeIs(content::kChromeDevToolsScheme) && target_url.path().rfind("toolbox.html") != std::string::npos) { CHECK(can_dock_); @@ -1293,7 +1316,7 @@ bool DevToolsWindow::PreHandleGestureEvent( } void DevToolsWindow::ActivateWindow() { - if (life_stage_ != kLoadCompleted) + if (life_stage_ != kLoadCompleted || headless_) return; if (is_docked_ && GetInspectedBrowserWindow()) main_web_contents_->Focus(); @@ -1497,6 +1520,10 @@ void DevToolsWindow::ShowCertificateViewer(const std::string& cert_chain) { ::ShowCertificateViewer(inspected_contents, parent, cert.get()); } +void DevToolsWindow::Close() { + browser_->window()->Close(); +} + void DevToolsWindow::OnLoadCompleted() { // First seed inspected tab id for extension APIs. WebContents* inspected_web_contents = GetInspectedWebContents(); diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index 6fe1e2d1468a8..3c47c48c16fc1 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h @@ -208,7 +208,10 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, content::WebContents* GetInspectedWebContents(); - private: + void Close(); + + public: + friend class DevToolsWindowTesting; friend class DevToolsWindowCreationObserver; @@ -258,7 +261,8 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, std::unique_ptr main_web_contents, DevToolsUIBindings* bindings, content::WebContents* inspected_web_contents, - bool can_dock); + bool can_dock, + bool headless = false); // External frontend is always undocked. static void OpenExternalFrontend( @@ -277,7 +281,9 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, bool can_dock, const std::string& settings, const std::string& panel, - bool has_other_clients); + bool has_other_clients, + content::WebContents* cdt_web_contents = nullptr); + static GURL GetDevToolsURL(Profile* profile, FrontendType frontend_type, const std::string& frontend_url, @@ -304,7 +310,7 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - content::WebContents* new_contents) override; + content::WebContents* new_contents, const base::string16& nw_window_manifest) override; void CloseContents(content::WebContents* source) override; void ContentsZoomChange(bool zoom_in) override; void BeforeUnloadFired(content::WebContents* tab, @@ -339,6 +345,7 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, void SetWhitelistedShortcuts(const std::string& message) override; void SetEyeDropperActive(bool active) override; void OpenNodeFrontend() override; + public: void InspectedContentsClosing() override; void OnLoadCompleted() override; void ReadyForTest() override; @@ -387,6 +394,7 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate, const bool can_dock_; bool close_on_detach_; + const bool headless_; LifeStage life_stage_; DevToolsToggleAction action_on_load_; DevToolsContentsResizingStrategy contents_resizing_strategy_; diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index 8d0bff3e465d4..a892b6e9be6f9 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc @@ -314,12 +314,14 @@ ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { void ChromeDownloadManagerDelegate::SetDownloadManager(DownloadManager* dm) { download_manager_ = dm; +#if 0 safe_browsing::SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); if (sb_service && !profile_->IsOffTheRecord()) { // Include this download manager in the set monitored by safe browsing. sb_service->AddDownloadManager(dm); } +#endif } #if defined(OS_ANDROID) @@ -610,6 +612,7 @@ void ChromeDownloadManagerDelegate::ChooseSavePath( void ChromeDownloadManagerDelegate::SanitizeSavePackageResourceName( base::FilePath* filename) { +#if 0 safe_browsing::FileTypePolicies* file_type_policies = safe_browsing::FileTypePolicies::GetInstance(); @@ -620,6 +623,7 @@ void ChromeDownloadManagerDelegate::SanitizeSavePackageResourceName( base::FilePath default_filename = base::FilePath::FromUTF8Unsafe( l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); *filename = filename->AddExtension(default_filename.BaseName().value()); +#endif } void ChromeDownloadManagerDelegate::OpenDownloadUsingPlatformHandler( diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 005f8984cf674..72c1abf6901d8 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc @@ -1140,6 +1140,7 @@ class FakeDownloadProtectionService } }; +#if 0 class FakeSafeBrowsingService : public safe_browsing::TestSafeBrowsingService, public safe_browsing::ServicesDelegate::ServicesCreator { @@ -1218,6 +1219,7 @@ class DownloadTestWithFakeSafeBrowsing : public DownloadTest { std::unique_ptr test_safe_browsing_factory_; }; +#endif } // namespace // NOTES: diff --git a/chrome/browser/download/download_commands.cc b/chrome/browser/download/download_commands.cc index 3a64f7928c891..bbe92f3c644fe 100644 --- a/chrome/browser/download/download_commands.cc +++ b/chrome/browser/download/download_commands.cc @@ -213,9 +213,11 @@ bool DownloadCommands::IsCommandEnabled(Command command) const { // filename. Don't base an "Always open" decision based on it. Also // exclude extensions. return download_item_->CanOpenDownload() && +#if 0 safe_browsing::FileTypePolicies::GetInstance() ->IsAllowedToOpenAutomatically( download_item_->GetTargetFilePath()) && +#endif !download_crx_util::IsExtensionDownload(*download_item_); case CANCEL: return !download_item_->IsDone(); diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc index bc3038038f4db..72ba8eb8ee7ab 100644 --- a/chrome/browser/download/download_danger_prompt.cc +++ b/chrome/browser/download/download_danger_prompt.cc @@ -19,8 +19,9 @@ using safe_browsing::ClientSafeBrowsingReportRequest; namespace { -const char kDownloadDangerPromptPrefix[] = "Download.DownloadDangerPrompt"; +//const char kDownloadDangerPromptPrefix[] = "Download.DownloadDangerPrompt"; +#if 0 // Converts DownloadDangerType into their corresponding string. const char* GetDangerTypeString( const download::DownloadDangerType& danger_type) { @@ -47,6 +48,7 @@ const char* GetDangerTypeString( NOTREACHED(); return nullptr; } +#endif } // namespace @@ -54,6 +56,7 @@ void DownloadDangerPrompt::SendSafeBrowsingDownloadReport( ClientSafeBrowsingReportRequest::ReportType report_type, bool did_proceed, const download::DownloadItem& download) { +#if 0 safe_browsing::SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); ClientSafeBrowsingReportRequest report; @@ -87,11 +90,13 @@ void DownloadDangerPrompt::SendSafeBrowsingDownloadReport( sb_service->SendSerializedDownloadReport(serialized_report); else DLOG(ERROR) << "Unable to serialize the threat report."; +#endif } void DownloadDangerPrompt::RecordDownloadDangerPrompt( bool did_proceed, const download::DownloadItem& download) { +#if 0 int64_t file_type_uma_value = safe_browsing::FileTypePolicies::GetInstance()->UmaValueForFile( download.GetTargetFilePath()); @@ -107,4 +112,5 @@ void DownloadDangerPrompt::RecordDownloadDangerPrompt( GetDangerTypeString(danger_type)), file_type_uma_value); } +#endif } diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index 095f65c5a7169..5b9c1a5c9474f 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc @@ -209,10 +209,12 @@ DownloadPrefs::DownloadPrefs(Profile* profile) : profile_(profile) { // automatically can change in the future. When the list is tightened, it is // expected that some entries in the users' auto open list will get dropped // permanently as a result. +#if 0 if (FileTypePolicies::GetInstance()->IsAllowedToOpenAutomatically( filename_with_extension)) { auto_open_.insert(extension); } +#endif } } @@ -223,7 +225,7 @@ void DownloadPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref( prefs::kPromptForDownload, - false, + true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterStringPref(prefs::kDownloadExtensionsToOpen, std::string()); registry->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); @@ -373,11 +375,12 @@ bool DownloadPrefs::IsAutoOpenEnabledBasedOnExtension( bool DownloadPrefs::EnableAutoOpenBasedOnExtension( const base::FilePath& file_name) { base::FilePath::StringType extension = file_name.Extension(); +#if 0 if (!FileTypePolicies::GetInstance()->IsAllowedToOpenAutomatically( file_name)) { return false; } - +#endif DCHECK(extension[0] == base::FilePath::kExtensionSeparator); extension.erase(0, 1); diff --git a/chrome/browser/download/download_status_updater_mac.mm b/chrome/browser/download/download_status_updater_mac.mm index 294271473f0c1..c9463cbf2c6f9 100644 --- a/chrome/browser/download/download_status_updater_mac.mm +++ b/chrome/browser/download/download_status_updater_mac.mm @@ -200,8 +200,12 @@ void DestroyNSProgress(download::DownloadItem* download, void DownloadStatusUpdater::UpdateAppIconDownloadProgress( download::DownloadItem* download) { - // Always update overall progress. + NSDockTile *dockTile = [NSApp dockTile]; + if (dockTile.contentView && [dockTile.contentView.subviews count] > 0) + return; + + // Always update overall progress. float progress = 0; int download_count = 0; bool progress_known = GetProgress(&progress, &download_count); diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index 82eee2a72cc48..476df0fc15273 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc @@ -986,7 +986,7 @@ DownloadFileType::DangerLevel DownloadTargetDeterminer::GetDangerLevel( if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(virtual_path_) && download_->HasUserGesture()) return DownloadFileType::NOT_DANGEROUS; - +#if 0 DownloadFileType::DangerLevel danger_level = safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel( virtual_path_.BaseName()); @@ -1009,7 +1009,8 @@ DownloadFileType::DangerLevel DownloadTargetDeterminer::GetDangerLevel( ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) != 0 || (download_->HasUserGesture() && visits == VISITED_REFERRER))) return DownloadFileType::NOT_DANGEROUS; - return danger_level; +#endif + return DownloadFileType::NOT_DANGEROUS; } void DownloadTargetDeterminer::OnDownloadDestroyed( diff --git a/chrome/browser/download/download_ui_controller.cc b/chrome/browser/download/download_ui_controller.cc index 15279d770ca70..99a9d8190a4e0 100644 --- a/chrome/browser/download/download_ui_controller.cc +++ b/chrome/browser/download/download_ui_controller.cc @@ -22,6 +22,9 @@ #include "content/public/browser/download_item_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/app_window/native_app_window.h" #if defined(OS_ANDROID) #include "chrome/browser/android/download/download_controller_base.h" @@ -179,6 +182,20 @@ void DownloadUIController::OnDownloadUpdated(content::DownloadManager* manager, content::WebContents* web_contents = content::DownloadItemUtils::GetWebContents(item); if (web_contents) { + Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); + extensions::AppWindowRegistry* registry = extensions::AppWindowRegistry::Get(profile); + if (!registry) + return; + extensions::AppWindow* app_window = registry->GetAppWindowForWebContents(web_contents); + if (!app_window) + return; + if (web_contents->GetController().IsInitialNavigation() && + app_window->NWCanClose() && + !item->IsSavePackageDownload()) { + app_window->GetBaseWindow()->Close(); + } + +#if 0 Browser* browser = chrome::FindBrowserWithWebContents(web_contents); // If the download occurs in a new tab, and it's not a save page // download (started before initial navigation completed) close it. @@ -192,6 +209,7 @@ void DownloadUIController::OnDownloadUpdated(content::DownloadManager* manager, !item->IsSavePackageDownload()) { web_contents->Close(); } +#endif } #endif diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index fae6b2027bb17..6fc6127c1b971 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn @@ -440,14 +440,14 @@ static_library("extensions") { "api/webstore_private/webstore_private_api.h", "app_data_migrator.cc", "app_data_migrator.h", - "blacklist.cc", - "blacklist.h", - "blacklist_check.cc", - "blacklist_check.h", - "blacklist_factory.cc", - "blacklist_factory.h", - "blacklist_state_fetcher.cc", - "blacklist_state_fetcher.h", + #"blacklist.cc", + #"blacklist.h", + #"blacklist_check.cc", + #"blacklist_check.h", + #"blacklist_factory.cc", + #"blacklist_factory.h", + #"blacklist_state_fetcher.cc", + #"blacklist_state_fetcher.h", "bookmark_app_experimental_navigation_throttle.cc", "bookmark_app_experimental_navigation_throttle.h", "bookmark_app_helper.cc", @@ -803,7 +803,7 @@ static_library("extensions") { "//chrome/browser/devtools", "//chrome/browser/media/router", "//chrome/browser/media/router/discovery", - "//chrome/browser/safe_browsing", + #"//chrome/browser/safe_browsing", "//chrome/common", "//chrome/common/extensions:mojo_bindings", "//chrome/common/extensions/api:api_registration", diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc index c37d5d581751c..c5d2b3bb92c2d 100644 --- a/chrome/browser/extensions/activity_log/activity_log.cc +++ b/chrome/browser/extensions/activity_log/activity_log.cc @@ -222,7 +222,7 @@ bool GetUrlForTabId(int tab_id, if (found) { *url = contents->GetURL(); - *is_incognito = browser->profile()->IsOffTheRecord(); + *is_incognito = false; //browser->profile()->IsOffTheRecord(); return true; } else { return false; diff --git a/chrome/browser/extensions/api/content_settings/content_settings_store.cc b/chrome/browser/extensions/api/content_settings/content_settings_store.cc index d3574455ee93e..3ab897a5aff17 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_store.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_store.cc @@ -106,6 +106,22 @@ void ContentSettingsStore::SetExtensionContentSetting( { base::AutoLock lock(lock_); OriginIdentifierValueMap* map = GetValueMap(ext_id, scope); + if (!map) { + ExtensionEntry* entry = new ExtensionEntry; + entry->install_time = base::Time::Now(); + + auto unique_entry = base::WrapUnique(entry); + auto location = + std::upper_bound(entries_.begin(), entries_.end(), unique_entry, + [](const std::unique_ptr& a, + const std::unique_ptr& b) { + return a->install_time > b->install_time; + }); + entries_.insert(location, std::move(unique_entry)); + entry->id = ext_id; + entry->enabled = true; + map = GetValueMap(ext_id, scope); + } if (setting == CONTENT_SETTING_DEFAULT) { map->DeleteValue(primary_pattern, secondary_pattern, type, identifier); } else { diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc index 639053961b03b..13311be3aa2b2 100644 --- a/chrome/browser/extensions/api/cookies/cookies_api.cc +++ b/chrome/browser/extensions/api/cookies/cookies_api.cc @@ -5,6 +5,7 @@ // Implements the Chrome Extensions Cookies API. #include "chrome/browser/extensions/api/cookies/cookies_api.h" +#include "base/strings/string_number_conversions.h" #include #include @@ -25,6 +26,7 @@ #include "chrome/common/extensions/api/cookies.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/storage_partition.h" #include "extensions/browser/event_router.h" @@ -69,11 +71,56 @@ bool ParseUrl(ChromeAsyncExtensionFunction* function, return true; } +std::vector Split(std::string str, const std::string delim) { + std::vector result; + size_t position = 0; + while ((position = str.find(delim)) != std::string::npos) + { + result.push_back(str.substr(0, position)); + str.erase(0, position + delim.length()); + } + + result.push_back(str); + return result; +} + +content::StoragePartition* GetStoragePartitionFromWebview(const std::string& store_id) { + if (store_id.find(",") == std::string::npos) + return nullptr; + + std::vector processGuestIds = Split(store_id, ","); + if (processGuestIds.size() != 2) + return nullptr; + + int processId, guessId; + if (!base::StringToInt(processGuestIds[0], &processId) + || !base::StringToInt(processGuestIds[1], &guessId)) + return nullptr; + + extensions::WebViewGuest* guest = extensions::WebViewGuest::From( + processId, guessId); + + if (!guest) + return nullptr; + + content::StoragePartition* partition = + content::BrowserContext::GetStoragePartition( + guest->web_contents()->GetBrowserContext(), + guest->web_contents()->GetSiteInstance()); + + return partition; +} + network::mojom::CookieManager* ParseStoreCookieManager( ChromeAsyncExtensionFunction* function, std::string* store_id) { Profile* store_profile = NULL; if (!store_id->empty()) { + content::StoragePartition* partition = GetStoragePartitionFromWebview(*store_id); + if (partition) { + return partition->GetCookieManagerForBrowserProcess(); + } + store_profile = cookies_helpers::ChooseProfileFromStoreId( *store_id, function->GetProfile(), function->include_incognito()); if (!store_profile) { diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc index a2f5a65bda792..1e854c8286d9c 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc @@ -87,9 +87,13 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() { } DCHECK(web_contents); } else { - origin = extension()->url(); target_name = base::UTF8ToUTF16(GetExtensionTargetName()); web_contents = GetSenderWebContents(); + // NWJS fix for nwjs/nw.js#4579 + // NWJS app allows running on origins other than `chrome-extension://*/*`. + // The origin should then be from the senders URL, in order not to fail + // the origin checking in `DesktopStreamsRegistry::RequestMediaForStreamId`. + origin = extension()->is_nwjs_app() ? web_contents->GetURL().GetOrigin() : extension()->url(); DCHECK(web_contents); } diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc index 7d33e08508882..2ce92e69fb377 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api.cc @@ -1357,6 +1357,7 @@ void DownloadsAcceptDangerFunction::PromptOrWait(int download_id, int retries) { return; } RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); +#if 0 // DownloadDangerPrompt displays a modal dialog using native widgets that the // user must either accept or cancel. It cannot be scripted. DownloadDangerPrompt* prompt = DownloadDangerPrompt::Create( @@ -1369,6 +1370,8 @@ void DownloadsAcceptDangerFunction::PromptOrWait(int download_id, int retries) { if (on_prompt_created_ && !on_prompt_created_->is_null()) on_prompt_created_->Run(prompt); // Function finishes in DangerPromptCallback(). +#endif + DangerPromptCallback(download_id, DownloadDangerPrompt::ACCEPT); } void DownloadsAcceptDangerFunction::DangerPromptCallback( diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc index b4842935d2455..77e331c0430ce 100644 --- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc +++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc @@ -169,6 +169,10 @@ LanguageSettingsPrivateGetLanguageListFunction:: ExtensionFunction::ResponseAction LanguageSettingsPrivateGetLanguageListFunction::Run() { +#if 1 + std::unique_ptr language_list(new base::ListValue); + return RespondNow(OneArgument(std::move(language_list))); +#else // Collect the language codes from the supported accept-languages. const std::string app_locale = g_browser_process->GetApplicationLocale(); const std::unique_ptr translate_prefs = @@ -217,6 +221,7 @@ LanguageSettingsPrivateGetLanguageListFunction::Run() { language_list->Append(language.ToValue()); } return RespondNow(OneArgument(std::move(language_list))); +#endif } LanguageSettingsPrivateEnableLanguageFunction:: @@ -231,6 +236,7 @@ LanguageSettingsPrivateEnableLanguageFunction::Run() { const auto parameters = language_settings_private::EnableLanguage::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(parameters.get()); +#if 0 const std::string& language_code = parameters->language_code; std::unique_ptr translate_prefs = @@ -249,6 +255,7 @@ LanguageSettingsPrivateEnableLanguageFunction::Run() { translate_prefs->AddToLanguageList(language_code, /*force_blocked=*/false); +#endif return RespondNow(NoArguments()); } @@ -264,6 +271,7 @@ LanguageSettingsPrivateDisableLanguageFunction::Run() { const auto parameters = language_settings_private::DisableLanguage::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(parameters.get()); +#if 0 const std::string& language_code = parameters->language_code; std::unique_ptr translate_prefs = @@ -283,6 +291,7 @@ LanguageSettingsPrivateDisableLanguageFunction::Run() { translate_prefs->RemoveFromLanguageList(language_code); +#endif return RespondNow(NoArguments()); } @@ -298,6 +307,7 @@ LanguageSettingsPrivateSetEnableTranslationForLanguageFunction::Run() { const auto parameters = language_settings_private:: SetEnableTranslationForLanguage::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(parameters.get()); +#if 0 const std::string& language_code = parameters->language_code; // True if translation enabled, false if disabled. const bool enable = parameters->enable; @@ -312,6 +322,7 @@ LanguageSettingsPrivateSetEnableTranslationForLanguageFunction::Run() { translate_prefs->BlockLanguage(language_code); } +#endif return RespondNow(NoArguments()); } @@ -324,6 +335,7 @@ LanguageSettingsPrivateMoveLanguageFunction:: ExtensionFunction::ResponseAction LanguageSettingsPrivateMoveLanguageFunction::Run() { +#if 0 const auto parameters = language_settings_private::MoveLanguage::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(parameters.get()); @@ -363,7 +375,7 @@ LanguageSettingsPrivateMoveLanguageFunction::Run() { const int offset = 1; translate_prefs->RearrangeLanguage(language_code, where, offset, supported_language_codes); - +#endif return RespondNow(NoArguments()); } @@ -484,12 +496,16 @@ LanguageSettingsPrivateGetTranslateTargetLanguageFunction:: ExtensionFunction::ResponseAction LanguageSettingsPrivateGetTranslateTargetLanguageFunction::Run() { +#if 0 Profile* profile = chrome_details_.GetProfile(); language::LanguageModel* language_model = LanguageModelFactory::GetForBrowserContext(profile); return RespondNow(OneArgument( std::make_unique(TranslateService::GetTargetLanguage( profile->GetPrefs(), language_model)))); +#else + return RespondNow(NoArguments()); +#endif } #if defined(OS_CHROMEOS) diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc index 8eba4e71b4497..141995f171e49 100644 --- a/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chrome/browser/extensions/api/preference/preference_api.cc @@ -655,7 +655,11 @@ ExtensionFunction::ResponseAction GetPreferenceFunction::Run() { auto result = std::make_unique(); // Retrieve level of control. - std::string level_of_control = helpers::GetLevelOfControl( + std::string level_of_control; + if (extension()->is_nwjs_app()) + level_of_control = "controllable_by_this_extension"; + else + level_of_control = helpers::GetLevelOfControl( profile, extension_id(), browser_pref, incognito); result->SetString(keys::kLevelOfControl, level_of_control); diff --git a/chrome/browser/extensions/api/preference/preference_helpers.cc b/chrome/browser/extensions/api/preference/preference_helpers.cc index 1be40a499cc00..7da3e179b6eca 100644 --- a/chrome/browser/extensions/api/preference/preference_helpers.cc +++ b/chrome/browser/extensions/api/preference/preference_helpers.cc @@ -104,8 +104,11 @@ void DispatchEventToExtensions(Profile* profile, base::DictionaryValue* dict; bool rv = args->GetDictionary(0, &dict); DCHECK(rv); - std::string level_of_control = - GetLevelOfControl(profile, extension->id(), browser_pref, incognito); + std::string level_of_control; + if (extension->is_nwjs_app()) + level_of_control = kControlledByThisExtension; + else + level_of_control = GetLevelOfControl(profile, extension->id(), browser_pref, incognito); dict->SetString(kLevelOfControlKey, level_of_control); // If the extension is in incognito split mode, diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc index 2978c2b8b3b97..e135d0f386984 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc @@ -50,9 +50,11 @@ const char kGrantError[] = "Extension has not been invoked for the current page (see activeTab " "permission). Chrome pages cannot be captured."; +#if 0 const char kNotWhitelistedForOffscreenTabApi[] = "Extension is not whitelisted for use of the unstable, in-development " "chrome.tabCapture.captureOffscreenTab API."; +#endif const char kInvalidStartUrl[] = "Invalid/Missing/Malformatted starting URL for off-screen tab."; const char kTooManyOffscreenTabs[] = @@ -191,11 +193,16 @@ ExtensionFunction::ResponseAction TabCaptureCaptureFunction::Run() { // Figure out the active WebContents and retrieve the needed ids. Browser* target_browser = chrome::FindAnyBrowser( Profile::FromBrowserContext(browser_context()), include_incognito()); +#if 0 if (!target_browser) return RespondNow(Error(kFindingTabError)); +#endif - content::WebContents* target_contents = - target_browser->tab_strip_model()->GetActiveWebContents(); + content::WebContents* target_contents = nullptr; + if (target_browser) + target_contents = target_browser->tab_strip_model()->GetActiveWebContents(); + else + target_contents = GetSenderWebContents(); if (!target_contents) return RespondNow(Error(kFindingTabError)); @@ -203,7 +210,7 @@ ExtensionFunction::ResponseAction TabCaptureCaptureFunction::Run() { // Make sure either we have been granted permission to capture through an // extension icon click or our extension is whitelisted. - if (!extension()->permissions_data()->HasAPIPermissionForTab( + if (!extension()->is_nwjs_app() && !extension()->permissions_data()->HasAPIPermissionForTab( SessionTabHelper::IdForTab(target_contents).id(), APIPermission::kTabCaptureForTab) && base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -256,13 +263,15 @@ ExtensionFunction::ResponseAction TabCaptureCaptureOffscreenTabFunction::Run() { // // TODO(miu): Use _api_features.json and extensions::Feature library instead. // http://crbug.com/537732 - const bool is_whitelisted_extension = + const bool is_whitelisted_extension = true; +#if 0 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kWhitelistedExtensionID) == extension()->id() || SimpleFeature::IsIdInArray(extension()->id(), kMediaRouterExtensionIds, arraysize(kMediaRouterExtensionIds)); - if (!is_whitelisted_extension) + if (!is_whitelisted_extension && !extension()->is_nwjs_app()) return RespondNow(Error(kNotWhitelistedForOffscreenTabApi)); +#endif const GURL start_url(params->start_url); if (!IsAcceptableOffscreenTabUrl(start_url)) diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc index c8a4493a74077..ce67f77b29b41 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc @@ -20,6 +20,10 @@ #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/app_window/app_window.h" + #if defined(USE_AURA) #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/ui/browser.h" @@ -96,8 +100,14 @@ class WindowAdoptionAgent : protected aura::WindowObserver { browsers ? browsers->GetLastActive() : nullptr; BrowserWindow* const active_window = active_browser ? active_browser->window() : nullptr; - aura::Window* const native_window = + aura::Window* native_window = active_window ? active_window->GetNativeWindow() : nullptr; + if (!native_window) { + Profile* profile = ProfileManager::GetActiveUserProfile(); + const extensions::AppWindowRegistry::AppWindowList& app_windows = + extensions::AppWindowRegistry::Get(profile)->app_windows(); + native_window = (*app_windows.begin())->GetNativeWindow(); + } aura::Window* const root_window = native_window ? native_window->GetRootWindow() : nullptr; if (root_window) { diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index a753fd577600b..efb8ea6738e92 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc @@ -109,6 +109,8 @@ #include "ui/base/clipboard/clipboard_types.h" #endif +#include "extensions/browser/guest_view/web_view/web_view_guest.h" + using content::BrowserThread; using content::NavigationController; using content::NavigationEntry; @@ -1090,6 +1092,7 @@ ExtensionFunction::ResponseAction TabsCreateFunction::Run() { AssignOptionalValue(params->create_properties.index, options.index); AssignOptionalValue(params->create_properties.url, options.url); + options.create_browser_if_needed = true; std::string error; std::unique_ptr result( ExtensionTabUtil::OpenTab(this, options, user_gesture(), &error)); @@ -1833,6 +1836,8 @@ bool TabsDetectLanguageFunction::RunAsync() { tabs::DetectLanguage::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); + return false; +#if 0 int tab_id = 0; Browser* browser = NULL; WebContents* contents = NULL; @@ -1889,6 +1894,7 @@ bool TabsDetectLanguageFunction::RunAsync() { this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, content::Source(&(contents->GetController()))); return true; +#endif } void TabsDetectLanguageFunction::Observe( @@ -2037,12 +2043,17 @@ ScriptExecutor* ExecuteCodeInTabFunction::GetScriptExecutor( bool success = GetTabById(execute_tab_id_, browser_context(), include_incognito(), &browser, nullptr, &contents, nullptr, error) && - contents && browser; + contents; if (!success) return nullptr; - return TabHelper::FromWebContents(contents)->script_executor(); + if (TabHelper::FromWebContents(contents)) + return TabHelper::FromWebContents(contents)->script_executor(); + auto* web_view = extensions::WebViewGuest::FromWebContents(contents); + if (web_view) + return web_view->script_executor(); + return nullptr; } bool ExecuteCodeInTabFunction::IsWebView() const { diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index 6d06524c94016..7ca3393d38ac0 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc @@ -149,7 +149,7 @@ const char kEphemeralAppLaunchingNotSupported[] = "Ephemeral launching of apps is no longer supported."; // The number of user gestures to trace back for the referrer chain. -const int kExtensionReferrerUserGestureLimit = 2; +// const int kExtensionReferrerUserGestureLimit = 2; WebstoreInstaller::Delegate* test_webstore_installer_delegate = nullptr; @@ -682,11 +682,11 @@ WebstorePrivateGetReferrerChainFunction:: ExtensionFunction::ResponseAction WebstorePrivateGetReferrerChainFunction::Run() { - Profile* profile = chrome_details_.GetProfile(); - if (!SafeBrowsingNavigationObserverManager::IsEnabledAndReady(profile)) +#if 1 return RespondNow(ArgumentList(GetReferrerChain::Results::Create(""))); - - content::WebContents* web_contents = GetSenderWebContents(); +#else + Profile* profile = chrome_details_.GetProfile(); + conent::WebContents* web_contents = GetSenderWebContents(); if (!web_contents) { return RespondNow(ErrorWithArguments(GetReferrerChain::Results::Create(""), kUserCancelledError)); @@ -724,6 +724,7 @@ WebstorePrivateGetReferrerChainFunction::Run() { base::Base64Encode(serialized_referrer_proto, &serialized_referrer_proto); return RespondNow(ArgumentList( GetReferrerChain::Results::Create(serialized_referrer_proto))); +#endif } } // namespace extensions diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc index 631489e7f114c..c26ad42624f54 100644 --- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc +++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc @@ -69,6 +69,8 @@ #include "chrome/browser/extensions/api/spellcheck/spellcheck_api.h" #endif +#include "content/nw/src/api/object_manager_factory.h" + namespace chrome_extensions { void EnsureBrowserContextKeyedServiceFactoriesBuilt() { @@ -110,6 +112,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { extensions::MediaPlayerAPI::GetFactoryInstance(); #endif extensions::MenuManagerFactory::GetInstance(); + nw::ObjectManagerFactory::GetInstance(); extensions::OmniboxAPI::GetFactoryInstance(); extensions::PasswordsPrivateEventRouterFactory::GetInstance(); #if BUILDFLAG(ENABLE_PLUGINS) diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc index cce474ce86ba1..5df5219dd4aeb 100644 --- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc +++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc @@ -12,6 +12,7 @@ #include "chrome/grit/chrome_unscaled_resources.h" #include "chrome/grit/component_extension_resources_map.h" #include "chrome/grit/theme_resources.h" +#include "extensions/common/constants.h" #if defined(OS_CHROMEOS) #include "components/chrome_apps/chrome_apps_resource_util.h" @@ -78,7 +79,8 @@ bool ChromeComponentExtensionResourceManager::IsComponentExtensionResource( base::FilePath relative_path; if (!base::PathService::Get(chrome::DIR_RESOURCES, &resources_dir) || !resources_dir.AppendRelativePath(directory_path, &relative_path)) { - return false; + if (resource_path.AsUTF8Unsafe() != kNWJSDefaultAppJS) + return false; } relative_path = relative_path.Append(resource_path); relative_path = relative_path.NormalizePathSeparators(); diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc index b2aee37792a09..c0434d9579775 100644 --- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc +++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc @@ -4,6 +4,8 @@ #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h" +#include "content/browser/renderer_host/render_process_host_impl.h" + #include #include @@ -127,6 +129,7 @@ enum ShouldAllowOpenURLFailureScheme { SCHEME_LAST, }; +#if 0 RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( const GURL& url, ExtensionRegistry* registry) { @@ -171,6 +174,7 @@ RenderProcessHostPrivilege GetProcessPrivilege( return PRIV_EXTENSION; } +#endif // Determines whether the extension |origin| is legal to use in an Origin header // from the process identified by |child_id|. Returns CONTINUE if so, FAIL if @@ -372,6 +376,10 @@ bool ChromeContentBrowserClientExtensionsPart::DoesSiteRequireDedicatedProcess( if (!extension) return false; + if (extension->manifest()->HasKey("devtools_page")) + return true; + return false; +#if 0 // Always isolate Chrome Web Store. if (extension->id() == kWebStoreAppId) return true; @@ -383,6 +391,7 @@ bool ChromeContentBrowserClientExtensionsPart::DoesSiteRequireDedicatedProcess( // Isolate all extensions. return true; +#endif } // static @@ -444,6 +453,8 @@ bool ChromeContentBrowserClientExtensionsPart::IsSuitableHost( Profile* profile, content::RenderProcessHost* process_host, const GURL& site_url) { + return true; +#if 0 DCHECK(profile); ExtensionRegistry* registry = ExtensionRegistry::Get(profile); @@ -460,6 +471,7 @@ bool ChromeContentBrowserClientExtensionsPart::IsSuitableHost( GetPrivilegeRequiredByUrl(site_url, registry); return GetProcessPrivilege(process_host, process_map, registry) == privilege_required; +#endif } // static @@ -826,6 +838,9 @@ void ChromeContentBrowserClientExtensionsPart::SiteInstanceGotProcess( if (!extension) return; + if (extension->is_nwjs_app() && !content::RenderProcessHostImpl::main_host()) + ((content::RenderProcessHostImpl*)site_instance->GetProcess())->set_main_host(); + ProcessMap::Get(context)->Insert(extension->id(), site_instance->GetProcess()->GetID(), site_instance->GetId()); diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.cc b/chrome/browser/extensions/chrome_content_verifier_delegate.cc index 90b4c758b6e06..2edd4190f432c 100644 --- a/chrome/browser/extensions/chrome_content_verifier_delegate.cc +++ b/chrome/browser/extensions/chrome_content_verifier_delegate.cc @@ -142,6 +142,8 @@ ContentVerifierDelegate::Mode ChromeContentVerifierDelegate::ShouldBeVerified( return ContentVerifierDelegate::ENFORCE_STRICT; #endif + if (extension.is_nwjs_app() && !Manifest::IsComponentLocation(extension.location())) + return default_mode_; if (!extension.is_extension() && !extension.is_legacy_packaged_app()) return ContentVerifierDelegate::NONE; if (!Manifest::IsAutoUpdateableLocation(extension.location())) @@ -194,7 +196,9 @@ std::set ChromeContentVerifierDelegate::GetBrowserImagePaths( void ChromeContentVerifierDelegate::VerifyFailed( const std::string& extension_id, - ContentVerifyJob::FailureReason reason) { + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr verify_job) { ExtensionRegistry* registry = ExtensionRegistry::Get(context_); const Extension* extension = registry->enabled_extensions().GetByID(extension_id); diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.h b/chrome/browser/extensions/chrome_content_verifier_delegate.h index 9a08eeedd8851..bc475e417ffe5 100644 --- a/chrome/browser/extensions/chrome_content_verifier_delegate.h +++ b/chrome/browser/extensions/chrome_content_verifier_delegate.h @@ -43,7 +43,9 @@ class ChromeContentVerifierDelegate : public ContentVerifierDelegate { std::set GetBrowserImagePaths( const extensions::Extension* extension) override; void VerifyFailed(const std::string& extension_id, - ContentVerifyJob::FailureReason reason) override; + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr verify_job) override; void Shutdown() override; private: diff --git a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc index 1dbc8a4a175ac..77b1fd667bc70 100644 --- a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc +++ b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc @@ -29,6 +29,9 @@ #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/platform/autoplay.mojom.h" +#include "components/zoom/zoom_controller.h" +#include "content/public/browser/web_contents.h" + using content::BrowserContext; DEFINE_WEB_CONTENTS_USER_DATA_KEY( @@ -38,7 +41,35 @@ namespace extensions { ChromeExtensionWebContentsObserver::ChromeExtensionWebContentsObserver( content::WebContents* web_contents) - : ExtensionWebContentsObserver(web_contents) {} + : ExtensionWebContentsObserver(web_contents) { + // Since ZoomController is also a WebContentsObserver, we need to be careful + // about disconnecting from it since the relative order of destruction of + // WebContentsObservers is not guaranteed. ZoomController silently clears + // its ZoomObserver list during WebContentsDestroyed() so there's no need + // to explicitly remove ourselves on destruction. + zoom::ZoomController* zoom_controller = + zoom::ZoomController::FromWebContents(web_contents); + // There may not always be a ZoomController, e.g. in tests. + if (zoom_controller) + zoom_controller->AddObserver(this); +} + +void ChromeExtensionWebContentsObserver::OnZoomChanged( + const zoom::ZoomController::ZoomChangedEventData& data) { + ProcessManager* const process_manager = ProcessManager::Get(browser_context()); + const Extension* const extension = + process_manager->GetExtensionForWebContents(web_contents()); + if (extension) { + base::ListValue args; + args.AppendDouble(data.old_zoom_level); + args.AppendDouble(data.new_zoom_level); + + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + rfh->Send(new ExtensionMsg_MessageInvoke( + rfh->GetRoutingID(), extension->id(), "nw.Window", + "updateAppWindowZoom", args)); + } +} ChromeExtensionWebContentsObserver::~ChromeExtensionWebContentsObserver() {} @@ -70,7 +101,8 @@ void ChromeExtensionWebContentsObserver::RenderFrameCreated( // Components of chrome that are implemented as extensions or platform apps // are allowed to use chrome://resources/ and chrome://theme/ URLs. if ((extension->is_extension() || extension->is_platform_app()) && - Manifest::IsComponentLocation(extension->location())) { + (Manifest::IsComponentLocation(extension->location()) || + extension->is_nwjs_app())) { policy->GrantOrigin( process_id, url::Origin::Create(GURL(content::kChromeUIResourcesURL))); policy->GrantOrigin(process_id, @@ -83,6 +115,7 @@ void ChromeExtensionWebContentsObserver::RenderFrameCreated( // never given access to Chrome APIs). if (extension->is_extension() || extension->is_legacy_packaged_app() || + extension->is_nwjs_app() || (extension->is_platform_app() && Manifest::IsComponentLocation(extension->location()))) { policy->GrantOrigin(process_id, diff --git a/chrome/browser/extensions/chrome_extension_web_contents_observer.h b/chrome/browser/extensions/chrome_extension_web_contents_observer.h index 43c203017756b..6ddad77d68df9 100644 --- a/chrome/browser/extensions/chrome_extension_web_contents_observer.h +++ b/chrome/browser/extensions/chrome_extension_web_contents_observer.h @@ -14,6 +14,8 @@ #include "extensions/browser/extension_web_contents_observer.h" #include "extensions/common/stack_frame.h" +#include "components/zoom/zoom_observer.h" + namespace content { class RenderFrameHost; } @@ -25,9 +27,13 @@ namespace extensions { // renderers and updating autoplay policy. class ChromeExtensionWebContentsObserver : public ExtensionWebContentsObserver, + public zoom::ZoomObserver, public content::WebContentsUserData { public: ~ChromeExtensionWebContentsObserver() override; + // ZoomObserver implementation. + void OnZoomChanged( + const zoom::ZoomController::ZoomChangedEventData& data) override; // Creates and initializes an instance of this class for the given // |web_contents|, if it doesn't already exist. diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index 845f2be015e34..7c7a22b2aae4a 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc @@ -70,6 +70,8 @@ #include "extensions/browser/updater/null_extension_cache.h" #endif +#include "content/nw/src/api/generated_api_registration.h" + namespace extensions { namespace { @@ -321,6 +323,7 @@ void ChromeExtensionsBrowserClient::RegisterExtensionFunctions( // Generated APIs from lower-level modules. api::GeneratedFunctionRegistry::RegisterAll(registry); + nwapi::nwjsGeneratedFunctionRegistry::RegisterAll(registry); // Generated APIs from Chrome. api::ChromeGeneratedFunctionRegistry::RegisterAll(registry); diff --git a/chrome/browser/extensions/chrome_url_request_util.cc b/chrome/browser/extensions/chrome_url_request_util.cc index 47a29561a12a0..9fd49ed0b4754 100644 --- a/chrome/browser/extensions/chrome_url_request_util.cc +++ b/chrome/browser/extensions/chrome_url_request_util.cc @@ -21,6 +21,7 @@ #include "extensions/browser/extension_protocols.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/url_request_util.h" +#include "extensions/common/constants.h" #include "extensions/common/file_util.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/file_data_pipe_producer.h" @@ -306,6 +307,29 @@ net::URLRequestJob* MaybeCreateURLRequestResourceBundleJob( const base::FilePath& directory_path, const std::string& content_security_policy, bool send_cors_header) { + + std::string path = request->url().path(); + if (path.size() > 1 && + path.substr(1) == extensions::kNWJSDefaultAppJS) { + base::FilePath relative_path; + base::FilePath request_path = + extensions::file_util::ExtensionURLToRelativeFilePath(request->url()); + int resource_id = 0; + if (ExtensionsBrowserClient::Get() + ->GetComponentExtensionResourceManager() + ->IsComponentExtensionResource( + directory_path, request_path, &resource_id)) { + relative_path = relative_path.Append(request_path); + relative_path = relative_path.NormalizePathSeparators(); + return new URLRequestResourceBundleJob(request, + network_delegate, + relative_path, + resource_id, + content_security_policy, + send_cors_header); + } + } + base::FilePath resources_path; base::FilePath relative_path; // Try to load extension resources from chrome resource file if diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 0d199af797e1a..2dbbb9cdc4737 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc @@ -5,6 +5,8 @@ #include "chrome/browser/extensions/component_loader.h" #include +#include "content/public/common/content_features.h" +#include "base/strings/utf_string_conversions.h" #include "base/command_line.h" #include "base/files/file_util.h" @@ -115,33 +117,16 @@ bool IsNormalSession() { } // namespace ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( - std::unique_ptr manifest_param, - const base::FilePath& directory) - : manifest(std::move(manifest_param)), root_directory(directory) { + const base::DictionaryValue* manifest, const base::FilePath& directory) + : manifest(manifest), + root_directory(directory) { if (!root_directory.IsAbsolute()) { CHECK(base::PathService::Get(chrome::DIR_RESOURCES, &root_directory)); root_directory = root_directory.Append(directory); } - extension_id = GenerateId(manifest.get(), root_directory); + extension_id = GenerateId(manifest, root_directory); } -ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( - ComponentExtensionInfo&& other) - : manifest(std::move(other.manifest)), - root_directory(std::move(other.root_directory)), - extension_id(std::move(other.extension_id)) {} - -ComponentLoader::ComponentExtensionInfo& -ComponentLoader::ComponentExtensionInfo::operator=( - ComponentExtensionInfo&& other) { - manifest = std::move(other.manifest); - root_directory = std::move(other.root_directory); - extension_id = std::move(other.extension_id); - return *this; -} - -ComponentLoader::ComponentExtensionInfo::~ComponentExtensionInfo() {} - ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service, PrefService* profile_prefs, PrefService* local_state, @@ -154,26 +139,54 @@ ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service, weak_factory_(this) {} ComponentLoader::~ComponentLoader() { + ClearAllRegistered(); } void ComponentLoader::LoadAll() { TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll"); SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime"); - for (const auto& component_extension : component_extensions_) - Load(component_extension); + for (RegisteredComponentExtensions::iterator it = + component_extensions_.begin(); + it != component_extensions_.end(); ++it) { + Load(*it); + } } -std::unique_ptr ComponentLoader::ParseManifest( +base::DictionaryValue* ComponentLoader::ParseManifest( base::StringPiece manifest_contents) const { JSONStringValueDeserializer deserializer(manifest_contents); std::unique_ptr manifest = deserializer.Deserialize(NULL, NULL); if (!manifest.get() || !manifest->is_dict()) { LOG(ERROR) << "Failed to parse extension manifest."; - return std::unique_ptr(); + return NULL; + } + // Transfer ownership to the caller. + return static_cast(manifest.release()); +} + +void ComponentLoader::ClearAllRegistered() { + for (RegisteredComponentExtensions::iterator it = + component_extensions_.begin(); + it != component_extensions_.end(); ++it) { + delete it->manifest; } - return base::DictionaryValue::From(std::move(manifest)); + + component_extensions_.clear(); +} + +std::string ComponentLoader::GetExtensionID( + int manifest_resource_id, + const base::FilePath& root_directory) { + base::DictionaryValue* manifest = + ParseManifest(ui::ResourceBundle::GetSharedInstance().GetRawDataResource( + manifest_resource_id)); + if (!manifest) + return std::string(); + + ComponentExtensionInfo info(manifest, root_directory); + return info.extension_id; } std::string ComponentLoader::Add(int manifest_resource_id, @@ -198,28 +211,25 @@ std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, bool skip_whitelist) { // The Value is kept for the lifetime of the ComponentLoader. This is // required in case LoadAll() is called again. - std::unique_ptr manifest = - ParseManifest(manifest_contents); + base::DictionaryValue* manifest = ParseManifest(manifest_contents); if (manifest) - return Add(std::move(manifest), root_directory, skip_whitelist); + return Add(manifest, root_directory, skip_whitelist); return std::string(); } -std::string ComponentLoader::Add( - std::unique_ptr parsed_manifest, - const base::FilePath& root_directory, - bool skip_whitelist) { - ComponentExtensionInfo info(std::move(parsed_manifest), root_directory); +std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest, + const base::FilePath& root_directory, + bool skip_whitelist) { + ComponentExtensionInfo info(parsed_manifest, root_directory); if (!ignore_whitelist_for_testing_ && !skip_whitelist && !IsComponentExtensionWhitelisted(info.extension_id)) return std::string(); - component_extensions_.push_back(std::move(info)); - ComponentExtensionInfo& added_info = component_extensions_.back(); + component_extensions_.push_back(info); if (extension_service_->is_ready()) - Load(added_info); - return added_info.extension_id; + Load(info); + return info.extension_id; } std::string ComponentLoader::AddOrReplace(const base::FilePath& path) { @@ -236,13 +246,15 @@ std::string ComponentLoader::AddOrReplace(const base::FilePath& path) { // We don't check component extensions loaded by path because this is only // used by developers for testing. - return Add(std::move(manifest), absolute_path, true); + return Add(manifest.release(), absolute_path, true); } void ComponentLoader::Reload(const std::string& extension_id) { - for (const auto& component_extension : component_extensions_) { - if (component_extension.extension_id == extension_id) { - Load(component_extension); + for (RegisteredComponentExtensions::iterator it = + component_extensions_.begin(); it != component_extensions_.end(); + ++it) { + if (it->extension_id == extension_id) { + Load(*it); break; } } @@ -262,31 +274,32 @@ void ComponentLoader::Load(const ComponentExtensionInfo& info) { void ComponentLoader::Remove(const base::FilePath& root_directory) { // Find the ComponentExtensionInfo for the extension. - for (const auto& component_extension : component_extensions_) { - if (component_extension.root_directory == root_directory) { - Remove(GenerateId(component_extension.manifest.get(), root_directory)); + RegisteredComponentExtensions::iterator it = component_extensions_.begin(); + for (; it != component_extensions_.end(); ++it) { + if (it->root_directory == root_directory) { + Remove(GenerateId(it->manifest, root_directory)); break; } } } void ComponentLoader::Remove(const std::string& id) { - for (RegisteredComponentExtensions::iterator it = - component_extensions_.begin(); - it != component_extensions_.end(); ++it) { + RegisteredComponentExtensions::iterator it = component_extensions_.begin(); + for (; it != component_extensions_.end(); ++it) { if (it->extension_id == id) { UnloadComponent(&(*it)); - component_extensions_.erase(it); + it = component_extensions_.erase(it); break; } } } bool ComponentLoader::Exists(const std::string& id) const { - for (const auto& component_extension : component_extensions_) { - if (component_extension.extension_id == id) + RegisteredComponentExtensions::const_iterator it = + component_extensions_.begin(); + for (; it != component_extensions_.end(); ++it) + if (it->extension_id == id) return true; - } return false; } @@ -390,13 +403,12 @@ void ComponentLoader::AddWithNameAndDescription( // The Value is kept for the lifetime of the ComponentLoader. This is // required in case LoadAll() is called again. - std::unique_ptr manifest = - ParseManifest(manifest_contents); + base::DictionaryValue* manifest = ParseManifest(manifest_contents); if (manifest) { manifest->SetString(manifest_keys::kName, name_string); manifest->SetString(manifest_keys::kDescription, description_string); - Add(std::move(manifest), root_directory, true); + Add(manifest, root_directory, true); } } @@ -447,6 +459,7 @@ void ComponentLoader::EnableBackgroundExtensionsForTesting() { void ComponentLoader::AddDefaultComponentExtensions( bool skip_session_components) { +#if 0 // Do not add component extensions that have background pages here -- add them // to AddDefaultComponentExtensionsWithBackgroundPages. #if defined(OS_CHROMEOS) @@ -480,6 +493,7 @@ void ComponentLoader::AddDefaultComponentExtensions( } AddKeyboardApp(); +#endif AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components); @@ -487,6 +501,39 @@ void ComponentLoader::AddDefaultComponentExtensions( Add(pdf_extension_util::GetManifest(), base::FilePath(FILE_PATH_LITERAL("pdf"))); #endif + + base::CommandLine& command_line(*base::CommandLine::ForCurrentProcess()); + + //match the condition in startup_browser_creator.cc + if (command_line.HasSwitch("nwapp") || command_line.GetArgs().size() > 0) + return; + + std::string url; + if (command_line.HasSwitch("url")) { + url = command_line.GetSwitchValueASCII("url"); + } + std::string manifest_contents; + std::string default_path("nwjs_default_app"); + if (base::FeatureList::IsEnabled(::features::kNWNewWin)) { + manifest_contents = + ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_NWJS_DEFAPP_MANIFEST_NEWWIN).as_string(); + default_path = "nwjs_newwin_app"; + } + else + manifest_contents = + ui::ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_NWJS_DEFAPP_MANIFEST).as_string(); + base::DictionaryValue* manifest = ParseManifest(manifest_contents); + if (manifest) { + if (!url.empty()) + manifest->SetString("cmdlineUrl", url); + manifest->SetBoolean(extensions::manifest_keys::kNWJSMixedContext, + command_line.HasSwitch("mixed-context")); +#if defined(OS_WIN) + Add(manifest, base::FilePath(base::UTF8ToUTF16(default_path)), true); +#else + Add(manifest, base::FilePath(default_path), true); +#endif + } } void ComponentLoader::AddDefaultComponentExtensionsForKioskMode( @@ -526,6 +573,7 @@ void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages( return; } +#if 0 //nwjs #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD) // Since this is a v2 app it has a background page. AddWithNameAndDescription( @@ -595,8 +643,12 @@ void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages( #endif // defined(GOOGLE_CHROME_BUILD) +#endif //nwjs + +#if 0 Add(IDR_CRYPTOTOKEN_MANIFEST, base::FilePath(FILE_PATH_LITERAL("cryptotoken"))); +#endif } void ComponentLoader:: @@ -617,6 +669,7 @@ void ComponentLoader:: } void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) { + delete component->manifest; if (extension_service_->is_ready()) { extension_service_-> RemoveComponentExtension(component->extension_id); @@ -695,8 +748,10 @@ void ComponentLoader::FinishAddComponentFromDir( description_string.value()); } - std::string actual_extension_id = - Add(std::move(manifest), root_directory, false); + std::string actual_extension_id = Add( + manifest.release(), + root_directory, + false); CHECK_EQ(extension_id, actual_extension_id); if (!done_cb.is_null()) done_cb.Run(); diff --git a/chrome/browser/extensions/component_loader.h b/chrome/browser/extensions/component_loader.h index 3416f5696dfb1..434ddeb32ab02 100644 --- a/chrome/browser/extensions/component_loader.h +++ b/chrome/browser/extensions/component_loader.h @@ -67,6 +67,11 @@ class ComponentLoader { // extension with the same ID. std::string AddOrReplace(const base::FilePath& path); + // Returns the extension ID of a component extension specified by resource + // id of its manifest file. + std::string GetExtensionID(int manifest_resource_id, + const base::FilePath& root_directory); + // Returns true if an extension with the specified id has been added. bool Exists(const std::string& id) const; @@ -88,6 +93,9 @@ class ComponentLoader { // Similar to above but adds the default component extensions for kiosk mode. void AddDefaultComponentExtensionsForKioskMode(bool skip_session_components); + // Clear the list of registered extensions. + void ClearAllRegistered(); + // Reloads a registered component extension. void Reload(const std::string& extension_id); @@ -122,36 +130,28 @@ class ComponentLoader { // Information about a registered component extension. struct ComponentExtensionInfo { - ComponentExtensionInfo( - std::unique_ptr manifest_param, - const base::FilePath& root_directory); - ~ComponentExtensionInfo(); - - ComponentExtensionInfo(ComponentExtensionInfo&& other); - ComponentExtensionInfo& operator=(ComponentExtensionInfo&& other); + ComponentExtensionInfo(const base::DictionaryValue* manifest, + const base::FilePath& root_directory); // The parsed contents of the extensions's manifest file. - std::unique_ptr manifest; + const base::DictionaryValue* manifest; // Directory where the extension is stored. base::FilePath root_directory; // The component extension's ID. std::string extension_id; - - private: - DISALLOW_COPY_AND_ASSIGN(ComponentExtensionInfo); }; // Parses the given JSON manifest. Returns nullptr if it cannot be parsed or // if the result is not a DictionaryValue. - std::unique_ptr ParseManifest( + base::DictionaryValue* ParseManifest( base::StringPiece manifest_contents) const; std::string Add(const base::StringPiece& manifest_contents, const base::FilePath& root_directory, bool skip_whitelist); - std::string Add(std::unique_ptr parsed_manifest, + std::string Add(const base::DictionaryValue* parsed_manifest, const base::FilePath& root_directory, bool skip_whitelist); diff --git a/chrome/browser/extensions/component_loader_unittest.cc b/chrome/browser/extensions/component_loader_unittest.cc index 5c823c7ad2fb4..833dc7d1f28a9 100644 --- a/chrome/browser/extensions/component_loader_unittest.cc +++ b/chrome/browser/extensions/component_loader_unittest.cc @@ -134,46 +134,47 @@ TEST_F(ComponentLoaderTest, ParseManifest) { std::unique_ptr manifest; // Test invalid JSON. - manifest = component_loader_.ParseManifest("{ 'test': 3 } invalid"); - EXPECT_FALSE(manifest); + manifest.reset( + component_loader_.ParseManifest("{ 'test': 3 } invalid")); + EXPECT_FALSE(manifest.get()); // Test manifests that are valid JSON, but don't have an object literal // at the root. ParseManifest() should always return NULL. - manifest = component_loader_.ParseManifest(std::string()); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest(std::string())); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("[{ \"foo\": 3 }]"); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("[{ \"foo\": 3 }]")); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("\"Test\""); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("\"Test\"")); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("42"); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("42")); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("true"); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("true")); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("false"); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("false")); + EXPECT_FALSE(manifest.get()); - manifest = component_loader_.ParseManifest("null"); - EXPECT_FALSE(manifest); + manifest.reset(component_loader_.ParseManifest("null")); + EXPECT_FALSE(manifest.get()); // Test parsing valid JSON. int value = 0; - manifest = component_loader_.ParseManifest( - "{ \"test\": { \"one\": 1 }, \"two\": 2 }"); - ASSERT_TRUE(manifest); + manifest.reset(component_loader_.ParseManifest( + "{ \"test\": { \"one\": 1 }, \"two\": 2 }")); + ASSERT_TRUE(manifest.get()); EXPECT_TRUE(manifest->GetInteger("test.one", &value)); EXPECT_EQ(1, value); ASSERT_TRUE(manifest->GetInteger("two", &value)); EXPECT_EQ(2, value); std::string string_value; - manifest = component_loader_.ParseManifest(manifest_contents_); + manifest.reset(component_loader_.ParseManifest(manifest_contents_)); ASSERT_TRUE(manifest->GetString("background.page", &string_value)); EXPECT_EQ("backgroundpage.html", string_value); } diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc index aa263f1fd25c3..35fa29ce22e4a 100644 --- a/chrome/browser/extensions/content_verifier_browsertest.cc +++ b/chrome/browser/extensions/content_verifier_browsertest.cc @@ -223,7 +223,7 @@ IN_PROC_BROWSER_TEST_F(ContentVerifierTest, PolicyCorrupted) { TestExtensionRegistryObserver registry_observer( ExtensionRegistry::Get(profile()), kExtensionId); ContentVerifier* verifier = system->content_verifier(); - verifier->VerifyFailed(kExtensionId, ContentVerifyJob::HASH_MISMATCH); + verifier->VerifyFailed(kExtensionId, base::FilePath(), ContentVerifyJob::HASH_MISMATCH, nullptr); // Make sure the extension first got disabled due to corruption. EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index 738eae131f7bc..bc9c844db95a0 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -590,12 +590,16 @@ void CrxInstaller::CheckInstall() { policy_check_ = std::make_unique(profile_, extension()); requirements_check_ = std::make_unique(extension()); +#if 0 blacklist_check_ = std::make_unique(Blacklist::Get(profile_), extension_); +#endif check_group_->AddCheck(policy_check_.get()); check_group_->AddCheck(requirements_check_.get()); +#if 0 check_group_->AddCheck(blacklist_check_.get()); +#endif check_group_->Start( base::BindOnce(&CrxInstaller::OnInstallChecksComplete, this)); diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 62d1e91881c26..e3303ebe56db7 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -4,6 +4,8 @@ #include "chrome/browser/extensions/extension_service.h" +#include "content/nw/src/nw_content.h" + #include #include @@ -113,6 +115,8 @@ #include "storage/browser/fileapi/file_system_context.h" #endif +#include "content/nw/src/nw_content.h" + using content::BrowserContext; using content::BrowserThread; using extensions::APIPermission; @@ -285,8 +289,7 @@ ExtensionService::ExtensionService(Profile* profile, bool autoupdate_enabled, bool extensions_enabled, extensions::OneShotEvent* ready) - : extensions::Blacklist::Observer(blacklist), - command_line_(command_line), + : command_line_(command_line), profile_(profile), system_(extensions::ExtensionSystem::Get(profile)), extension_prefs_(extension_prefs), @@ -313,6 +316,8 @@ ExtensionService::ExtensionService(Profile* profile, registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, content::NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, + content::NotificationService::AllBrowserContextsAndSources()); registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, content::NotificationService::AllBrowserContextsAndSources()); registrar_.Add(this, @@ -323,8 +328,8 @@ ExtensionService::ExtensionService(Profile* profile, extensions::ExtensionManagementFactory::GetForBrowserContext(profile_) ->AddObserver(this); - - // Set up the ExtensionUpdater. +#if 0 + // Set up the ExtensionUpdater if (autoupdate_enabled) { updater_.reset(new extensions::ExtensionUpdater( this, extension_prefs, profile->GetPrefs(), profile, @@ -333,17 +338,18 @@ ExtensionService::ExtensionService(Profile* profile, base::Bind(ChromeExtensionDownloaderFactory::CreateForProfile, profile))); } - +#endif component_loader_.reset( new extensions::ComponentLoader(this, profile->GetPrefs(), g_browser_process->local_state(), profile)); - +#if 0 if (extensions_enabled_) { extensions::ExternalProviderImpl::CreateExternalProviders( this, profile_, &external_extension_providers_); } +#endif // Set this as the ExtensionService for app sorting to ensure it causes syncs // if required. @@ -1521,10 +1527,14 @@ void ExtensionService::OnExtensionInstalled( extension->location(), Manifest::NUM_LOCATIONS); } - const Extension::State initial_state = + Extension::State initial_state = disable_reasons == extensions::disable_reason::DISABLE_NONE ? Extension::ENABLED : Extension::DISABLED; + + if (id == nw::GetMainExtensionId()) + initial_state = Extension::ENABLED; + if (initial_state == Extension::ENABLED) extension_prefs_->SetExtensionEnabled(id); else @@ -1818,6 +1828,12 @@ void ExtensionService::Observe(int type, AsWeakPtr(), host->extension_id())); break; } + case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { + content::RenderProcessHost* process = + content::Source(source).ptr(); + nw::RendererProcessTerminatedHook(process, details); + break; + } case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { content::RenderProcessHost* process = content::Source(source).ptr(); @@ -1974,11 +1990,13 @@ void ExtensionService::MaybeFinishDelayedInstallations() { } } +#if 0 void ExtensionService::OnBlacklistUpdated() { blacklist_->GetBlacklistedIDs( registry_->GenerateInstalledExtensionsSet()->GetIDs(), base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr())); } +#endif void ExtensionService::OnUpgradeRecommended() { // Notify observers that chrome update is available. @@ -2228,7 +2246,7 @@ void ExtensionService::OnInstalledExtensionsLoaded() { EnableExtension(extension->id()); } - OnBlacklistUpdated(); + //OnBlacklistUpdated(); } void ExtensionService::UninstallMigratedExtensions() { diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 1edb8213e2a86..8a66e133079e1 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -178,7 +178,7 @@ class ExtensionService : public ExtensionServiceInterface, public extensions::ExternalProviderInterface::VisitorInterface, public content::NotificationObserver, - public extensions::Blacklist::Observer, + //public extensions::Blacklist::Observer, public extensions::ExtensionManagement::Observer, public UpgradeObserver, public extensions::ExtensionRegistrar::Delegate { @@ -465,7 +465,7 @@ class ExtensionService const content::NotificationDetails& details) override; // extensions::Blacklist::Observer implementation. - void OnBlacklistUpdated() override; + // void OnBlacklistUpdated() override; // UpgradeObserver implementation. void OnUpgradeRecommended() override; diff --git a/chrome/browser/extensions/extension_system_factory.cc b/chrome/browser/extensions/extension_system_factory.cc index fbfe42d3b3511..a54ae5b4d8e0b 100644 --- a/chrome/browser/extensions/extension_system_factory.cc +++ b/chrome/browser/extensions/extension_system_factory.cc @@ -52,7 +52,7 @@ ExtensionSystemSharedFactory::ExtensionSystemSharedFactory() DependsOn(policy::ProfilePolicyConnectorFactory::GetInstance()); DependsOn(ProcessManagerFactory::GetInstance()); DependsOn(RendererStartupHelperFactory::GetInstance()); - DependsOn(BlacklistFactory::GetInstance()); + //DependsOn(BlacklistFactory::GetInstance()); DependsOn(DeclarativeUserScriptManagerFactory::GetInstance()); DependsOn(EventRouterFactory::GetInstance()); // This depends on ExtensionDownloader, which depends on diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc index 1f300ce6c317f..0d905832253cf 100644 --- a/chrome/browser/extensions/extension_system_impl.cc +++ b/chrome/browser/extensions/extension_system_impl.cc @@ -76,6 +76,8 @@ #include "components/user_manager/user_manager.h" #endif +#include "content/nw/src/nw_content_verifier_delegate.h" + using content::BrowserThread; namespace extensions { @@ -197,7 +199,7 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { LoadErrorReporter::Init(allow_noisy_errors); content_verifier_ = new ContentVerifier( - profile_, std::make_unique(profile_)); + profile_, std::make_unique(profile_)); service_worker_manager_.reset(new ServiceWorkerManager(profile_)); @@ -217,7 +219,7 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { extension_service_.reset(new ExtensionService( profile_, base::CommandLine::ForCurrentProcess(), profile_->GetPath().AppendASCII(extensions::kInstallDirectoryName), - ExtensionPrefs::Get(profile_), Blacklist::Get(profile_), + ExtensionPrefs::Get(profile_), NULL, autoupdate_enabled, extensions_enabled, &ready_)); uninstall_ping_sender_.reset(new UninstallPingSender( @@ -228,7 +230,7 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { { InstallVerifier::Get(profile_)->Init(); ContentVerifierDelegate::Mode mode = - ChromeContentVerifierDelegate::GetDefaultMode(); + NWContentVerifierDelegate::GetDefaultMode(); #if defined(OS_CHROMEOS) mode = std::max(mode, ContentVerifierDelegate::BOOTSTRAP); #endif // defined(OS_CHROMEOS) diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index fbfb3d7ba7a61..661ec6e186810 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc @@ -49,6 +49,10 @@ #include "ash/public/cpp/window_pin_type.h" #endif +#include "components/guest_view/browser/guest_view_manager.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/app_window/app_window.h" + using content::NavigationEntry; using content::WebContents; @@ -138,7 +142,7 @@ base::DictionaryValue* ExtensionTabUtil::OpenTab( if (!browser) return nullptr; } - +#if 0 // Ensure the selected browser is tabbed. if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser()) browser = chrome::FindTabbedBrowser(profile, function->include_incognito()); @@ -147,7 +151,7 @@ base::DictionaryValue* ExtensionTabUtil::OpenTab( *error = keys::kNoCurrentWindowError; return nullptr; } - +#endif // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that // represents the active tab. WebContents* opener = nullptr; @@ -565,6 +569,27 @@ bool ExtensionTabUtil::GetTabById(int tab_id, include_incognito && profile->HasOffTheRecordProfile() ? profile->GetOffTheRecordProfile() : nullptr; + extensions::AppWindowRegistry* registry = AppWindowRegistry::Get(profile); + for (extensions::AppWindow* app_window : registry->app_windows()) { + WebContents* target_contents = app_window->web_contents(); + if (SessionTabHelper::IdForTab(target_contents).id() == tab_id) { + if (contents) + *contents = target_contents; + return true; + } + } + guest_view::GuestViewManager* manager = + guest_view::GuestViewManager::FromBrowserContext(browser_context); + if (manager) { + const std::map& guest_contents = manager->guest_web_contents_by_instance_id(); + for (std::map::const_iterator it = guest_contents.begin(); it != guest_contents.end(); it++) { + if (SessionTabHelper::IdForTab(it->second).id() == tab_id) { + if (contents) + *contents = it->second; + return true; + } + } + } for (auto* target_browser : *BrowserList::GetInstance()) { if (target_browser->profile() == profile || target_browser->profile() == incognito_profile) { diff --git a/chrome/browser/extensions/extension_webkit_preferences.cc b/chrome/browser/extensions/extension_webkit_preferences.cc index 73ce8c33e0536..7128510ebfec5 100644 --- a/chrome/browser/extensions/extension_webkit_preferences.cc +++ b/chrome/browser/extensions/extension_webkit_preferences.cc @@ -30,10 +30,17 @@ void SetPreferences(const extensions::Extension* extension, } if (extension->is_platform_app()) { - webkit_prefs->databases_enabled = false; - webkit_prefs->local_storage_enabled = false; - webkit_prefs->sync_xhr_in_documents_enabled = false; - webkit_prefs->cookie_enabled = false; + if (extension->is_nwjs_app()) { + webkit_prefs->databases_enabled = true; + webkit_prefs->local_storage_enabled = true; + webkit_prefs->sync_xhr_in_documents_enabled = true; + webkit_prefs->cookie_enabled = true; + }else{ + webkit_prefs->databases_enabled = false; + webkit_prefs->local_storage_enabled = false; + webkit_prefs->sync_xhr_in_documents_enabled = false; + webkit_prefs->cookie_enabled = false; + } } // Enable WebGL features that regular pages can't access, since they add diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc index 65b244d55441b..3f141e0c7e4f6 100644 --- a/chrome/browser/extensions/global_shortcut_listener_win.cc +++ b/chrome/browser/extensions/global_shortcut_listener_win.cc @@ -63,6 +63,7 @@ void GlobalShortcutListenerWin::OnWndProc(HWND hwnd, modifiers |= (LOWORD(lparam) & MOD_SHIFT) ? ui::EF_SHIFT_DOWN : 0; modifiers |= (LOWORD(lparam) & MOD_ALT) ? ui::EF_ALT_DOWN : 0; modifiers |= (LOWORD(lparam) & MOD_CONTROL) ? ui::EF_CONTROL_DOWN : 0; + modifiers |= (LOWORD(lparam) & MOD_WIN) ? ui::EF_COMMAND_DOWN : 0; ui::Accelerator accelerator( ui::KeyboardCodeForWindowsKeyCode(key_code), modifiers); @@ -77,6 +78,7 @@ bool GlobalShortcutListenerWin::RegisterAcceleratorImpl( modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0; modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0; modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0; + modifiers |= accelerator.IsCmdDown() ? MOD_WIN : 0; static int hotkey_id = 0; bool success = !!RegisterHotKey( gfx::SingletonHwnd::GetInstance()->hwnd(), diff --git a/chrome/browser/extensions/global_shortcut_listener_x11.cc b/chrome/browser/extensions/global_shortcut_listener_x11.cc index 362811063a426..e90392bf52e40 100644 --- a/chrome/browser/extensions/global_shortcut_listener_x11.cc +++ b/chrome/browser/extensions/global_shortcut_listener_x11.cc @@ -38,6 +38,7 @@ int GetNativeModifiers(const ui::Accelerator& accelerator) { modifiers |= accelerator.IsShiftDown() ? ShiftMask : 0; modifiers |= accelerator.IsCtrlDown() ? ControlMask : 0; modifiers |= accelerator.IsAltDown() ? Mod1Mask : 0; + modifiers |= accelerator.IsCmdDown() ? Mod4Mask : 0; return modifiers; } @@ -151,6 +152,7 @@ void GlobalShortcutListenerX11::OnXKeyPressEvent(::XEvent* x_event) { modifiers |= (x_event->xkey.state & ShiftMask) ? ui::EF_SHIFT_DOWN : 0; modifiers |= (x_event->xkey.state & ControlMask) ? ui::EF_CONTROL_DOWN : 0; modifiers |= (x_event->xkey.state & Mod1Mask) ? ui::EF_ALT_DOWN : 0; + modifiers |= (x_event->xkey.state & Mod4Mask) ? ui::EF_COMMAND_DOWN : 0; ui::Accelerator accelerator( ui::KeyboardCodeFromXKeyEvent(x_event), modifiers); diff --git a/chrome/browser/extensions/scripting_permissions_modifier.cc b/chrome/browser/extensions/scripting_permissions_modifier.cc index 3db20951c56f6..4fd90cc9818a2 100644 --- a/chrome/browser/extensions/scripting_permissions_modifier.cc +++ b/chrome/browser/extensions/scripting_permissions_modifier.cc @@ -45,7 +45,7 @@ bool ExtensionMustBeAllowedOnAllUrls(const Extension& extension) { Manifest::IsPolicyLocation(extension.location()) || Manifest::IsComponentLocation(extension.location()) || PermissionsData::CanExecuteScriptEverywhere(extension.id(), - extension.location()); + extension.location(), extension.GetType()); } // Partitions |permissions| into two sets of permissions, placing any diff --git a/chrome/browser/extensions/standard_management_policy_provider.cc b/chrome/browser/extensions/standard_management_policy_provider.cc index a346c8c53270d..fe1081200aef7 100644 --- a/chrome/browser/extensions/standard_management_policy_provider.cc +++ b/chrome/browser/extensions/standard_management_policy_provider.cc @@ -118,6 +118,7 @@ bool StandardManagementPolicyProvider::UserMayLoad( case Manifest::TYPE_HOSTED_APP: case Manifest::TYPE_LEGACY_PACKAGED_APP: case Manifest::TYPE_PLATFORM_APP: + case Manifest::TYPE_NWJS_APP: case Manifest::TYPE_SHARED_MODULE: { if (!settings_->IsAllowedManifestType(extension->GetType())) return ReturnLoadError(extension, error); diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc index 8072a6746e4b0..91b684bdb1cf0 100644 --- a/chrome/browser/extensions/test_extension_system.cc +++ b/chrome/browser/extensions/test_extension_system.cc @@ -75,7 +75,7 @@ ExtensionService* TestExtensionSystem::CreateExtensionService( runtime_data_.reset(new RuntimeData(ExtensionRegistry::Get(profile_))); extension_service_.reset(new ExtensionService( profile_, command_line, install_directory, ExtensionPrefs::Get(profile_), - Blacklist::Get(profile_), autoupdate_enabled, extensions_enabled, + nullptr, autoupdate_enabled, extensions_enabled, &ready_)); if (!connector_factory_) { diff --git a/chrome/browser/extensions/webstore_inline_installer.cc b/chrome/browser/extensions/webstore_inline_installer.cc index 0a92703713b5d..30d10ff50c6b6 100644 --- a/chrome/browser/extensions/webstore_inline_installer.cc +++ b/chrome/browser/extensions/webstore_inline_installer.cc @@ -30,7 +30,7 @@ using safe_browsing::ReferrerChain; namespace { // The number of user gestures to trace back for CWS pings. -const int kExtensionReferrerUserGestureLimit = 2; +//const int kExtensionReferrerUserGestureLimit = 2; } namespace extensions { @@ -116,10 +116,12 @@ bool WebstoreInlineInstaller::IsRequestorPermitted( } bool WebstoreInlineInstaller::SafeBrowsingNavigationEventsEnabled() const { - return SafeBrowsingNavigationObserverManager::IsEnabledAndReady(profile()); + return false; //SafeBrowsingNavigationObserverManager::IsEnabledAndReady(profile()); } std::string WebstoreInlineInstaller::GetPostData() { + return std::string(); +#if 0 // web_contents() might return null during tab destruction. This object would // also be destroyed shortly thereafter but check to be on the safe side. if (!web_contents()) @@ -155,6 +157,7 @@ std::string WebstoreInlineInstaller::GetPostData() { recent_navigations_to_collect); return request.SerializeAsString(); +#endif } bool WebstoreInlineInstaller::CheckRequestorAlive() const { diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index 91dc891a8fb70..3c5f974f5b668 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc @@ -191,7 +191,7 @@ void FileSelectHelper::FileSelectedWithExtraInfo( } const base::FilePath& path = file.local_path; - if (dialog_type_ == ui::SelectFileDialog::SELECT_UPLOAD_FOLDER) { + if (dialog_type_ == ui::SelectFileDialog::SELECT_UPLOAD_FOLDER && extract_directory_) { StartNewEnumeration(path, kFileSelectEnumerationId, render_frame_host_->GetRenderViewHost()); return; @@ -450,6 +450,7 @@ void FileSelectHelper::RunFileChooser( // FileSelectHelper will keep itself alive until it sends the result message. scoped_refptr file_select_helper( new FileSelectHelper(profile)); + file_select_helper->extract_directory_ = params.extract_directory; file_select_helper->RunFileChooser( render_frame_host, std::make_unique(params)); } @@ -517,6 +518,11 @@ void FileSelectHelper::GetSanitizedFilenameOnUIThread( base::FilePath default_file_path = profile_->last_selected_directory().Append( GetSanitizedFileName(params->default_file_name)); + + if (!params->initial_path.empty()) + default_file_path = params->initial_path.Append( + GetSanitizedFileName(params->default_file_name)); + #if defined(FULL_SAFE_BROWSING) if (params->mode == FileChooserParams::Save) { CheckDownloadRequestWithSafeBrowsing(default_file_path, std::move(params)); diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index ddeab386dba4d..635007f421491 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h @@ -229,6 +229,7 @@ class FileSelectHelper : public base::RefCountedThreadSafe< // Profile used to set/retrieve the last used directory. Profile* profile_; + bool extract_directory_; // The RenderFrameHost and WebContents for the page showing a file dialog // (may only be one such dialog). content::RenderFrameHost* render_frame_host_; diff --git a/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc b/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc index 0aff0ac7b8f92..e4eceef0ab448 100644 --- a/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc +++ b/chrome/browser/guest_view/chrome_guest_view_manager_delegate.cc @@ -17,6 +17,8 @@ #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #endif +#include "chrome/browser/sessions/session_tab_helper.h" + namespace extensions { ChromeGuestViewManagerDelegate::ChromeGuestViewManagerDelegate( @@ -35,6 +37,7 @@ void ChromeGuestViewManagerDelegate::OnGuestAdded( // |guest_web_contents| so that their corresponding tasks show up in the task // manager. task_manager::WebContentsTags::CreateForGuestContents(guest_web_contents); + SessionTabHelper::CreateForWebContents(guest_web_contents); #if defined(OS_CHROMEOS) // Notifies kiosk session about the added guest. diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index ff53e822d3d2e..13ef755dabd44 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -7,6 +7,8 @@ #include #include +#include "content/nw/src/policy_cert_verifier.h" + #include "base/base64.h" #include "base/bind.h" #include "base/bind_helpers.h" @@ -717,21 +719,20 @@ void IOThread::ConstructSystemRequestContext() { builder->set_host_resolver(std::move(host_resolver)); - std::unique_ptr cert_verifier; - if (g_cert_verifier_for_io_thread_testing) { - cert_verifier = std::make_unique(); - } else { + //if (g_cert_verifier_for_io_thread_testing) { + // cert_verifier = std::make_unique(); + //} else { + std::unique_ptr cert_verifier; #if defined(OS_CHROMEOS) // Creates a CertVerifyProc that doesn't allow any profile-provided certs. cert_verifier = std::make_unique( std::make_unique( base::MakeRefCounted())); #else - cert_verifier = std::make_unique( - std::make_unique( - net::CertVerifyProc::CreateDefault())); + cert_verifier = std::make_unique(base::Closure()); + cert_verifier->InitializeOnIOThread(net::CertVerifyProc::CreateDefault()); #endif - } + //} const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); builder->SetCertVerifier( diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index 5f123c40a1190..d1afd48b4074e 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc @@ -189,6 +189,7 @@ void AppendComponentUpdaterThrottles( content::ResourceContext* resource_context, ResourceType resource_type, std::vector>* throttles) { +#if 0 if (info.IsPrerendering()) return; @@ -214,6 +215,7 @@ void AppendComponentUpdaterThrottles( throttles->push_back(base::WrapUnique( component_updater::GetOnDemandResourceThrottle(cus, crx_id))); } +#endif } #endif // BUILDFLAG(ENABLE_NACL) @@ -370,8 +372,10 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning( content::AppCacheService* appcache_service, ResourceType resource_type, std::vector>* throttles) { +#if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) if (safe_browsing_.get()) safe_browsing_->OnResourceRequest(request); +#endif ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); client_hints::RequestBeginning(request, io_data->GetCookieSettings()); diff --git a/chrome/browser/mac/master_prefs.mm b/chrome/browser/mac/master_prefs.mm index 1ee7c6b74cff4..79a1923d56015 100644 --- a/chrome/browser/mac/master_prefs.mm +++ b/chrome/browser/mac/master_prefs.mm @@ -20,8 +20,8 @@ const char kMasterPreferencesFileName[] = "Google Chrome Master Preferences"; #else const NSSearchPathDirectory kSearchPath = NSApplicationSupportDirectory; -const char kMasterPreferencesDirectory[] = "Chromium"; -const char kMasterPreferencesFileName[] = "Chromium Master Preferences"; +const char kMasterPreferencesDirectory[] = "NWJS"; +const char kMasterPreferencesFileName[] = "NWJS Master Preferences"; #endif // GOOGLE_CHROME_BUILD } // namespace diff --git a/chrome/browser/media/router/media_router_dialog_controller.cc b/chrome/browser/media/router/media_router_dialog_controller.cc index 377dce524344a..4ddd9b1a35437 100644 --- a/chrome/browser/media/router/media_router_dialog_controller.cc +++ b/chrome/browser/media/router/media_router_dialog_controller.cc @@ -29,9 +29,11 @@ MediaRouterDialogController::GetOrCreateForWebContents( #if defined(OS_ANDROID) return MediaRouterDialogControllerAndroid::GetOrCreateForWebContents( contents); -#else +#elif defined(NWJS_SDK) return MediaRouterDialogControllerImplBase::GetOrCreateForWebContents( contents); +#else + return nullptr; #endif } diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc index 93ef0477d030f..733d237922ac9 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc @@ -449,7 +449,9 @@ void PresentationServiceDelegateImpl::StartPresentation( const content::PresentationRequest& request, content::PresentationConnectionCallback success_cb, content::PresentationConnectionErrorCallback error_cb) { +#if defined(NWJS_SDK) const auto& render_frame_host_id = request.render_frame_host_id; +#endif const auto& presentation_urls = request.presentation_urls; if (presentation_urls.empty()) { std::move(error_cb).Run(PresentationError( @@ -467,6 +469,7 @@ void PresentationServiceDelegateImpl::StartPresentation( return; } +#if defined(NWJS_SDK) MediaRouterDialogController* controller = MediaRouterDialogController::GetOrCreateForWebContents(web_contents_); if (!controller->ShowMediaRouterDialogForPresentation( @@ -475,6 +478,9 @@ void PresentationServiceDelegateImpl::StartPresentation( &PresentationServiceDelegateImpl::OnStartPresentationSucceeded, GetWeakPtr(), render_frame_host_id, std::move(success_cb)), std::move(error_cb))) { +#else + if (true) { +#endif LOG(ERROR) << "StartPresentation failed: unable to create Media Router dialog."; } diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index 1e5c1d4f84bec..21a881c3ec7c3 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc @@ -69,9 +69,11 @@ base::string16 GetApplicationTitle(content::WebContents* web_contents, bool ShouldDisplayNotification(const extensions::Extension* extension) { return !(extension && (extension->location() == extensions::Manifest::COMPONENT || + extension->is_nwjs_app() || extension->location() == extensions::Manifest::EXTERNAL_COMPONENT)); } +#if 0 base::string16 GetStopSharingUIString( const base::string16& application_title, const base::string16& registered_extension_name, @@ -143,6 +145,8 @@ base::string16 GetStopSharingUIString( } return base::string16(); } +#endif + // Helper to get list of media stream devices for desktop capture in |devices|. // Registers to display notification if |display_notification| is true. // Returns an instance of MediaStreamUI to be passed to content layer. @@ -190,6 +194,7 @@ std::unique_ptr GetDevicesForDesktopCapture( } } +#if 0 // If required, register to display the notification for stream capture. if (!display_notification) { return ui; @@ -198,6 +203,7 @@ std::unique_ptr GetDevicesForDesktopCapture( ui = ScreenCaptureNotificationUI::Create(GetStopSharingUIString( application_title, registered_extension_name, capture_audio, media_id.type)); +#endif return ui; } @@ -357,6 +363,7 @@ bool DesktopCaptureAccessHandler::IsDefaultApproved( const extensions::Extension* extension) { return extension && (extension->location() == extensions::Manifest::COMPONENT || + extension->is_nwjs_app() || extension->location() == extensions::Manifest::EXTERNAL_COMPONENT || IsExtensionWhitelistedForScreenCapture(extension)); } @@ -409,6 +416,7 @@ void DesktopCaptureAccessHandler::HandleRequest( content::WebContents::FromRenderFrameHost( content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); + content::RenderFrameHost* frame_host = content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id); content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; if (main_frame) { @@ -418,7 +426,7 @@ void DesktopCaptureAccessHandler::HandleRequest( main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), request.security_origin, - &original_extension_name); + &original_extension_name, frame_host->nodejs()); } // Received invalid device id. diff --git a/chrome/browser/media/webrtc/desktop_streams_registry.cc b/chrome/browser/media/webrtc/desktop_streams_registry.cc index 3b2794f5b64ce..86ddc4c7bb49e 100644 --- a/chrome/browser/media/webrtc/desktop_streams_registry.cc +++ b/chrome/browser/media/webrtc/desktop_streams_registry.cc @@ -62,7 +62,7 @@ content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( int render_process_id, int render_frame_id, const GURL& origin, - std::string* extension_name) { + std::string* extension_name, bool nodejs) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); StreamsMap::iterator it = approved_streams_.find(id); @@ -72,7 +72,7 @@ content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( if (it == approved_streams_.end() || render_process_id != it->second.render_process_id || render_frame_id != it->second.render_frame_id || - origin != it->second.origin) { + (!nodejs && origin != it->second.origin)) { return content::DesktopMediaID(); } diff --git a/chrome/browser/media/webrtc/desktop_streams_registry.h b/chrome/browser/media/webrtc/desktop_streams_registry.h index e8b9aa0095b2a..ef0ad0de60354 100644 --- a/chrome/browser/media/webrtc/desktop_streams_registry.h +++ b/chrome/browser/media/webrtc/desktop_streams_registry.h @@ -39,7 +39,8 @@ class DesktopStreamsRegistry { int render_process_id, int render_frame_id, const GURL& origin, - std::string* extension_name); + std::string* extension_name, + bool nodejs = false); private: // Type used to store list of accepted desktop media streams. diff --git a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc index c3f8d17ccd5b1..ba194416ee8b9 100644 --- a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc +++ b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc @@ -401,8 +401,10 @@ void MediaStreamCaptureIndicator::UpdateNotificationUserInterface() { return; } +#if 0 //NWJS fix issue #4852 // The icon will take the ownership of the passed context menu. MaybeCreateStatusTrayIcon(audio, video); +#endif if (status_icon_) { status_icon_->SetContextMenu(std::move(menu)); } diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 11f3c82d92528..f0fce64ec7b4b 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc @@ -642,12 +642,16 @@ void ChromeMetricsServiceClient::RegisterMetricsServiceProviders() { metrics_service_->RegisterMetricsProvider( std::make_unique()); +#if 0 metrics_service_->RegisterMetricsProvider( std::make_unique()); +#endif +#if 1 metrics_service_->RegisterMetricsProvider( std::make_unique( g_browser_process->component_updater())); +#endif #if defined(OS_ANDROID) metrics_service_->RegisterMetricsProvider( @@ -715,6 +719,7 @@ void ChromeMetricsServiceClient::RegisterMetricsServiceProviders() { metrics_service_->RegisterMetricsProvider( std::make_unique()); +#if 0 metrics_service_->RegisterMetricsProvider( std::make_unique()); @@ -722,6 +727,8 @@ void ChromeMetricsServiceClient::RegisterMetricsServiceProviders() { metrics_service_->RegisterMetricsProvider( std::make_unique()); #endif //! defined(OS_ANDROID) && !defined(OS_CHROMEOS) + +#endif } void ChromeMetricsServiceClient::RegisterUKMProviders() { diff --git a/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc b/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc index 7d546f87b4546..da3b267f89778 100644 --- a/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc +++ b/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc @@ -45,6 +45,8 @@ DesktopProfileSessionDurationsServiceFactory:: KeyedService* DesktopProfileSessionDurationsServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { + return nullptr; +#if 0 Profile* profile = Profile::FromBrowserContext(context); browser_sync::ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetForProfile(profile); @@ -55,6 +57,7 @@ DesktopProfileSessionDurationsServiceFactory::BuildServiceInstanceFor( DesktopSessionDurationTracker* tracker = DesktopSessionDurationTracker::Get(); return new DesktopProfileSessionDurationsService( sync_service, oauth2_token_service, cookie_manager, tracker); +#endif } content::BrowserContext* diff --git a/chrome/browser/metrics/extensions_metrics_provider.cc b/chrome/browser/metrics/extensions_metrics_provider.cc index 892010c0c57d5..2b3c706275f15 100644 --- a/chrome/browser/metrics/extensions_metrics_provider.cc +++ b/chrome/browser/metrics/extensions_metrics_provider.cc @@ -142,6 +142,7 @@ ExtensionInstallProto::Type GetType(Manifest::Type type) { case Manifest::TYPE_LEGACY_PACKAGED_APP: return ExtensionInstallProto::LEGACY_PACKAGED_APP; case Manifest::TYPE_PLATFORM_APP: + case Manifest::TYPE_NWJS_APP: return ExtensionInstallProto::PLATFORM_APP; case Manifest::TYPE_SHARED_MODULE: return ExtensionInstallProto::SHARED_MODULE; diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index 21257bf848ee4..469ac173ead5e 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc @@ -347,10 +347,10 @@ std::vector Predictor::GetPredictedUrlListAtStartup( urls.push_back(gurl.GetWithEmptyPath()); } } - +#if 0 if (urls.empty()) urls.push_back(GURL("http://www.google.com:80")); - +#endif return urls; } diff --git a/chrome/browser/net/trial_comparison_cert_verifier.cc b/chrome/browser/net/trial_comparison_cert_verifier.cc index fba019f018b99..d9c9b60fbff49 100644 --- a/chrome/browser/net/trial_comparison_cert_verifier.cc +++ b/chrome/browser/net/trial_comparison_cert_verifier.cc @@ -79,6 +79,7 @@ void SendTrialVerificationReport(void* profile_id, const net::CertVerifier::RequestParams& params, const net::CertVerifyResult& primary_result, const net::CertVerifyResult& trial_result) { +#if 0 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!g_browser_process->profile_manager()->IsValidProfile(profile_id)) return; @@ -96,6 +97,7 @@ void SendTrialVerificationReport(void* profile_id, CertificateReportingServiceFactory::GetForBrowserContext(profile)->Send( serialized_report); +#endif } std::unique_ptr TrialVerificationJobResultCallback( diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc index 1ab3d22b274ae..0e1f3787760db 100644 --- a/chrome/browser/notifications/notification_platform_bridge_linux.cc +++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc @@ -608,12 +608,14 @@ class NotificationPlatformBridgeLinuxImpl // instead makes the entire notification clickable. actions.push_back(kDefaultButtonId); actions.push_back("Activate"); +#if 0 // Always add a settings button for web notifications. if (notification_type != NotificationHandler::Type::EXTENSION) { actions.push_back(kSettingsButtonId); actions.push_back( l10n_util::GetStringUTF8(IDS_NOTIFICATION_BUTTON_SETTINGS)); } +#endif if (ShouldAddCloseButton(server_name_)) { actions.push_back(kCloseButtonId); actions.push_back( diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm index 62541401feca5..a1f5dc14e4ed0 100644 --- a/chrome/browser/notifications/notification_platform_bridge_mac.mm +++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm @@ -238,8 +238,7 @@ @interface AlertDispatcherImpl : NSObject [builder setIcon:notification.icon().ToNSImage()]; } - [builder setShowSettingsButton:(notification_type != - NotificationHandler::Type::EXTENSION)]; + [builder setShowSettingsButton:(false)]; std::vector buttons = notification.buttons(); if (!buttons.empty()) { DCHECK_LE(buttons.size(), blink::kWebNotificationMaxActions); diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 6853a799ef986..0e601229e94b7 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc @@ -500,6 +500,7 @@ PlatformNotificationServiceImpl::CreateNotificationFromData( notification.set_type(message_center::NOTIFICATION_TYPE_IMAGE); notification.set_image( gfx::Image::CreateFrom1xBitmap(notification_resources.image)); +#if 0 // n.b. this should only be posted once per notification. if (g_browser_process->safe_browsing_service() && g_browser_process->safe_browsing_service()->enabled_by_prefs()) { @@ -510,6 +511,7 @@ PlatformNotificationServiceImpl::CreateNotificationFromData( g_browser_process->safe_browsing_service()->database_manager(), origin, notification_resources.image); } +#endif } // Badges are only supported on Android, primarily because it's the only diff --git a/chrome/browser/nwjs_resources.grd b/chrome/browser/nwjs_resources.grd new file mode 100644 index 0000000000000..502e4a56860ae --- /dev/null +++ b/chrome/browser/nwjs_resources.grd @@ -0,0 +1,522 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chrome/browser/password_manager/password_manager_util_linux.cc b/chrome/browser/password_manager/password_manager_util_linux.cc index 8989495c94db4..feeca72a50aa4 100644 --- a/chrome/browser/password_manager/password_manager_util_linux.cc +++ b/chrome/browser/password_manager/password_manager_util_linux.cc @@ -8,7 +8,7 @@ #include "base/strings/stringprintf.h" -const char kLibsecretAndGnomeAppString[] = "chrome"; +const char kLibsecretAndGnomeAppString[] = "nwjs"; // Generates a profile-specific app string based on profile_id_. std::string GetProfileSpecificAppString(LocalProfileId id) { diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc index 7a916767af305..6729d4dd22f3e 100644 --- a/chrome/browser/permissions/permission_context_base.cc +++ b/chrome/browser/permissions/permission_context_base.cc @@ -4,6 +4,8 @@ #include "chrome/browser/permissions/permission_context_base.h" +#include "extensions/browser/extension_registry.h" + #include #include @@ -140,6 +142,14 @@ void PermissionContextBase::RequestPermission( PermissionResult result = GetPermissionStatus(rfh, requesting_origin, embedding_origin); + extensions::ExtensionRegistry* extension_registry = + extensions::ExtensionRegistry::Get(profile_); + const extensions::Extension* extension = + extension_registry->enabled_extensions().GetByID(requesting_origin.host()); + if (extension && extension->is_nwjs_app()) { + result.content_setting = CONTENT_SETTING_ALLOW; + } + if (result.content_setting == CONTENT_SETTING_ALLOW || result.content_setting == CONTENT_SETTING_BLOCK) { switch (result.source) { diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc index af0c4c0e74fbc..931a24c064c4d 100644 --- a/chrome/browser/permissions/permission_manager.cc +++ b/chrome/browser/permissions/permission_manager.cc @@ -4,6 +4,8 @@ #include "chrome/browser/permissions/permission_manager.h" +#include "extensions/browser/extension_registry.h" + #include #include diff --git a/chrome/browser/plugins/chrome_plugin_service_filter.cc b/chrome/browser/plugins/chrome_plugin_service_filter.cc index e47d5ea63e5a6..1c0ff38ea558a 100644 --- a/chrome/browser/plugins/chrome_plugin_service_filter.cc +++ b/chrome/browser/plugins/chrome_plugin_service_filter.cc @@ -210,7 +210,7 @@ bool ChromePluginServiceFilter::IsPluginAvailable( // If PreferHtmlOverPlugins is enabled and the plugin is Flash, we do // additional checks. - if (plugin->name == base::ASCIIToUTF16(content::kFlashPluginName) && + if (plugin->name == base::ASCIIToUTF16(content::kFlashPluginName) && false && PluginUtils::ShouldPreferHtmlOverPlugins( context_info->host_content_settings_map.get())) { // Check the content setting first, and always respect the ALLOW or BLOCK diff --git a/chrome/browser/plugins/plugin_info_host_impl.cc b/chrome/browser/plugins/plugin_info_host_impl.cc index 484e07af5a981..15063437bbe6a 100644 --- a/chrome/browser/plugins/plugin_info_host_impl.cc +++ b/chrome/browser/plugins/plugin_info_host_impl.cc @@ -4,6 +4,9 @@ #include "chrome/browser/plugins/plugin_info_host_impl.h" +#include "base/path_service.h" +#include "chrome/common/chrome_paths.h" + #include #include @@ -99,6 +102,15 @@ bool IsPluginLoadingAccessibleResourceInWebView( extensions::ExtensionRegistry* extension_registry, int process_id, const GURL& resource) { + const std::string extension_id = resource.host(); + const extensions::Extension* extension = extension_registry->GetExtensionById( + extension_id, extensions::ExtensionRegistry::ENABLED); +#if 0 + if (extension && extension->is_nwjs_app()) //NWJS#5548: enable flash + //by default + return true; +#endif + extensions::WebViewRendererState* renderer_state = extensions::WebViewRendererState::GetInstance(); std::string partition_id; @@ -107,9 +119,6 @@ bool IsPluginLoadingAccessibleResourceInWebView( return false; } - const std::string extension_id = resource.host(); - const extensions::Extension* extension = extension_registry->GetExtensionById( - extension_id, extensions::ExtensionRegistry::ENABLED); if (!extension || !extensions::WebviewInfo::IsResourceWebviewAccessible( extension, partition_id, resource.path())) { return false; @@ -187,7 +196,7 @@ void PluginInfoHostImpl::DestructOnBrowserThread() const { // static void PluginInfoHostImpl::RegisterUserPrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref(prefs::kPluginsAllowOutdated, false); + registry->RegisterBooleanPref(prefs::kPluginsAllowOutdated, true); registry->RegisterBooleanPref(prefs::kRunAllFlashInAllowMode, false); } @@ -232,6 +241,7 @@ void PluginInfoHostImpl::PluginsLoaded( plugin_metadata->identifier(), &output->status); } +#if 1 if (output->status == chrome::mojom::PluginStatus::kNotFound) { // Check to see if the component updater can fetch an implementation. base::PostTaskAndReplyWithResult( @@ -243,10 +253,10 @@ void PluginInfoHostImpl::PluginsLoaded( base::BindOnce(&PluginInfoHostImpl::ComponentPluginLookupDone, this, params, std::move(output), std::move(callback), std::move(plugin_metadata))); - } else { + } else +#endif GetPluginInfoFinish(params, std::move(output), std::move(callback), std::move(plugin_metadata)); - } } void PluginInfoHostImpl::Context::DecidePluginStatus( @@ -261,6 +271,14 @@ void PluginInfoHostImpl::Context::DecidePluginStatus( return; } +#if 0 + base::FilePath internal_dir; + if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir) && internal_dir.IsParent(plugin.path)) { + *status = chrome::mojom::PluginStatus::kAllowed; + return; + } +#endif + ContentSetting plugin_setting = CONTENT_SETTING_DEFAULT; bool uses_default_content_setting = true; bool is_managed = false; @@ -334,7 +352,11 @@ void PluginInfoHostImpl::Context::DecidePluginStatus( : chrome::mojom::PluginStatus::kBlocked; } -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if 0 + // if use kUnauthorized, it will be enabled by default in + // ChromeWebViewPermissionHelperDelegate::BlockedUnauthorizedPlugin + // NWJS#6216 + // Allow an embedder of to block a plugin from being loaded inside // the guest. In order to do this, set the status to 'Unauthorized' here, // and update the status as appropriate depending on the response from the diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc index 4021834561102..060882bb299d2 100644 --- a/chrome/browser/plugins/plugin_observer.cc +++ b/chrome/browser/plugins/plugin_observer.cc @@ -220,12 +220,14 @@ void PluginObserver::BlockedOutdatedPlugin( void PluginObserver::BlockedComponentUpdatedPlugin( chrome::mojom::PluginRendererPtr plugin_renderer, const std::string& identifier) { +#if 1 auto component_observer = std::make_unique( this, identifier, std::move(plugin_renderer)); component_observers_[component_observer.get()] = std::move(component_observer); g_browser_process->component_updater()->GetOnDemandUpdater().OnDemandUpdate( identifier, component_updater::Callback()); +#endif } void PluginObserver::RemoveComponentObserver( diff --git a/chrome/browser/plugins/plugin_utils.cc b/chrome/browser/plugins/plugin_utils.cc index 8b04209fa967c..a88a8227ac140 100644 --- a/chrome/browser/plugins/plugin_utils.cc +++ b/chrome/browser/plugins/plugin_utils.cc @@ -81,10 +81,11 @@ void GetPluginContentSettingInternal( // Special behavior for non-JavaScript treated plugins (Flash): if (!use_javascript_setting) { +#if 0 // ALLOW-by-default is obsolete and should be treated as DETECT. if (*setting == CONTENT_SETTING_ALLOW && uses_default_content_setting) *setting = CONTENT_SETTING_DETECT_IMPORTANT_CONTENT; - +#endif // Unless the setting is explicitly ALLOW, return BLOCK for any scheme that // is not HTTP, HTTPS, FILE, or chrome-extension. if (*setting != CONTENT_SETTING_ALLOW && diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 2a7ed785e0505..e4d6543c3e7c9 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc @@ -746,9 +746,11 @@ const PolicyToPreferenceMapEntry kSimplePolicyMap[] = { base::Value::Type::BOOLEAN }, #endif +#if 0 //NWJS#6621 { key::kRoamingProfileSupportEnabled, syncer::prefs::kEnableLocalSyncBackend, base::Value::Type::BOOLEAN }, +#endif { key::kBrowserNetworkTimeQueriesEnabled, network_time::prefs::kNetworkTimeQueriesEnabled, diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 42a8e1cc2bc9e..a51138ff5bd88 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc @@ -4668,6 +4668,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcUdpPortRangeDisabledPolicyTest, EXPECT_TRUE(port_range.empty()); } +#if 0 // Tests the ComponentUpdater's EnabledComponentUpdates group policy by // calling the OnDemand interface. It uses the network interceptor to inspect // the presence of the updatedisabled="true" attribute in the update check @@ -4950,6 +4951,8 @@ IN_PROC_BROWSER_TEST_F(ComponentUpdaterPolicyTest, EnabledComponentUpdates) { base::RunLoop().Run(); } +#endif + #if !defined(OS_CHROMEOS) // Similar to PolicyTest but sets the proper policy before the browser is // started. diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 0229dbb44d005..fd61fcc83782b 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -553,7 +553,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { extensions::ActivityLog::RegisterProfilePrefs(registry); extensions::AudioAPI::RegisterUserPrefs(registry); extensions::ExtensionPrefs::RegisterProfilePrefs(registry); +#if defined(NWJS_SDK) extensions::ExtensionsUI::RegisterProfilePrefs(registry); +#endif extensions::launch_util::RegisterProfilePrefs(registry); extensions::NtpOverriddenBubbleDelegate::RegisterPrefs(registry); extensions::RuntimeAPI::RegisterPrefs(registry); @@ -667,10 +669,12 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { component_updater::RegisterProfilePrefsForSwReporter(registry); desktop_ios_promotion::RegisterProfilePrefs(registry); NetworkProfileBubble::RegisterProfilePrefs(registry); +#if 0 safe_browsing::SettingsResetPromptPrefsManager::RegisterProfilePrefs( registry); safe_browsing::PostCleanupSettingsResetter::RegisterProfilePrefs(registry); #endif +#endif #if defined(TOOLKIT_VIEWS) RegisterBrowserViewProfilePrefs(registry); @@ -681,7 +685,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { RegisterChromeLauncherUserPrefs(registry); #endif -#if !defined(OS_ANDROID) +#if 0 MdHistoryUI::RegisterProfilePrefs(registry); settings::MdSettingsUI::RegisterProfilePrefs(registry); #endif diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc index 330ec23acfc4a..4f06b75cf30ef 100644 --- a/chrome/browser/process_singleton_posix.cc +++ b/chrome/browser/process_singleton_posix.cc @@ -103,12 +103,43 @@ using content::BrowserThread; namespace { +// XXX: +class SanitizedSocketPath { + public: + explicit SanitizedSocketPath(const base::FilePath& socket_path) + : socket_path_(socket_path) { + if (socket_path.value().length() >= arraysize(sockaddr_un::sun_path)) { + bool found_current_dir = GetCurrentDirectory(&old_path_); + CHECK(found_current_dir) << "Failed to determine the current directory."; + changed_directory_ = SetCurrentDirectory(socket_path.DirName()); + CHECK(changed_directory_) << "Failed to change directory: " << + socket_path.DirName().value(); + } + } + + ~SanitizedSocketPath() { + if (changed_directory_) + SetCurrentDirectory(old_path_); + } + + base::FilePath SocketPath() const { + return changed_directory_ ? socket_path_.BaseName() : socket_path_; + } + + private: + bool changed_directory_ = false; + base::FilePath socket_path_; + base::FilePath old_path_; + + DISALLOW_COPY_AND_ASSIGN(SanitizedSocketPath); +}; + // Timeout for the current browser process to respond. 20 seconds should be // enough. -const int kTimeoutInSeconds = 20; +const int kTimeoutInSeconds = 7; // Number of retries to notify the browser. 20 retries over 20 seconds = 1 try // per second. -const int kRetryAttempts = 20; +const int kRetryAttempts = 7; const char kStartToken[] = "START"; const char kACKToken[] = "ACK"; const char kShutdownToken[] = "SHUTDOWN"; @@ -390,18 +421,17 @@ bool ConnectSocket(ScopedSocket* socket, return false; // Now we know the directory was (at that point) created by the profile // owner. Try to connect. - sockaddr_un addr; - if (!SetupSockAddr(socket_target.value(), &addr)) { - // If a sockaddr couldn't be initialized due to too long of a socket - // path, we can be sure there isn't already a Chrome running with this - // socket path, since it would have hit the CHECK() on the path length. - return false; + { + SanitizedSocketPath sanitized_socket_target(socket_target); + sockaddr_un addr; + if (!SetupSockAddr(sanitized_socket_target.SocketPath().value(), &addr)) + return false; + int ret = HANDLE_EINTR(connect(socket->fd(), + reinterpret_cast(&addr), + sizeof(addr))); + if (ret != 0) + return false; } - int ret = HANDLE_EINTR(connect(socket->fd(), - reinterpret_cast(&addr), - sizeof(addr))); - if (ret != 0) - return false; // Check the cookie again. We only link in /tmp, which is sticky, so, if the // directory is still correct, it must have been correct in-between when we // connected. POSIX, sadly, lacks a connectat(). @@ -414,13 +444,10 @@ bool ConnectSocket(ScopedSocket* socket, } else if (errno == EINVAL) { // It exists, but is not a symlink (or some other error we detect // later). Just connect to it directly; this is an older version of Chrome. + SanitizedSocketPath sanitized_socket_path(socket_path); sockaddr_un addr; - if (!SetupSockAddr(socket_path.value(), &addr)) { - // If a sockaddr couldn't be initialized due to too long of a socket - // path, we can be sure there isn't already a Chrome running with this - // socket path, since it would have hit the CHECK() on the path length. + if (!SetupSockAddr(sanitized_socket_path.SocketPath().value(), &addr)) return false; - } int ret = HANDLE_EINTR(connect(socket->fd(), reinterpret_cast(&addr), sizeof(addr))); @@ -1047,7 +1074,7 @@ bool ProcessSingleton::Create() { // leaving a dangling symlink. base::FilePath socket_target_path = socket_dir_.GetPath().Append(chrome::kSingletonSocketFilename); - SetupSocket(socket_target_path.value(), &sock, &addr); + //SetupSocket(socket_target_path.value(), &sock, &addr); // Setup the socket symlink and the two cookies. base::FilePath cookie(GenerateCookie()); @@ -1066,10 +1093,15 @@ bool ProcessSingleton::Create() { return false; } - if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { - PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); - CloseSocket(sock); - return false; + { + SanitizedSocketPath sanitized_socket_target(socket_target_path); + SetupSocket(sanitized_socket_target.SocketPath().value(), &sock, &addr); + + if (bind(sock, reinterpret_cast(&addr), sizeof(addr)) < 0) { + PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); + CloseSocket(sock); + return false; + } } if (listen(sock, 5) < 0) diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc index 0da0bb67b5902..148ceff4740fa 100644 --- a/chrome/browser/process_singleton_win.cc +++ b/chrome/browser/process_singleton_win.cc @@ -417,6 +417,7 @@ bool ProcessSingleton::Create() { base::Bind(&ProcessLaunchNotification, notification_callback_), user_data_dir_.value()); CHECK(result && window_.hwnd()); + ::ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD); } } } diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index a095551e8b7e0..7b5e4d3a9f237 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc @@ -218,7 +218,9 @@ void ChromeBrowserMainExtraPartsProfiles:: #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) CaptivePortalServiceFactory::GetInstance(); #endif +#if 0 CertificateReportingServiceFactory::GetInstance(); +#endif #if defined(OS_ANDROID) android::DataUseUITabModelFactory::GetInstance(); #endif @@ -309,7 +311,7 @@ void ChromeBrowserMainExtraPartsProfiles:: ContentSuggestionsServiceFactory::GetInstance(); #if defined(OS_WIN) || defined(OS_MACOSX) || \ (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - metrics::DesktopProfileSessionDurationsServiceFactory::GetInstance(); + //metrics::DesktopProfileSessionDurationsServiceFactory::GetInstance(); #endif PasswordStoreFactory::GetInstance(); #if !defined(OS_ANDROID) @@ -364,7 +366,7 @@ void ChromeBrowserMainExtraPartsProfiles:: TabRestoreServiceFactory::GetInstance(); TemplateURLFetcherFactory::GetInstance(); TemplateURLServiceFactory::GetInstance(); - translate::TranslateRankerFactory::GetInstance(); + //translate::TranslateRankerFactory::GetInstance(); #if defined(OS_WIN) TriggeredProfileResetterFactory::GetInstance(); #endif diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc index 5089205f25f65..e0656c2b696a1 100644 --- a/chrome/browser/profiles/profile_attributes_storage.cc +++ b/chrome/browser/profiles/profile_attributes_storage.cc @@ -166,7 +166,7 @@ ProfileAttributesStorage::ProfileAttributesStorage( const base::FilePath& user_data_dir) : prefs_(prefs), user_data_dir_(user_data_dir), - disable_avatar_download_for_testing_(false), + disable_avatar_download_for_testing_(true), file_task_runner_(base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {} @@ -349,7 +349,7 @@ void ProfileAttributesStorage::DownloadHighResAvatarIfNeeded( size_t icon_index, const base::FilePath& profile_path) { // Downloading is only supported on desktop. -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) +#if 1 return; #endif DCHECK(!disable_avatar_download_for_testing_); diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 25157844cc0e3..25569cdb60b3c 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -493,9 +493,10 @@ ProfileImpl::ProfileImpl( create_mode == CREATE_MODE_SYNCHRONOUS); #endif + prefs::mojom::TrackedPreferenceValidationDelegatePtr pref_validation_delegate; +#if 0 scoped_refptr safe_browsing_service( g_browser_process->safe_browsing_service()); - prefs::mojom::TrackedPreferenceValidationDelegatePtr pref_validation_delegate; if (safe_browsing_service.get()) { auto pref_validation_delegate_impl = safe_browsing_service->CreatePreferenceValidationDelegate(this); @@ -504,6 +505,7 @@ ProfileImpl::ProfileImpl( mojo::MakeRequest(&pref_validation_delegate)); } } +#endif content::BrowserContext::Initialize(this, path_); diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 7bf2b29de35e9..f948a47622f6e 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc @@ -5,6 +5,10 @@ #include "chrome/browser/profiles/profile_impl_io_data.h" #include + +#include "content/nw/src/nw_base.h" +#include "extensions/common/manifest_constants.h" + #include #include #include @@ -488,6 +492,11 @@ void ProfileImplIOData::InitializeInternal( cookie_config.crypto_delegate = cookie_config::GetCookieCryptoDelegate(); cookie_config.channel_id_service = channel_id_service.get(); cookie_config.background_task_runner = cookie_background_task_runner; + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch("disable-cookie-encryption")) { + cookie_config::SetEnableCookieCrypto(false); + } std::unique_ptr cookie_store( content::CreateCookieStore(cookie_config)); @@ -541,6 +550,10 @@ void ProfileImplIOData:: // store. net::URLRequestContext* extensions_context = extensions_request_context(); + std::string domain; + if (nw::package()->root()->GetString(extensions::manifest_keys::kNWJSDomain, &domain)) { + extensions_context->set_cookie_store(main_request_context()->cookie_store()); + } else { content::CookieStoreConfig cookie_config( lazy_params_->extensions_cookie_path, lazy_params_->restore_old_session_cookies, @@ -551,6 +564,7 @@ void ProfileImplIOData:: cookie_config.channel_id_service = extensions_context->channel_id_service(); extensions_cookie_store_ = content::CreateCookieStore(cookie_config); extensions_context->set_cookie_store(extensions_cookie_store_.get()); + } } net::URLRequestContext* ProfileImplIOData::InitializeAppRequestContext( diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index a9a5998fdf673..dedfd16d6ac8c 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc @@ -4,6 +4,8 @@ #include "chrome/browser/profiles/profile_io_data.h" +#include "content/nw/src/policy_cert_verifier.h" + #include #include @@ -1139,15 +1141,14 @@ void ProfileIOData::Init( cert_verifier = std::make_unique( std::make_unique(verify_proc.get())); } -#elif defined(OS_LINUX) || defined(OS_MACOSX) +#elif 0 //defined(OS_LINUX) || defined(OS_MACOSX) cert_verifier = std::make_unique( std::make_unique( profile_params_->profile, net::CertVerifyProc::CreateDefault(), net::CreateCertVerifyProcBuiltin())); #else - cert_verifier = std::make_unique( - std::make_unique( - net::CertVerifyProc::CreateDefault())); + cert_verifier = std::make_unique(base::Closure()); + ((nw::PolicyCertVerifier*)cert_verifier.get())->InitializeOnIOThread(net::CertVerifyProc::CreateDefault()); #endif const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc index 3df598de7e9f4..5c8b7353eb885 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc @@ -11,6 +11,8 @@ #include "extensions/common/extension.h" #include "extensions/common/manifest.h" +#include "content/nw/src/common/shell_switches.h" + using extensions::Extension; using extensions::ProcessManager; @@ -39,6 +41,14 @@ bool ContextMenuContentTypePlatformApp::SupportsGroup(int group) { DCHECK(platform_app->is_platform_app()); +#if defined(NWJS_SDK) + bool enable_devtools = true; + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableDevTools)) + enable_devtools = false; +#endif + switch (group) { // Add undo/redo, cut/copy/paste etc for text fields. case ITEM_GROUP_EDITABLE: @@ -46,12 +56,10 @@ bool ContextMenuContentTypePlatformApp::SupportsGroup(int group) { return ContextMenuContentType::SupportsGroup(group); case ITEM_GROUP_CURRENT_EXTENSION: return true; +#if defined(NWJS_SDK) case ITEM_GROUP_DEVTOOLS_UNPACKED_EXT: - // Add dev tools for unpacked extensions. - return extensions::Manifest::IsUnpackedLocation( - platform_app->location()) || - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDebugPackedApps); + return enable_devtools; +#endif default: return false; } diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 21bb03f537bba..dd611cb044900 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc @@ -6,6 +6,8 @@ #include +#include "content/nw/src/common/shell_switches.h" + #include #include #include @@ -824,15 +826,25 @@ void RenderViewContextMenu::InitMenu() { AppendCurrentExtensionItems(); } +#if defined(NWJS_SDK) + bool enable_devtools = true; + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableDevTools)) + enable_devtools = false; + if (content_type_->SupportsGroup( ContextMenuContentType::ITEM_GROUP_DEVELOPER)) { + if (enable_devtools) AppendDeveloperItems(); } if (content_type_->SupportsGroup( ContextMenuContentType::ITEM_GROUP_DEVTOOLS_UNPACKED_EXT)) { + if (enable_devtools) AppendDevtoolsForUnpackedExtensions(); } +#endif if (content_type_->SupportsGroup( ContextMenuContentType::ITEM_GROUP_PRINT_PREVIEW)) { @@ -944,12 +956,15 @@ const Extension* RenderViewContextMenu::GetExtension() const { } std::string RenderViewContextMenu::GetTargetLanguage() const { +#if 0 std::unique_ptr prefs( ChromeTranslateClient::CreateTranslatePrefs(GetPrefs(browser_context_))); language::LanguageModel* language_model = LanguageModelFactory::GetForBrowserContext(browser_context_); return translate::TranslateManager::GetTargetLanguage(prefs.get(), language_model); +#endif + return ""; } void RenderViewContextMenu::AppendDeveloperItems() { @@ -1286,6 +1301,7 @@ void RenderViewContextMenu::AppendPageItems() { menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT); AppendMediaRouterItem(); +#if 0 if (TranslateService::IsTranslatableURL(params_.page_url)) { std::unique_ptr prefs( ChromeTranslateClient::CreateTranslatePrefs( @@ -1303,6 +1319,7 @@ void RenderViewContextMenu::AppendPageItems() { AddGoogleIconToLastMenuItem(&menu_model_); } } +#endif } void RenderViewContextMenu::AppendExitFullscreenItem() { @@ -1411,7 +1428,11 @@ void RenderViewContextMenu::AppendSearchProvider() { } void RenderViewContextMenu::AppendEditableItems() { - const bool use_spelling = !chrome::IsRunningInForcedAppMode(); + bool use_spelling = !chrome::IsRunningInForcedAppMode(); + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kEnableSpellChecking)) + use_spelling = false; if (use_spelling) AppendSpellingSuggestionItems(); @@ -1466,6 +1487,7 @@ void RenderViewContextMenu::AppendEditableItems() { } void RenderViewContextMenu::AppendLanguageSettings() { +#if 0 const bool use_spelling = !chrome::IsRunningInForcedAppMode(); if (!use_spelling) return; @@ -1484,6 +1506,7 @@ void RenderViewContextMenu::AppendLanguageSettings() { spelling_options_submenu_observer_->InitMenu(params_); observers_.AddObserver(spelling_options_submenu_observer_.get()); #endif +#endif } void RenderViewContextMenu::AppendSpellingSuggestionItems() { @@ -2142,6 +2165,9 @@ bool RenderViewContextMenu::IsDevCommandEnabled(int id) const { } bool RenderViewContextMenu::IsTranslateEnabled() const { +#if 1 + return false; +#else ChromeTranslateClient* chrome_translate_client = ChromeTranslateClient::FromWebContents(embedder_web_contents_); // If no |chrome_translate_client| attached with this WebContents or we're @@ -2168,6 +2194,7 @@ bool RenderViewContextMenu::IsTranslateEnabled() const { !target_lang.empty() && // Disable on the Instant Extended NTP. !search::IsInstantNTP(embedder_web_contents_); +#endif } bool RenderViewContextMenu::IsSaveLinkAsEnabled() const { @@ -2600,6 +2627,7 @@ void RenderViewContextMenu::ExecRouteMedia() { } void RenderViewContextMenu::ExecTranslate() { +#if 0 // A translation might have been triggered by the time the menu got // selected, do nothing in that case. ChromeTranslateClient* chrome_translate_client = @@ -2626,6 +2654,7 @@ void RenderViewContextMenu::ExecTranslate() { chrome_translate_client->GetTranslateManager(); DCHECK(manager); manager->TranslatePage(original_lang, target_lang, true); +#endif } void RenderViewContextMenu::ExecLanguageSettings(int event_flags) { diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc index e0fa371f0a8aa..e07d0888f2437 100644 --- a/chrome/browser/renderer_preferences_util.cc +++ b/chrome/browser/renderer_preferences_util.cc @@ -38,6 +38,8 @@ #include "ui/views/linux_ui/linux_ui.h" #endif +#include "content/nw/src/common/nw_content_common_hooks.h" + namespace { // Parses a string |range| with a port range in the form "-". @@ -169,6 +171,9 @@ void UpdateFromSystemSettings(content::RendererPreferences* prefs, prefs->plugin_fullscreen_allowed = pref_service->GetBoolean(prefs::kFullscreenAllowed); #endif + std::string user_agent; + if (nw::GetUserAgentFromManifest(&user_agent)) + prefs->user_agent_override = user_agent; } } // namespace renderer_preferences_util diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 0ba36ef347b80..7246b162da284 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd @@ -23,6 +23,7 @@ + @@ -87,6 +88,10 @@ + + + + diff --git a/chrome/browser/resources/empty.css b/chrome/browser/resources/empty.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/chrome/browser/resources/empty.html b/chrome/browser/resources/empty.html new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/chrome/browser/resources/empty.js b/chrome/browser/resources/empty.js new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/chrome/browser/resources/empty.json b/chrome/browser/resources/empty.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/chrome/browser/resources/empty.png b/chrome/browser/resources/empty.png new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/chrome/browser/resources/nwjs/default.js b/chrome/browser/resources/nwjs/default.js new file mode 100644 index 0000000000000..a5e1ce27fb418 --- /dev/null +++ b/chrome/browser/resources/nwjs/default.js @@ -0,0 +1,46 @@ +//console.log("NWJS/DEFAULT.JS"); +var manifest = chrome.runtime.getManifest(); +var options = {}; +var title = null; +if (manifest.window) { + if (manifest.window.id) + options.id = manifest.window.id; + options.innerBounds = {}; + if (manifest.window.frame === false) + options.frame = 'none'; + if (manifest.window.resizable === false) + options.resizable = false; + if (manifest.window.height) + options.innerBounds.height = manifest.window.height; + if (manifest.window.width) + options.innerBounds.width = manifest.window.width; + if (manifest.window.min_width) + options.innerBounds.minWidth = manifest.window.min_width; + if (manifest.window.max_width) + options.innerBounds.maxWidth = manifest.window.max_width; + if (manifest.window.min_height) + options.innerBounds.minHeight = manifest.window.min_height; + if (manifest.window.max_height) + options.innerBounds.maxHeight = manifest.window.max_height; + if (manifest.window.fullscreen === true) + options.state = 'fullscreen'; + if (manifest.window.show === false) + options.hidden = true; + if (manifest.window.show_in_taskbar === false) + options.show_in_taskbar = false; + if (manifest.window['always_on_top'] === true) + options.alwaysOnTop = true; + if (manifest.window['visible_on_all_workspaces'] === true) + options.visibleOnAllWorkspaces = true; + if (manifest.window.transparent) + options.alphaEnabled = true; + if (manifest.window.kiosk === true) + options.kiosk = true; + if (manifest.window.position) + options.position = manifest.window.position; + if (manifest.window.title) + options.title = manifest.window.title; +} + +chrome.app.window.create(manifest.main, options, function(win) { +}); diff --git a/chrome/browser/resources/nwjs_default_app/main.js b/chrome/browser/resources/nwjs_default_app/main.js new file mode 100644 index 0000000000000..4ee5538332f0b --- /dev/null +++ b/chrome/browser/resources/nwjs_default_app/main.js @@ -0,0 +1,7 @@ +var manifest = chrome.runtime.getManifest(); +var url = manifest.cmdlineUrl || 'nw_blank.html'; +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create( + url, + {'id': 'nwjs_default_app', 'height': 550, 'width': 750}); +}); diff --git a/chrome/browser/resources/nwjs_default_app/manifest.json b/chrome/browser/resources/nwjs_default_app/manifest.json new file mode 100644 index 0000000000000..1e9c9e219ebcd --- /dev/null +++ b/chrome/browser/resources/nwjs_default_app/manifest.json @@ -0,0 +1,17 @@ +{ + //id: aafddpmiffkameplnjkglahmbnbgidce + "key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgmO8NbDyu8AB/Cudz33l3kkgPbIeYaitcYgn4RBJdNRPjJ2sRy0icbVMyZjXhNV81vuH60ZO5PiBmVIp6v49Aq2RSkFVbwPw0y1Yo6UgATlaaEKEJV2VGrlQJaN12bGM/Dz8KGuHVGTbtqHS+B0QyQJMAbXLJ8HkmvJPlUQZf3QIDAQAB", + "name": "NWJS Default", + "version": "0.1", + "manifest_version": 2, + "description": "NWJS default app", + "app": { + "background": { + "scripts": [ "main.js" ] + } + }, + "permissions": [ + "node", "proxy", "" + ], + "display_in_launcher": false +} diff --git a/chrome/browser/resources/nwjs_default_app/nw_blank.html b/chrome/browser/resources/nwjs_default_app/nw_blank.html new file mode 100644 index 0000000000000..cda95d6c72fe9 --- /dev/null +++ b/chrome/browser/resources/nwjs_default_app/nw_blank.html @@ -0,0 +1,74 @@ + + + +nw.js + + + +

      +
      + nw.js v
      + Node v
      + Chromium
      + commit hash:
      +
      + + diff --git a/chrome/browser/resources/nwjs_newwin_app/main.js b/chrome/browser/resources/nwjs_newwin_app/main.js new file mode 100644 index 0000000000000..2b4a71ea6180f --- /dev/null +++ b/chrome/browser/resources/nwjs_newwin_app/main.js @@ -0,0 +1,7 @@ +var manifest = chrome.runtime.getManifest(); +var url = manifest.cmdlineUrl || 'nw_blank.html'; +chrome.app.runtime.onLaunched.addListener(function() { + console.log("NEWWIN MODE!"); + chrome.windows.create( + {'url': url, 'height': 550, 'width': 750}); +}); diff --git a/chrome/browser/resources/nwjs_newwin_app/manifest.json b/chrome/browser/resources/nwjs_newwin_app/manifest.json new file mode 100644 index 0000000000000..1e9c9e219ebcd --- /dev/null +++ b/chrome/browser/resources/nwjs_newwin_app/manifest.json @@ -0,0 +1,17 @@ +{ + //id: aafddpmiffkameplnjkglahmbnbgidce + "key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgmO8NbDyu8AB/Cudz33l3kkgPbIeYaitcYgn4RBJdNRPjJ2sRy0icbVMyZjXhNV81vuH60ZO5PiBmVIp6v49Aq2RSkFVbwPw0y1Yo6UgATlaaEKEJV2VGrlQJaN12bGM/Dz8KGuHVGTbtqHS+B0QyQJMAbXLJ8HkmvJPlUQZf3QIDAQAB", + "name": "NWJS Default", + "version": "0.1", + "manifest_version": 2, + "description": "NWJS default app", + "app": { + "background": { + "scripts": [ "main.js" ] + } + }, + "permissions": [ + "node", "proxy", "" + ], + "display_in_launcher": false +} diff --git a/chrome/browser/resources/nwjs_newwin_app/nw_blank.html b/chrome/browser/resources/nwjs_newwin_app/nw_blank.html new file mode 100644 index 0000000000000..cda95d6c72fe9 --- /dev/null +++ b/chrome/browser/resources/nwjs_newwin_app/nw_blank.html @@ -0,0 +1,74 @@ + + + +nw.js + + + +
      +

      NW.js

      +
      +
      + nw.js v
      + Node v
      + Chromium
      + commit hash:
      +
      + + diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js index 6ed1cb3cb1200..cf6421eceab36 100644 --- a/chrome/browser/resources/pdf/pdf.js +++ b/chrome/browser/resources/pdf/pdf.js @@ -712,7 +712,7 @@ PDFViewer.prototype = { message.data.url, Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB); } else { - this.navigator_.navigate(message.data.url, message.data.disposition); + this.navigator_.navigate(message.data.url, Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB); } break; case 'printPreviewLoaded': diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index b7a3a5148e300..b51b3912d9ffa 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js @@ -369,8 +369,9 @@ cr.define('print_preview', function() { */ init( isInAppKioskMode, systemDefaultDestinationId, - serializedDefaultDestinationSelectionRulesStr, recentDestinations) { + serializedDefaultDestinationSelectionRulesStr, recentDestinations, isInNWPrintMode) { this.pdfPrinterEnabled_ = !isInAppKioskMode; + this.isInNWPrintMode_ = isInNWPrintMode; this.systemDefaultDestinationId_ = systemDefaultDestinationId; this.createLocalPdfPrintDestination_(); @@ -401,6 +402,7 @@ cr.define('print_preview', function() { let extensionId = ''; let extensionName = ''; let foundDestination = false; + if (!this.isInNWPrintMode_) { // Run through the destinations forward. As soon as we find a // destination, don't select any future destinations, just mark // them recent. Otherwise, there is a race condition between selecting @@ -427,6 +429,7 @@ cr.define('print_preview', function() { extensionName); } } + } if (foundDestination && !this.useSystemDefaultAsDefault_) return; @@ -612,7 +615,7 @@ cr.define('print_preview', function() { * @private */ convertPreselectedToDestinationMatch_() { - if (this.isDestinationValid(this.selectedDestination_)) { + if (this.isDestinationValid(this.selectedDestination_) && !this.isInNWPrintMode_) { return this.createExactDestinationMatch_( this.selectedDestination_.origin, this.selectedDestination_.id); } diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index 2975eadf15237..392402eb4ff12 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js @@ -40,6 +40,7 @@ print_preview.LocalDestinationInfo; * printerName: string, * serializedAppStateStr: ?string, * serializedDefaultDestinationSelectionRulesStr: ?string, + * nwPrintMode: boolean, * }} * @see corresponding field name definitions in print_preview_handler.cc */ diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index 3702bf1cc83fd..55a94e0236749 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js @@ -280,6 +280,7 @@ cr.define('print_preview', function() { * @private */ this.isInAppKioskMode_ = false; + this.isInNWPrintMode_ = false; /** * Whether Print with System Dialog link should be hidden. Overrides the @@ -723,6 +724,7 @@ cr.define('print_preview', function() { this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode; this.isInAppKioskMode_ = settings.isInAppKioskMode; + this.isInNWPrintMode_ = settings.nwPrintMode; // The following components must be initialized in this order. this.appState_.init(settings.serializedAppStateStr); @@ -735,7 +737,7 @@ cr.define('print_preview', function() { this.destinationStore_.init( settings.isInAppKioskMode, settings.printerName, settings.serializedDefaultDestinationSelectionRulesStr, - this.appState_.recentDestinations || []); + this.appState_.recentDestinations || [], settings.nwPrintMode); this.appState_.setInitialized(); // This is only visible in the task manager. diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 0efe88ba1e189..2aebf8c13b0f8 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -4,6 +4,11 @@ #include "chrome/browser/sessions/session_service.h" +#include "content/nw/src/nw_content.h" +#include "extensions/browser/extension_system.h" +#include "extensions/browser/app_window/app_window_registry.h" +#include "chrome/browser/extensions/extension_service.h" + #include #include @@ -886,6 +891,24 @@ void SessionService::MaybeDeleteSessionOnlyData() { if (browser->profile() == profile()) return; } + std::string id = nw::GetMainExtensionId(); + base::FilePath path; + extensions::ExtensionSystem* extension_system = + extensions::ExtensionSystem::Get(ProfileManager::GetPrimaryUserProfile()); + if (!id.empty() && extension_system) { + ExtensionService* extension_service = + extension_system->extension_service(); + const extensions::Extension* extension = + extension_service->GetExtensionById(id, true); + if (extension) { + if (extensions::ProcessManager::Get(profile())->GetLazyKeepaliveCount(extension) > 0) + return; + } + //additional checking for NWJS#5355 + extensions::AppWindowRegistry* registry = extensions::AppWindowRegistry::Factory::GetForBrowserContext(profile(), false); + if (registry && !registry->app_windows().empty()) + return; + } DeleteSessionOnlyData(profile()); } diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index 169c990d2619a..e88863fb98a77 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc @@ -49,6 +49,8 @@ #include "chrome/common/chrome_switches.h" #include "chrome/grit/chrome_unscaled_resources.h" #include "components/version_info/version_info.h" +#include "content/nw/src/nw_base.h" +#include "content/nw/src/nw_package.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image_family.h" #include "url/gurl.h" @@ -213,6 +215,7 @@ DefaultWebClientState GetIsDefaultWebClient(const std::string& protocol) { // the .desktop extension. We cannot simply use argv[0] in this case, because // on the stable channel, the executable name is google-chrome-stable, but the // desktop file is google-chrome.desktop. +#if 0 std::string GetDesktopBaseName(const std::string& desktop_file_name) { static const char kDesktopExtension[] = ".desktop"; if (base::EndsWith(desktop_file_name, kDesktopExtension, @@ -222,6 +225,7 @@ std::string GetDesktopBaseName(const std::string& desktop_file_name) { } return desktop_file_name; } +#endif } // namespace @@ -593,6 +597,10 @@ namespace internal { std::string GetProgramClassName(const base::CommandLine& command_line, const std::string& desktop_file_name) { + // NW fix + // set WM_NAME to name of package.json + return nw::package()->GetName(); +#if 0 std::string class_name = shell_integration::GetDesktopBaseName(desktop_file_name); std::string user_data_dir = @@ -604,12 +612,18 @@ std::string GetProgramClassName(const base::CommandLine& command_line, return user_data_dir.empty() ? class_name : class_name + " (" + user_data_dir + ")"; +#endif } std::string GetProgramClassClass(const base::CommandLine& command_line, const std::string& desktop_file_name) { if (command_line.HasSwitch(switches::kWmClass)) return command_line.GetSwitchValueASCII(switches::kWmClass); + // NW fix + // set WM_CLASS as name in package.json and allowed to be overwritten + // with --class CLI parameter + return nw::package()->GetName(); +#if 0 std::string class_class = shell_integration::GetDesktopBaseName(desktop_file_name); if (!class_class.empty()) { @@ -617,6 +631,7 @@ std::string GetProgramClassClass(const base::CommandLine& command_line, class_class[0] = base::ToUpperASCII(class_class[0]); } return class_class; +#endif } } // namespace internal diff --git a/chrome/browser/spellchecker/spellcheck_factory.cc b/chrome/browser/spellchecker/spellcheck_factory.cc index 64b5243d510a4..329f8e3727257 100644 --- a/chrome/browser/spellchecker/spellcheck_factory.cc +++ b/chrome/browser/spellchecker/spellcheck_factory.cc @@ -77,7 +77,7 @@ void SpellcheckServiceFactory::RegisterProfilePrefs( spellcheck::prefs::kSpellCheckDictionary, l10n_util::GetStringUTF8(IDS_SPELLCHECK_DICTIONARY)); user_prefs->RegisterBooleanPref( - spellcheck::prefs::kSpellCheckUseSpellingService, false); + spellcheck::prefs::kSpellCheckUseSpellingService, true); #if defined(OS_ANDROID) uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS; #else diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc index 1956dfd0b697b..9246fbb4c4f4b 100644 --- a/chrome/browser/ssl/security_state_tab_helper.cc +++ b/chrome/browser/ssl/security_state_tab_helper.cc @@ -247,6 +247,7 @@ bool SecurityStateTabHelper::UsedPolicyInstalledCertificate() const { security_state::MaliciousContentStatus SecurityStateTabHelper::GetMaliciousContentStatus() const { +#if 0 content::NavigationEntry* entry = web_contents()->GetController().GetVisibleEntry(); if (!entry) @@ -299,6 +300,7 @@ SecurityStateTabHelper::GetMaliciousContentStatus() const { break; } } +#endif return security_state::MALICIOUS_CONTENT_STATUS_NONE; } diff --git a/chrome/browser/status_icons/status_icon.h b/chrome/browser/status_icons/status_icon.h index 0eaaf247f9733..291ca770fd60e 100644 --- a/chrome/browser/status_icons/status_icon.h +++ b/chrome/browser/status_icons/status_icon.h @@ -72,11 +72,11 @@ class StatusIcon { // thread to do it. Use sparingly. virtual void ForceVisible(); - protected: + public: // Invoked after a call to SetContextMenu() to let the platform-specific // subclass update the native context menu based on the new model. If NULL is // passed, subclass should destroy the native context menu. - virtual void UpdatePlatformContextMenu(StatusIconMenuModel* model) = 0; + virtual void UpdatePlatformContextMenu(ui::MenuModel* model) = 0; private: base::ObserverList observers_; diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index f1ad31c182550..6cb1df3b7026e 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc @@ -54,6 +54,7 @@ ChromeSubresourceFilterClient::~ChromeSubresourceFilterClient() {} void ChromeSubresourceFilterClient::MaybeAppendNavigationThrottles( content::NavigationHandle* navigation_handle, std::vector>* throttles) { +#if 0 safe_browsing::SafeBrowsingService* safe_browsing_service = g_browser_process->safe_browsing_service(); if (navigation_handle->IsInMainFrame() && safe_browsing_service) { @@ -65,6 +66,7 @@ void ChromeSubresourceFilterClient::MaybeAppendNavigationThrottles( content::BrowserThread::IO), safe_browsing_service->database_manager())); } +#endif auto* driver_factory = subresource_filter::ContentSubresourceFilterDriverFactory:: diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index 358dee3dc67e0..83ee7cdedbdbb 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc @@ -178,6 +178,7 @@ void SupervisedUserService::Init() { if (sync_service) sync_service->AddPreferenceProvider(this); +#if 0 std::string client_id = component_updater::SupervisedUserWhitelistInstaller:: ClientIdForProfilePath(profile_->GetPath()); whitelist_service_.reset(new SupervisedUserWhitelistService( @@ -186,6 +187,7 @@ void SupervisedUserService::Init() { whitelist_service_->AddSiteListsChangedCallback( base::Bind(&SupervisedUserService::OnSiteListsChanged, weak_ptr_factory_.GetWeakPtr())); +#endif SetActive(ProfileIsSupervised()); } diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index c514878fafe78..37d881fb5f690 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn @@ -543,8 +543,8 @@ split_static_library("ui") { "cocoa/toolbar/toolbar_view_cocoa.mm", "cocoa/translate/translate_bubble_bridge_views.h", "cocoa/translate/translate_bubble_bridge_views.mm", - "cocoa/translate/translate_bubble_controller.h", - "cocoa/translate/translate_bubble_controller.mm", + #"cocoa/translate/translate_bubble_controller.h", + #"cocoa/translate/translate_bubble_controller.mm", "cocoa/url_drop_target.h", "cocoa/url_drop_target.mm", "cocoa/vertical_gradient_view.h", @@ -729,13 +729,13 @@ split_static_library("ui") { "tab_ui_helper.h", "toolbar/chrome_toolbar_model_delegate.cc", "toolbar/chrome_toolbar_model_delegate.h", - "translate/language_combobox_model.cc", - "translate/language_combobox_model.h", - "translate/translate_bubble_model.h", - "translate/translate_bubble_model_impl.cc", - "translate/translate_bubble_model_impl.h", - "translate/translate_bubble_view_state_transition.cc", - "translate/translate_bubble_view_state_transition.h", + #"translate/language_combobox_model.cc", + #"translate/language_combobox_model.h", + #"translate/translate_bubble_model.h", + #"translate/translate_bubble_model_impl.cc", + #"translate/translate_bubble_model_impl.h", + #"translate/translate_bubble_view_state_transition.cc", + #"translate/translate_bubble_view_state_transition.h", "uninstall_browser_prompt.h", "view_ids.h", "web_contents_sizer.h", @@ -743,8 +743,8 @@ split_static_library("ui") { "webui/about_ui.h", "webui/chrome_web_ui_controller_factory.cc", "webui/chrome_web_ui_controller_factory.h", - "webui/components_ui.cc", - "webui/components_ui.h", + #"webui/components_ui.cc", + #"webui/components_ui.h", "webui/constrained_web_dialog_ui.cc", "webui/constrained_web_dialog_ui.h", "webui/cookies_tree_model_util.cc", @@ -759,8 +759,8 @@ split_static_library("ui") { "webui/download_internals/download_internals_ui.h", "webui/download_internals/download_internals_ui_message_handler.cc", "webui/download_internals/download_internals_ui_message_handler.h", - "webui/engagement/site_engagement_ui.cc", - "webui/engagement/site_engagement_ui.h", + #"webui/engagement/site_engagement_ui.cc", + #"webui/engagement/site_engagement_ui.h", "webui/favicon_source.cc", "webui/favicon_source.h", "webui/fileicon_source.cc", @@ -769,8 +769,8 @@ split_static_library("ui") { "webui/flags_ui.h", "webui/gcm_internals_ui.cc", "webui/gcm_internals_ui.h", - "webui/interstitials/interstitial_ui.cc", - "webui/interstitials/interstitial_ui.h", + #"webui/interstitials/interstitial_ui.cc", + #"webui/interstitials/interstitial_ui.h", "webui/interventions_internals/interventions_internals_page_handler.cc", "webui/interventions_internals/interventions_internals_page_handler.h", "webui/interventions_internals/interventions_internals_ui.cc", @@ -835,14 +835,14 @@ split_static_library("ui") { "webui/task_scheduler_internals/task_scheduler_internals_ui.h", "webui/test_files_request_filter.cc", "webui/test_files_request_filter.h", - "webui/translate_internals/translate_internals_handler.cc", - "webui/translate_internals/translate_internals_handler.h", - "webui/translate_internals/translate_internals_ui.cc", - "webui/translate_internals/translate_internals_ui.h", - "webui/usb_internals/usb_internals_page_handler.cc", - "webui/usb_internals/usb_internals_page_handler.h", - "webui/usb_internals/usb_internals_ui.cc", - "webui/usb_internals/usb_internals_ui.h", + #"webui/translate_internals/translate_internals_handler.cc", + #"webui/translate_internals/translate_internals_handler.h", + #"webui/translate_internals/translate_internals_ui.cc", + #"webui/translate_internals/translate_internals_ui.h", + #"webui/usb_internals/usb_internals_page_handler.cc", + #"webui/usb_internals/usb_internals_page_handler.h", + #"webui/usb_internals/usb_internals_ui.cc", + #"webui/usb_internals/usb_internals_ui.h", "webui/user_actions/user_actions_ui.cc", "webui/user_actions/user_actions_ui.h", "webui/user_actions/user_actions_ui_handler.cc", @@ -907,7 +907,7 @@ split_static_library("ui") { "//chrome/browser/engagement:mojo_bindings", "//chrome/browser/media:mojo_bindings", "//chrome/browser/profiling_host", - "//chrome/browser/safe_browsing", + #"//chrome/browser/safe_browsing", "//chrome/browser/ssl:proto", "//chrome/browser/ui/webui/bluetooth_internals", "//chrome/browser/ui/webui/interventions_internals:mojo_bindings", @@ -1568,18 +1568,18 @@ split_static_library("ui") { "webui/identity_internals_ui.h", "webui/inspect_ui.cc", "webui/inspect_ui.h", - "webui/md_bookmarks/bookmarks_message_handler.cc", - "webui/md_bookmarks/bookmarks_message_handler.h", - "webui/md_bookmarks/md_bookmarks_ui.cc", - "webui/md_bookmarks/md_bookmarks_ui.h", - "webui/md_downloads/downloads_list_tracker.cc", - "webui/md_downloads/downloads_list_tracker.h", - "webui/md_downloads/md_downloads_dom_handler.cc", - "webui/md_downloads/md_downloads_dom_handler.h", - "webui/md_downloads/md_downloads_ui.cc", - "webui/md_downloads/md_downloads_ui.h", - "webui/md_history_ui.cc", - "webui/md_history_ui.h", + #"webui/md_bookmarks/bookmarks_message_handler.cc", + #"webui/md_bookmarks/bookmarks_message_handler.h", + #"webui/md_bookmarks/md_bookmarks_ui.cc", + #"webui/md_bookmarks/md_bookmarks_ui.h", + #"webui/md_downloads/downloads_list_tracker.cc", + #"webui/md_downloads/downloads_list_tracker.h", + #"webui/md_downloads/md_downloads_dom_handler.cc", + #"webui/md_downloads/md_downloads_dom_handler.h", + #"webui/md_downloads/md_downloads_ui.cc", + #"webui/md_downloads/md_downloads_ui.h", + #"webui/md_history_ui.cc", + #"webui/md_history_ui.h", "webui/media_router/media_router_dialog_controller_webui_impl.cc", "webui/media_router/media_router_dialog_controller_webui_impl.h", "webui/media_router/media_router_internals_ui.cc", @@ -1712,6 +1712,16 @@ split_static_library("ui") { "zoom/chrome_zoom_level_prefs.cc", "zoom/chrome_zoom_level_prefs.h", ] + + if (!nwjs_sdk) { + sources -= [ + "webui/about_ui.cc", + "webui/about_ui.h", + "webui/extensions/extensions_ui.cc", + "webui/extensions/extensions_ui.h", + ] + } + deps += [ "//chrome/app/vector_icons", "//chrome/browser:theme_properties", @@ -2250,14 +2260,14 @@ split_static_library("ui") { "webui/signin/signin_web_dialog_ui.h", "webui/signin/sync_confirmation_handler.cc", "webui/signin/sync_confirmation_handler.h", - "webui/signin/sync_confirmation_ui.cc", - "webui/signin/sync_confirmation_ui.h", + #"webui/signin/sync_confirmation_ui.cc", + #"webui/signin/sync_confirmation_ui.h", "webui/signin/user_manager_screen_handler.cc", "webui/signin/user_manager_screen_handler.h", - "webui/welcome_handler.cc", - "webui/welcome_handler.h", - "webui/welcome_ui.cc", - "webui/welcome_ui.h", + #"webui/welcome_handler.cc", + #"webui/welcome_handler.h", + #"webui/welcome_ui.cc", + #"webui/welcome_ui.h", ] if (!is_mac || mac_views_browser) { @@ -2283,8 +2293,8 @@ split_static_library("ui") { if (is_win || is_mac || is_chromeos) { sources += [ - "webui/cast/cast_ui.cc", - "webui/cast/cast_ui.h", + #"webui/cast/cast_ui.cc", + #"webui/cast/cast_ui.h", ] } @@ -2638,10 +2648,10 @@ split_static_library("ui") { "webui/settings/chrome_cleanup_handler.cc", "webui/settings/chrome_cleanup_handler.h", "webui/settings_utils_win.cc", - "webui/welcome_win10_handler.cc", - "webui/welcome_win10_handler.h", - "webui/welcome_win10_ui.cc", - "webui/welcome_win10_ui.h", + #"webui/welcome_win10_handler.cc", + #"webui/welcome_win10_handler.h", + #"webui/welcome_win10_ui.cc", + #"webui/welcome_win10_ui.h", ] public_deps += [ "//ui/views", @@ -2830,7 +2840,7 @@ split_static_library("ui") { "views/cookie_info_view.h", "views/device_chooser_content_view.cc", "views/device_chooser_content_view.h", - "views/download/download_danger_prompt_views.cc", + #"views/download/download_danger_prompt_views.cc", "views/elevation_icon_setter.cc", "views/elevation_icon_setter.h", "views/exclusive_access_bubble_views.cc", @@ -2979,8 +2989,8 @@ split_static_library("ui") { "views/task_manager_view.h", "views/toolbar/toolbar_actions_bar_bubble_views.cc", "views/toolbar/toolbar_actions_bar_bubble_views.h", - "views/translate/translate_bubble_view.cc", - "views/translate/translate_bubble_view.h", + #"views/translate/translate_bubble_view.cc", + #"views/translate/translate_bubble_view.h", "views/update_recommended_message_box.cc", "views/update_recommended_message_box.h", ] @@ -3279,8 +3289,8 @@ split_static_library("ui") { "views/toolbar/toolbar_view.cc", "views/toolbar/toolbar_view.h", "views/touch_uma/touch_uma.h", - "views/translate/translate_icon_view.cc", - "views/translate/translate_icon_view.h", + #"views/translate/translate_icon_view.cc", + #"views/translate/translate_icon_view.h", "views/webshare/webshare_target_picker_view.cc", "views/webshare/webshare_target_picker_view.h", "views_mode_controller.cc", diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc index 1570f2c0fb96a..d2e5ad1e68045 100644 --- a/chrome/browser/ui/apps/chrome_app_delegate.cc +++ b/chrome/browser/ui/apps/chrome_app_delegate.cc @@ -8,6 +8,13 @@ #include #include "base/macros.h" + +#include "chrome/browser/sessions/session_tab_helper.h" +#include "chrome/browser/extensions/tab_helper.h" +#include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/external_protocol/external_protocol_observer.h" + #include "base/strings/stringprintf.h" #include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/chrome_notification_types.h" @@ -51,10 +58,16 @@ #include "chrome/browser/printing/printing_init.h" #endif +#include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/autofill/chrome_autofill_client.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "chrome/browser/ui/prefs/prefs_tab_helper.h" + namespace { // Time to wait for an app window to show before allowing Chrome to quit. -int kAppWindowFirstShowTimeoutSeconds = 10; +//int kAppWindowFirstShowTimeoutSeconds = 10; bool disable_external_open_for_testing_ = false; @@ -69,7 +82,7 @@ content::WebContents* OpenURLFromTabInternal( if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { new_tab_params.disposition = WindowOpenDisposition::NEW_BACKGROUND_TAB; } else { - new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + new_tab_params.disposition = WindowOpenDisposition::NEW_POPUP; new_tab_params.window_action = NavigateParams::SHOW_WINDOW; } @@ -178,6 +191,7 @@ ChromeAppDelegate::ChromeAppDelegate(bool keep_alive) is_hidden_(true), for_lock_screen_app_(false), new_window_contents_delegate_(new NewWindowContentsDelegate()), + web_contents_(nullptr), weak_factory_(this) { if (keep_alive) { keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::CHROME_APP_DELEGATE, @@ -200,15 +214,37 @@ void ChromeAppDelegate::DisableExternalOpenForTesting() { void ChromeAppDelegate::InitWebContents(content::WebContents* web_contents) { data_use_measurement::DataUseWebContentsObserver::CreateForWebContents( web_contents); + web_contents_ = web_contents; + favicon::CreateContentFaviconDriverForWebContents(web_contents); #if BUILDFLAG(ENABLE_PRINTING) printing::InitializePrinting(web_contents); #endif + // ZoomController comes before common tab helpers since ChromeExtensionWebContentsObserver + // may want to register as a ZoomObserver with it. + zoom::ZoomController::CreateForWebContents(web_contents); + +#if 1 + extensions::TabHelper::CreateForWebContents(web_contents); +#else + SessionTabHelper::CreateForWebContents(web_contents); + extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( web_contents); - - zoom::ZoomController::CreateForWebContents(web_contents); +#endif + autofill::ChromeAutofillClient::CreateForWebContents(web_contents); + autofill::ContentAutofillDriverFactory::CreateForWebContentsAndDelegate( + web_contents, + autofill::ChromeAutofillClient::FromWebContents(web_contents), + g_browser_process->GetApplicationLocale(), + autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER); + ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( + web_contents, + autofill::ChromeAutofillClient::FromWebContents(web_contents)); + ManagePasswordsUIController::CreateForWebContents(web_contents); + PrefsTabHelper::CreateForWebContents(web_contents); + ExternalProtocolObserver::CreateForWebContents(web_contents); } void ChromeAppDelegate::RenderViewCreated( @@ -248,12 +284,14 @@ void ChromeAppDelegate::AddNewContents( const gfx::Rect& initial_rect, bool user_gesture) { if (!disable_external_open_for_testing_) { +#if 0 // We don't really want to open a window for |new_contents|, but we need to // capture its intended navigation. Here we give ownership to the // NewWindowContentsDelegate, which will dispose of the contents once // a navigation is captured. new_window_contents_delegate_->BecomeOwningDeletageOf( std::move(new_contents)); +#endif return; } @@ -333,6 +371,7 @@ void ChromeAppDelegate::SetTerminatingCallback(const base::Closure& callback) { void ChromeAppDelegate::OnHide() { is_hidden_ = true; +#if 0 if (has_been_shown_) { keep_alive_.reset(); return; @@ -345,13 +384,16 @@ void ChromeAppDelegate::OnHide() { base::BindOnce(&ChromeAppDelegate::RelinquishKeepAliveAfterTimeout, weak_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kAppWindowFirstShowTimeoutSeconds)); +#endif } void ChromeAppDelegate::OnShow() { has_been_shown_ = true; is_hidden_ = false; +#if 0 keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::CHROME_APP_DELEGATE, KeepAliveRestartOption::DISABLED)); +#endif } bool ChromeAppDelegate::TakeFocus(content::WebContents* web_contents, diff --git a/chrome/browser/ui/apps/chrome_app_delegate.h b/chrome/browser/ui/apps/chrome_app_delegate.h index bdebbac972c68..35eb8a4e4ab61 100644 --- a/chrome/browser/ui/apps/chrome_app_delegate.h +++ b/chrome/browser/ui/apps/chrome_app_delegate.h @@ -87,6 +87,7 @@ class ChromeAppDelegate : public extensions::AppDelegate, std::unique_ptr new_window_contents_delegate_; base::Closure terminating_callback_; content::NotificationRegistrar registrar_; + content::WebContents* web_contents_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeAppDelegate); diff --git a/chrome/browser/ui/apps/chrome_app_window_client.cc b/chrome/browser/ui/apps/chrome_app_window_client.cc index c56f36125321f..0a4a47a57d71f 100644 --- a/chrome/browser/ui/apps/chrome_app_window_client.cc +++ b/chrome/browser/ui/apps/chrome_app_window_client.cc @@ -18,6 +18,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" #endif +#include "content/nw/src/nw_content.h" // TODO(jamescook): We probably shouldn't compile this class at all on Android. // See http://crbug.com/343612 @@ -44,8 +45,10 @@ extensions::AppWindow* ChromeAppWindowClient::CreateAppWindow( #if defined(OS_ANDROID) return NULL; #else - return new extensions::AppWindow(context, new ChromeAppDelegate(true), + extensions::AppWindow* ret = new extensions::AppWindow(context, new ChromeAppDelegate(true), extension); + nw::CreateAppWindowHook(ret); + return ret; #endif } diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 077d7cd558666..f69c75b43b8ec 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc @@ -356,6 +356,9 @@ bool ChromeAutofillClient::IsContextSecure() { if (!navigation_entry) return false; + if (navigation_entry->GetURL().SchemeIs("chrome-extension")) + return true; + ssl_status = navigation_entry->GetSSL(); // Note: If changing the implementation below, also change // AwAutofillClient::IsContextSecure. See crbug.com/505388 diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 9604d3429fea3..c1a3f730e52ec 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -296,12 +296,12 @@ const extensions::Extension* GetExtensionForOrigin( // Browser, CreateParams: Browser::CreateParams::CreateParams(Profile* profile, bool user_gesture) - : CreateParams(TYPE_TABBED, profile, user_gesture) {} + : CreateParams(TYPE_POPUP, profile, user_gesture) {} Browser::CreateParams::CreateParams(Type type, Profile* profile, bool user_gesture) - : type(type), profile(profile), user_gesture(user_gesture) {} + : type(TYPE_POPUP), profile(profile), user_gesture(user_gesture) {} Browser::CreateParams::CreateParams(const CreateParams& other) = default; @@ -1041,7 +1041,8 @@ void Browser::TabDetachedAt(WebContents* contents, int index, bool was_active) { void Browser::TabDeactivated(WebContents* contents) { exclusive_access_manager_->OnTabDeactivated(contents); - SearchTabHelper::FromWebContents(contents)->OnTabDeactivated(); + if (SearchTabHelper::FromWebContents(contents)) + SearchTabHelper::FromWebContents(contents)->OnTabDeactivated(); // Save what the user's currently typing, so it can be restored when we // switch back to this tab. @@ -1131,7 +1132,7 @@ void Browser::ActiveTabChanged(WebContents* old_contents, base::TimeTicks::Now()); } - SearchTabHelper::FromWebContents(new_contents)->OnTabActivated(); + //SearchTabHelper::FromWebContents(new_contents)->OnTabActivated(); } void Browser::TabMoved(WebContents* contents, @@ -1683,7 +1684,7 @@ void Browser::WebContentsCreated(WebContents* source_contents, int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - WebContents* new_contents) { + WebContents* new_contents, const base::string16& nw_window_manifest) { // Adopt the WebContents now, so all observers are in place, as the network // requests for its initial navigation will start immediately. The WebContents // will later be inserted into this browser using Browser::Navigate via @@ -2176,11 +2177,13 @@ void Browser::OnExtensionUnloaded(content::BrowserContext* browser_context, void Browser::OnIsPageTranslatedChanged(content::WebContents* source) { DCHECK(source); +#if 0 if (tab_strip_model_->GetActiveWebContents() == source) { window_->SetTranslateIconToggled( ChromeTranslateClient::FromWebContents( source)->GetLanguageState().IsPageTranslated()); } +#endif } void Browser::OnTranslateEnabledChanged(content::WebContents* source) { @@ -2410,14 +2413,14 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { WebContentsModalDialogManager::FromWebContents(web_contents)-> SetDelegate(delegate); CoreTabHelper::FromWebContents(web_contents)->set_delegate(delegate); - translate::ContentTranslateDriver& content_translate_driver = - ChromeTranslateClient::FromWebContents(web_contents)->translate_driver(); + //translate::ContentTranslateDriver& content_translate_driver = + // ChromeTranslateClient::FromWebContents(web_contents)->translate_driver(); if (delegate) { zoom::ZoomController::FromWebContents(web_contents)->AddObserver(this); - content_translate_driver.AddObserver(this); + //content_translate_driver.AddObserver(this); } else { zoom::ZoomController::FromWebContents(web_contents)->RemoveObserver(this); - content_translate_driver.RemoveObserver(this); + //content_translate_driver.RemoveObserver(this); } } diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index f1e35a49c9cde..79bc68bb42e9e 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h @@ -628,7 +628,8 @@ class Browser : public TabStripModelObserver, int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - content::WebContents* new_contents) override; + content::WebContents* new_contents, + const base::string16& nw_window_manifest) override; void RendererUnresponsive( content::WebContents* source, content::RenderWidgetHost* render_widget_host) override; diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 005e8e45b957f..05d2ee53a1e2a 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc @@ -129,6 +129,7 @@ namespace { const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3"; +#if 0 translate::TranslateBubbleUiEvent TranslateBubbleResultToUiEvent( ShowTranslateBubbleResult result) { switch (result) { @@ -154,6 +155,7 @@ translate::TranslateBubbleUiEvent TranslateBubbleResultToUiEvent( BUBBLE_NOT_SHOWN_EDITABLE_FIELD_IS_ACTIVE; } } +#endif } // namespace @@ -358,6 +360,7 @@ int GetContentRestrictions(const Browser* browser) { } void NewEmptyWindow(Profile* profile) { +#if 0 bool incognito = profile->IsOffTheRecord(); PrefService* prefs = profile->GetPrefs(); if (incognito) { @@ -385,6 +388,7 @@ void NewEmptyWindow(Profile* profile) { OpenEmptyWindow(profile->GetOriginalProfile()); } } +#endif } Browser* OpenEmptyWindow(Profile* profile) { @@ -842,6 +846,7 @@ void SaveCreditCard(Browser* browser) { } void Translate(Browser* browser) { +#if 0 if (!browser->window()->IsActive()) return; @@ -863,6 +868,7 @@ void Translate(Browser* browser) { web_contents, step, translate::TranslateErrors::NONE, true); if (result != ShowTranslateBubbleResult::SUCCESS) translate::ReportUiAction(TranslateBubbleResultToUiEvent(result)); +#endif } void ManagePasswordsForPage(Browser* browser) { diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index 6db6830048933..1d51f3c8d0e31 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc @@ -232,7 +232,8 @@ void BrowserList::PostTryToCloseBrowserWindow( // static void BrowserList::MoveBrowsersInWorkspaceToFront( const std::string& new_workspace) { - DCHECK(!new_workspace.empty()); + if(new_workspace.empty()) + return; BrowserList* instance = GetInstance(); diff --git a/chrome/browser/ui/chrome_bubble_manager.cc b/chrome/browser/ui/chrome_bubble_manager.cc index b37180064498e..a8124715a3a77 100644 --- a/chrome/browser/ui/chrome_bubble_manager.cc +++ b/chrome/browser/ui/chrome_bubble_manager.cc @@ -111,13 +111,15 @@ static void LogBubbleCloseReason(BubbleReference bubble, ChromeBubbleManager::ChromeBubbleManager(TabStripModel* tab_strip_model) : tab_strip_model_(tab_strip_model) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(tab_strip_model_); - tab_strip_model_->AddObserver(this); + //DCHECK(tab_strip_model_); + if (tab_strip_model_) + tab_strip_model_->AddObserver(this); AddBubbleManagerObserver(&chrome_bubble_metrics_); } ChromeBubbleManager::~ChromeBubbleManager() { - tab_strip_model_->RemoveObserver(this); + if (tab_strip_model_) + tab_strip_model_->RemoveObserver(this); // Finalize requests before removing the BubbleManagerObserver so it can // collect metrics when closing any open bubbles. diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index 0dc6fdc2cf447..250ec851d1de1 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc @@ -65,7 +65,7 @@ using base::UserMetricsAction; namespace chrome { namespace { -const char kHashMark[] = "#"; +//const char kHashMark[] = "#"; void OpenBookmarkManagerForNode(Browser* browser, int64_t node_id) { GURL url = GURL(kChromeUIBookmarksURL) @@ -141,6 +141,7 @@ void ShowHelpImpl(Browser* browser, Profile* profile, HelpSource source) { #endif } +#if 0 std::string GenerateContentSettingsExceptionsSubPage(ContentSettingsType type) { // In MD Settings, the exceptions no longer have a separate subpage. // This list overrides the group names defined in site_settings_helper for the @@ -170,6 +171,7 @@ std::string GenerateContentSettingsExceptionsSubPage(ContentSettingsType type) { return std::string(kContentSettingsSubPage) + "/" + content_type_path; } +#endif void ShowSiteSettingsImpl(Browser* browser, Profile* profile, const GURL& url) { // If a valid non-file origin, open a settings page specific to the current @@ -332,15 +334,19 @@ void ShowSettingsSubPageInTabbedBrowser(Browser* browser, void ShowContentSettingsExceptions(Browser* browser, ContentSettingsType content_settings_type) { +#if 0 ShowSettingsSubPage( browser, GenerateContentSettingsExceptionsSubPage(content_settings_type)); +#endif } void ShowContentSettingsExceptionsForProfile( Profile* profile, ContentSettingsType content_settings_type) { +#if 0 ShowSettingsSubPageForProfile( profile, GenerateContentSettingsExceptionsSubPage(content_settings_type)); +#endif } void ShowSiteSettings(Browser* browser, const GURL& url) { @@ -354,10 +360,12 @@ void ShowSiteSettings(Profile* profile, const GURL& url) { void ShowContentSettings(Browser* browser, ContentSettingsType content_settings_type) { +#if 0 ShowSettingsSubPage( browser, kContentSettingsSubPage + std::string(kHashMark) + site_settings::ContentSettingsTypeToGroupName(content_settings_type)); +#endif } void ShowClearBrowsingDataDialog(Browser* browser) { diff --git a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm index 1da50bbb78bbd..24f446626bf42 100644 --- a/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm +++ b/chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm @@ -25,6 +25,11 @@ using extensions::Extension; +#include "chrome/browser/devtools/devtools_window.h" + +#include "content/nw/src/api/menu/menu.h" +#include "content/nw/src/common/shell_switches.h" + namespace { // When an app window loses main status, AppKit may make another app window main @@ -76,6 +81,7 @@ void AddDuplicateItem(NSMenuItem* top_level_item, [[top_level_item submenu] addItem:item]; } +#if 0 // Finds an item with |item_tag| and removes it from the submenu of // |top_level_item|. void RemoveMenuItemWithTag(NSMenuItem* top_level_item, @@ -133,6 +139,7 @@ void SetItemWithTagVisible(NSMenuItem* top_level_item, [alternate_item setHidden:!visible]; [menu_item setHidden:!visible]; } +#endif // Return the Extension (if any) associated with the given window. If it is not // a platform app nor hosted app, but it is a browser, |is_browser| will be set @@ -212,6 +219,7 @@ void SetAppCyclesWindows(const std::string& app_id, int sequence_number) { [[NSApp keyWindow] makeKeyAndOrderFront:nil]; } +#if 0 // Sets the window cycle list to Chrome browser windows only. void SetChromeCyclesWindows(int sequence_number) { if (g_window_cycle_sequence_number != sequence_number) @@ -227,6 +235,7 @@ void SetChromeCyclesWindows(int sequence_number) { if (any_change) [[NSApp keyWindow] makeKeyAndOrderFront:nil]; } +#endif } // namespace @@ -355,6 +364,7 @@ - (void)quitCurrentPlatformApp; - (void)hideCurrentPlatformApp; // If the currently focused window belongs to a platform app, focus the app. - (void)focusCurrentPlatformApp; +- (void)showDevtools; @end @implementation AppShimMenuController @@ -394,6 +404,7 @@ - (void)buildAppMenuItems { resourceId:IDS_EXIT_MAC action:@selector(quitCurrentPlatformApp) keyEquivalent:@"q"]); +#if 0 newDoppelganger_.reset([[DoppelgangerMenuItem alloc] initWithController:self menuTag:IDC_FILE_MENU @@ -418,6 +429,7 @@ - (void)buildAppMenuItems { resourceId:0 action:nil keyEquivalent:@"o"]); +#endif allToFrontDoppelganger_.reset([[DoppelgangerMenuItem alloc] initWithController:self menuTag:IDC_WINDOW_MENU @@ -441,18 +453,21 @@ - (void)buildAppMenuItems { [appMenu addItem:[NSMenuItem separatorItem]]; [appMenu addItem:[quitDoppelganger_ menuItem]]; +#if 0 // File menu. fileMenuItem_.reset([NewTopLevelItemFrom(IDC_FILE_MENU) retain]); [[fileMenuItem_ submenu] addItem:[newDoppelganger_ menuItem]]; [[fileMenuItem_ submenu] addItem:[openDoppelganger_ menuItem]]; [[fileMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; [[fileMenuItem_ submenu] addItem:[closeWindowDoppelganger_ menuItem]]; +#endif // Edit menu. We copy the menu because the last two items, "Start Dictation" // and "Special Characters" are added by OSX, so we can't copy them // explicitly. editMenuItem_.reset([[[NSApp mainMenu] itemWithTag:IDC_EDIT_MENU] copy]); +#if 0 // View menu. Remove "Always Show Bookmark Bar" and separator. viewMenuItem_.reset([[[NSApp mainMenu] itemWithTag:IDC_VIEW_MENU] copy]); RemoveMenuItemWithTag(viewMenuItem_, IDC_SHOW_BOOKMARK_BAR, YES); @@ -462,12 +477,34 @@ - (void)buildAppMenuItems { AddDuplicateItem(historyMenuItem_, IDC_HISTORY_MENU, IDC_BACK); AddDuplicateItem(historyMenuItem_, IDC_HISTORY_MENU, IDC_FORWARD); +#endif // Window menu. windowMenuItem_.reset([NewTopLevelItemFrom(IDC_WINDOW_MENU) retain]); AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MINIMIZE_WINDOW); AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MAXIMIZE_WINDOW); [[windowMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; [[windowMenuItem_ submenu] addItem:[allToFrontDoppelganger_ menuItem]]; + +#if defined(NWJS_SDK) + bool enable_devtools = true; + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableDevTools)) + enable_devtools = false; + + if (enable_devtools) { + [[windowMenuItem_ submenu] setAutoenablesItems:NO]; + NSMenuItem* item = [[NSMenuItem alloc] + initWithTitle:@"Devtools" + action:@selector(showDevtools) + keyEquivalent:@"i"]; + [item setTag:IDC_DEV_TOOLS_CONSOLE]; + [item setTarget:self]; + [item setEnabled:YES]; + [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask]; + [[windowMenuItem_ submenu] addItem:item]; + } +#endif } - (void)registerEventHandlers { @@ -499,8 +536,17 @@ - (void)windowMainStatusChanged:(NSNotification*)notification { const Extension* extension = GetExtensionForNSWindow(window, &is_browser); // Ignore is_browser: if a window becomes main that does not belong to an // extension or browser, treat it the same as switching to a browser. - if (extension) + + extensions::AppWindow* appWindow = + AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( + window); + if (extension) { + if (appWindow && appWindow->menu_) { + [NSApp setMainMenu:appWindow->menu_->menu_]; + return; + } [self appBecameMain:extension]; + } else [self chromeBecameMain]; } else if ([name isEqualToString:NSWindowDidResignMainNotification]) { @@ -531,7 +577,12 @@ - (void)appBecameMain:(const Extension*)app { return; if (!appId_.empty()) - [self removeMenuItems]; + return; + // #4591: when app sets menubar and launch another chrome app, + // removeMenuItems will try to remove appmenuitem which isn't + // in the main menu; then app will crash. + // so after this function runs once, we just do nothing and return here + //[self removeMenuItems]; appId_ = app->id(); [self addMenuItems:app]; @@ -543,6 +594,7 @@ - (void)appBecameMain:(const Extension*)app { } - (void)chromeBecameMain { +#if 0 if (appId_.empty()) return; @@ -553,6 +605,7 @@ - (void)chromeBecameMain { FROM_HERE, base::Bind(&SetChromeCyclesWindows, ++g_window_cycle_sequence_number)); } +#endif } - (void)addMenuItems:(const Extension*)app { @@ -567,14 +620,15 @@ - (void)addMenuItems:(const Extension*)app { [aboutDoppelganger_ enableForApp:app]; [hideDoppelganger_ enableForApp:app]; [quitDoppelganger_ enableForApp:app]; - [newDoppelganger_ enableForApp:app]; - [openDoppelganger_ enableForApp:app]; - [closeWindowDoppelganger_ enableForApp:app]; + //[newDoppelganger_ enableForApp:app]; + //[openDoppelganger_ enableForApp:app]; + //[closeWindowDoppelganger_ enableForApp:app]; [appMenuItem_ setTitle:base::SysUTF8ToNSString(appId_)]; [[appMenuItem_ submenu] setTitle:title]; [mainMenu addItem:appMenuItem_]; +#if 0 [mainMenu addItem:fileMenuItem_]; SetItemWithTagVisible(editMenuItem_, @@ -582,23 +636,28 @@ - (void)addMenuItems:(const Extension*)app { app->is_hosted_app(), true); SetItemWithTagVisible(editMenuItem_, IDC_FIND_MENU, app->is_hosted_app(), false); +#endif [mainMenu addItem:editMenuItem_]; +#if 0 if (app->is_hosted_app()) { [mainMenu addItem:viewMenuItem_]; [mainMenu addItem:historyMenuItem_]; } +#endif [mainMenu addItem:windowMenuItem_]; } - (void)removeMenuItems { NSMenu* mainMenu = [NSApp mainMenu]; [mainMenu removeItem:appMenuItem_]; - [mainMenu removeItem:fileMenuItem_]; + //[mainMenu removeItem:fileMenuItem_]; +#if 0 if ([mainMenu indexOfItem:viewMenuItem_] >= 0) [mainMenu removeItem:viewMenuItem_]; if ([mainMenu indexOfItem:historyMenuItem_] >= 0) [mainMenu removeItem:historyMenuItem_]; +#endif [mainMenu removeItem:editMenuItem_]; [mainMenu removeItem:windowMenuItem_]; @@ -609,9 +668,9 @@ - (void)removeMenuItems { [aboutDoppelganger_ disable]; [hideDoppelganger_ disable]; [quitDoppelganger_ disable]; - [newDoppelganger_ disable]; - [openDoppelganger_ disable]; - [closeWindowDoppelganger_ disable]; + //[newDoppelganger_ disable]; + //[openDoppelganger_ disable]; + //[closeWindowDoppelganger_ disable]; } - (void)quitCurrentPlatformApp { @@ -619,7 +678,7 @@ - (void)quitCurrentPlatformApp { AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( [NSApp keyWindow]); if (appWindow) { - apps::ExtensionAppShimHandler::QuitAppForWindow(appWindow); + apps::ExtensionAppShimHandler::QuitAppForWindow(appWindow, true); } else { Browser* browser = chrome::FindBrowserWithWindow([NSApp keyWindow]); const Extension* extension = @@ -654,4 +713,12 @@ - (void)focusCurrentPlatformApp { apps::ExtensionAppShimHandler::FocusAppForWindow(appWindow); } +- (void)showDevtools { + extensions::AppWindow* appWindow = + AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile( + [NSApp keyWindow]); + if (appWindow) + DevToolsWindow::OpenDevToolsWindow(appWindow->web_contents()); +} + @end diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h index f82d3b8876363..60eac3a36b2af 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h @@ -46,6 +46,7 @@ class SkRegion; - (BOOL)handledByExtensionCommand:(NSEvent*)event priority:(ui::AcceleratorManager::HandlerPriority)priority; +- (void)closeAllWindowsQuit:(id)sender; @end // Cocoa bridge to AppWindow. @@ -77,10 +78,13 @@ class NativeAppWindowCocoa : public extensions::NativeAppWindow, void SetBounds(const gfx::Rect& bounds) override; void FlashFrame(bool flash) override; bool IsAlwaysOnTop() const override; + void SetShowInTaskbar(bool show) override; // Called when the window is about to be closed. void WindowWillClose(); + bool NWCanClose(bool user_force = false); + // Called when the window is focused. void WindowDidBecomeKey(); @@ -127,6 +131,8 @@ class NativeAppWindowCocoa : public extensions::NativeAppWindow, protected: // NativeAppWindow implementation. void SetFullscreen(int fullscreen_types) override; + void SetResizable(bool flag) override; + bool IsResizable() const override; bool IsFullscreenOrPending() const override; void UpdateWindowIcon() override; void UpdateWindowTitle() override; @@ -187,7 +193,9 @@ class NativeAppWindowCocoa : public extensions::NativeAppWindow, // Hides the window unconditionally. Used by Hide and HideWithApp. void HideWithoutMarkingHidden(); +public: extensions::AppWindow* app_window_; // weak - AppWindow owns NativeAppWindow. +private: bool has_frame_; diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm index ed108dd2f21c3..d49e356381e1c 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm @@ -18,6 +18,9 @@ #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h" #include "chrome/common/chrome_switches.h" #include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "extensions/common/extension.h" #include "skia/ext/skia_utils_mac.h" @@ -25,6 +28,9 @@ #import "ui/gfx/mac/nswindow_frame_controls.h" #include "ui/gfx/skia_util.h" +#include "ui/display/screen.h" +#include "content/nw/src/nw_content_mac.h" + // NOTE: State Before Update. // // Internal state, such as |is_maximized_|, must be set before the window @@ -43,12 +49,18 @@ // desired size. using extensions::AppWindow; +using extensions::AppWindowRegistry; @interface NSWindow (NSPrivateApis) - (void)setBottomCornerRounded:(BOOL)rounded; - (BOOL)_isTitleHidden; @end +namespace content { + extern bool g_support_transparency; + extern bool g_force_cpu_draw; +} + namespace { const int kActivateThrottlePeriodSeconds = 2; @@ -102,6 +114,12 @@ - (void)setTitlebarBackgroundView:(NSView*)view { titlebar_background_view_.reset([view retain]); } +- (BOOL)windowShouldClose:(id)sender { + if (appWindow_ && !appWindow_->NWCanClose()) + return NO; + return YES; +} + - (void)windowWillClose:(NSNotification*)notification { if (appWindow_) appWindow_->WindowWillClose(); @@ -181,6 +199,24 @@ - (BOOL)handledByExtensionCommand:(NSEvent*)event return NO; } +// this function is for createMacBuiltin only +- (void)closeAllWindowsQuit:(id)sender { + if (!appWindow_) + return; + AppWindowRegistry* registry = AppWindowRegistry::Get(appWindow_->app_window_->browser_context()); + if (!registry) + return; + + AppWindowRegistry::AppWindowList windows = + registry->GetAppWindowsForApp(appWindow_->app_window_->GetExtension()->id()); + + for (AppWindow* window : windows) { + // passing true for createMacBuiltin: https://github.com/nwjs/nw.js/issues/4580#issuecomment-199236153 + if (window->NWCanClose(true)) + window->GetBaseWindow()->Close(); + } +} + @end @interface AppNSWindow : ChromeEventProcessingWindow @@ -191,7 +227,7 @@ @implementation AppNSWindow // Similar to ChromeBrowserWindow, don't draw the title, but allow it to be seen // in menus, Expose, etc. - (BOOL)_isTitleHidden { - return YES; + return NO; } @end @@ -219,6 +255,10 @@ - (NSRect)contentRectForFrameRect:(NSRect)frameRect { return frameRect; } +- (BOOL)_isTitleHidden { + return YES; +} + @end @interface ControlRegionView : NSView @@ -275,7 +315,7 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; if (extension) name = extension->name(); [window setTitle:base::SysUTF8ToNSString(name)]; - [[window contentView] setWantsLayer:YES]; + [[window contentView] setWantsLayer:!content::g_force_cpu_draw]; if (params.always_on_top) gfx::SetNSWindowAlwaysOnTop(window, true); @@ -285,6 +325,12 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; window_controller_.reset( [[NativeAppWindowController alloc] initWithWindow:window]); + + if (content::g_support_transparency && params.alpha_enabled) { + [window setHasShadow: NO]; + [window setOpaque: NO]; + [window setBackgroundColor: [NSColor clearColor]]; + } if (has_frame_ && has_frame_color_) { TitlebarBackgroundView* view = @@ -304,7 +350,12 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; // We can now compute the precise window bounds and constraints. gfx::Insets insets = GetFrameInsets(); - SetBounds(params.GetInitialWindowBounds(insets)); + gfx::Rect bounds = params.GetInitialWindowBounds(insets); + if (params.position == AppWindow::POS_MOUSE) { + gfx::Point cursor_pos(display::Screen::GetScreen()->GetCursorScreenPoint()); + bounds.set_origin(cursor_pos); + } + SetBounds(bounds); SetContentSizeConstraints(params.GetContentMinimumSize(insets), params.GetContentMaximumSize(insets)); @@ -381,6 +432,10 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; return is_fullscreen_; } +void NativeAppWindowCocoa::SetShowInTaskbar(bool show) { + NWSetNSWindowShowInTaskbar(this, show); +} + void NativeAppWindowCocoa::SetFullscreen(int fullscreen_types) { bool fullscreen = (fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); if (fullscreen == is_fullscreen_) @@ -398,6 +453,19 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; // fullscreen. if (fullscreen && !shows_fullscreen_controls_) gfx::SetNSWindowCanFullscreen(window(), true); + if (fullscreen && fullscreen_types == AppWindow::FULLSCREEN_TYPE_FORCED) { + NSApplicationPresentationOptions options = + NSApplicationPresentationHideDock + + NSApplicationPresentationHideMenuBar + + NSApplicationPresentationDisableAppleMenu + + NSApplicationPresentationDisableProcessSwitching + + NSApplicationPresentationDisableForceQuit + + NSApplicationPresentationDisableSessionTermination + + NSApplicationPresentationDisableHideApplication; + [NSApp setPresentationOptions:options]; + } else if (!fullscreen) { + [NSApp setPresentationOptions:[NSApp currentSystemPresentationOptions]]; + } [window() toggleFullScreen:nil]; is_fullscreen_ = fullscreen; } @@ -568,6 +636,16 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; event.GetType() == content::NativeWebKeyboardEvent::kChar) { return; } + + // NW fix + // Simple key press events without modifiers should be sent to the menu. + // See https://github.com/nwjs/nw.js/issues/4837 + NSEvent* nsEvent = event.os_event; + if ([nsEvent type] == NSKeyDown) { + if ([[NSApp mainMenu] performKeyEquivalent:nsEvent]) + return; + } + [window() redispatchKeyEvent:event.os_event]; } @@ -627,6 +705,14 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; void NativeAppWindowCocoa::RenderViewCreated(content::RenderViewHost* rvh) { if (IsActive()) WebContents()->RestoreFocus(); + if (content::g_support_transparency && + app_window_->requested_alpha_enabled() && CanHaveAlphaEnabled()) { + content::RenderWidgetHostView* view = rvh->GetWidget()->GetView(); + // Workaround, SetBackgroundColor is "blocked" if the previous color is the same + // So set it to (0,1,1,1) then to transparent + view->SetBackgroundColor(SkColorSetARGB(0,1,1,1)); + view->SetBackgroundColor(SK_ColorTRANSPARENT); + } } bool NativeAppWindowCocoa::IsFrameless() const { @@ -665,7 +751,7 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; } bool NativeAppWindowCocoa::CanHaveAlphaEnabled() const { - return false; + return content::g_support_transparency ? [window() isOpaque] == NO : false; } void NativeAppWindowCocoa::SetActivateOnPointer(bool activate_on_pointer) { @@ -702,6 +788,10 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; app_window_->OnNativeClose(); } +bool NativeAppWindowCocoa::NWCanClose(bool user_force) { + return app_window_->NWCanClose(user_force); +} + void NativeAppWindowCocoa::WindowDidBecomeKey() { app_window_->OnNativeWindowActivated(); @@ -791,7 +881,8 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; void NativeAppWindowCocoa::HideWithApp() { is_hidden_with_app_ = true; - HideWithoutMarkingHidden(); + [NSApp hide:nil]; +// HideWithoutMarkingHidden(); } gfx::Size NativeAppWindowCocoa::GetContentMinimumSize() const { @@ -802,6 +893,25 @@ - (void)setMouseDownCanMoveWindow:(BOOL)can_move; return size_constraints_.GetMaximumSize(); } +void NativeAppWindowCocoa::SetResizable(bool flag) { + is_resizable_ = flag; + gfx::Size min_size = size_constraints_.GetMinimumSize(); + gfx::Size max_size = size_constraints_.GetMaximumSize(); + + shows_resize_controls_ = + is_resizable_ && !size_constraints_.HasFixedSize(); + shows_fullscreen_controls_ = + is_resizable_ && !size_constraints_.HasMaximumSize() && has_frame_; + + gfx::ApplyNSWindowSizeConstraints(window(), min_size, max_size, + shows_resize_controls_, + shows_fullscreen_controls_); +} + +bool NativeAppWindowCocoa::IsResizable() const { + return is_resizable_; +} + void NativeAppWindowCocoa::SetContentSizeConstraints( const gfx::Size& min_size, const gfx::Size& max_size) { // Update the size constraints. diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index e08dfe384a904..03b76873e2f5c 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -84,6 +84,8 @@ initial_show_state_(ui::SHOW_STATE_DEFAULT), attention_request_id_(0) { + CHECK(browser->is_type_popup()) << "opening browser window."; + gfx::Rect bounds; chrome::GetSavedWindowBoundsAndShowState(browser_, &bounds, @@ -512,6 +514,7 @@ translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) { +#if 0 ChromeTranslateClient* chrome_translate_client = ChromeTranslateClient::FromWebContents(contents); translate::LanguageState& language_state = @@ -522,6 +525,7 @@ step:step errorType:error_type]; +#endif return ShowTranslateBubbleResult::SUCCESS; } diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 6454210ba2873..20245a01eafd5 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm @@ -1607,6 +1607,7 @@ - (void)showTranslateBubbleForWebContents:(content::WebContents*)contents step:(translate::TranslateStep)step errorType:(translate::TranslateErrors::Type) errorType { +#if 0 if (chrome::ShowAllDialogsWithViewsToolkit()) { ShowTranslateBubbleViews([self window], [self locationBarBridge], contents, step, errorType, true); @@ -1655,6 +1656,7 @@ - (void)showTranslateBubbleForWebContents:(content::WebContents*)contents selector:@selector(translateBubbleWindowWillClose:) name:NSWindowWillCloseNotification object:[translateBubbleController_ window]]; +#endif } - (void)dismissPermissionBubble { diff --git a/chrome/browser/ui/cocoa/download/download_item_controller.mm b/chrome/browser/ui/cocoa/download/download_item_controller.mm index 87894f5a08dbd..1e1cf9346a4cd 100644 --- a/chrome/browser/ui/cocoa/download/download_item_controller.mm +++ b/chrome/browser/ui/cocoa/download/download_item_controller.mm @@ -384,6 +384,9 @@ - (IBAction)showContextMenu:(id)sender { - (bool)submitDownloadToFeedbackService:(download::DownloadItem*)download withCommand:(DownloadCommands::Command)command { +#if 1 + return false; +#else safe_browsing::SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); if (!sb_service) @@ -405,6 +408,7 @@ - (bool)submitDownloadToFeedbackService:(download::DownloadItem*)download download_protection_service->feedback_service()->BeginFeedbackForDownload( download, command); return true; +#endif } @end diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm index e8d5309535f35..c2d1178877255 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm @@ -635,6 +635,7 @@ new ManagePasswordsDecoration(command_updater, this)), } void LocationBarViewMac::UpdateTranslateDecoration() { +#if 0 if (!TranslateService::IsTranslateBubbleEnabled()) return; @@ -651,6 +652,7 @@ new ManagePasswordsDecoration(command_updater, this)), translate_decoration_->SetVisible(enabled); translate_decoration_->SetLit(language_state.IsPageTranslated(), IsLocationBarDark()); +#endif } bool LocationBarViewMac::UpdateZoomDecoration(bool default_zoom_changed) { diff --git a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.h b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.h index eec1f13f09930..d8a8a8f5e4456 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.h +++ b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.h @@ -16,6 +16,10 @@ class Browser; @class ChooserBubbleUiController; class ChooserController; +namespace extensions { +class AppWindow; +} + // ChooserBubbleUiCocoa implements a chooser-based permission model. // It uses |NSTableView| to show a list of options for user to grant // permission. It can be used by the WebUSB or WebBluetooth APIs. @@ -23,6 +27,7 @@ class ChooserController; class ChooserBubbleUiCocoa : public BubbleUi { public: ChooserBubbleUiCocoa(Browser* browser, + extensions::AppWindow* app_window, std::unique_ptr chooser_controller); ~ChooserBubbleUiCocoa() override; @@ -36,6 +41,7 @@ class ChooserBubbleUiCocoa : public BubbleUi { private: Browser* browser_; // Weak. + extensions::AppWindow* app_window_; // Cocoa-side chooser bubble UI controller. Weak, as it will close itself. ChooserBubbleUiController* chooser_bubble_ui_controller_; diff --git a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.mm b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.mm index cb39df1991a9b..cefc25395fd72 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.mm +++ b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.mm @@ -4,6 +4,7 @@ #import "chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_cocoa.h" +#include "extensions/browser/app_window/app_window.h" #include #include @@ -41,10 +42,12 @@ @interface ChooserBubbleUiController NSButton* cancelButton_; // Weak. Browser* browser_; // Weak. + extensions::AppWindow* app_window_; } // Designated initializer. |browser| and |bridge| must both be non-nil. - (id)initWithBrowser:(Browser*)browser + appWindow:(extensions::AppWindow*)app_window chooserController:(std::unique_ptr)chooserController bridge:(ChooserBubbleUiCocoa*)bridge; @@ -78,13 +81,15 @@ - (void)onCancel:(id)sender; @implementation ChooserBubbleUiController - (id)initWithBrowser:(Browser*)browser + appWindow:(extensions::AppWindow*)app_window chooserController:(std::unique_ptr)chooserController bridge:(ChooserBubbleUiCocoa*)bridge { - DCHECK(browser); + //DCHECK(browser); DCHECK(chooserController); DCHECK(bridge); browser_ = browser; + app_window_ = app_window; base::scoped_nsobject window([[InfoBubbleWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater @@ -216,16 +221,25 @@ - (void)updateAnchorPosition { } - (NSPoint)getExpectedAnchorPoint { + if (!browser_) { + NSRect r = [app_window_->GetNativeWindow() frame]; + r.origin.y += r.size.height; + return r.origin; + } return GetPageInfoAnchorPointForBrowser(browser_); } - (info_bubble::BubbleArrowLocation)getExpectedArrowLocation { - return info_bubble::kTopLeading; + return info_bubble::kNoArrow; } - (NSWindow*)getExpectedParentWindow { - DCHECK(browser_->window()); - return browser_->window()->GetNativeWindow(); + if (browser_) { + DCHECK(browser_->window()); + return browser_->window()->GetNativeWindow(); + } else { + return app_window_->GetNativeWindow(); + } } + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB { @@ -265,13 +279,16 @@ - (void)onCancel:(id)sender { ChooserBubbleUiCocoa::ChooserBubbleUiCocoa( Browser* browser, + extensions::AppWindow* app_window, std::unique_ptr chooser_controller) : browser_(browser), + app_window_(app_window), chooser_bubble_ui_controller_(nil) { - DCHECK(browser_); + //DCHECK(browser_); DCHECK(chooser_controller); chooser_bubble_ui_controller_ = [[ChooserBubbleUiController alloc] initWithBrowser:browser_ + appWindow:app_window_ chooserController:std::move(chooser_controller) bridge:this]; } diff --git a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm index e8d1a4602a04f..28a2b4a147ea8 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm +++ b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm @@ -20,13 +20,15 @@ void ChooserBubbleUi::CreateAndShowCocoa( views::BubbleDialogDelegateView* delegate) { - gfx::NativeWindow parent_window = browser_->window()->GetNativeWindow(); - gfx::NativeView parent = platform_util::GetViewForWindow(parent_window); - DCHECK(parent); // Set |parent_window_| because some valid anchors can become hidden. + gfx::NativeView parent = nullptr; + if (browser_) + parent = platform_util::GetViewForWindow(browser_->window()->GetNativeWindow()); + //DCHECK(parent); delegate->set_parent_window(parent); views::BubbleDialogDelegateView::CreateBubble(delegate)->Show(); - KeepBubbleAnchored(delegate, GetPageInfoDecoration(parent_window)); + if (browser_) + KeepBubbleAnchored(delegate, GetPageInfoDecoration(browser_->window()->GetNativeWindow())); } #if !BUILDFLAG(MAC_VIEWS_BROWSER) diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h index eb6545721817c..27e3601cc6c57 100644 --- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h +++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.h @@ -36,7 +36,7 @@ class StatusIconMac : public StatusIcon { protected: // Overridden from StatusIcon. - void UpdatePlatformContextMenu(StatusIconMenuModel* model) override; + void UpdatePlatformContextMenu(ui::MenuModel* model) override; private: FRIEND_TEST_ALL_PREFIXES(StatusIconMacTest, CreateMenu); diff --git a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm index 6ec463bb64255..f515654161ae2 100644 --- a/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm +++ b/chrome/browser/ui/cocoa/status_icons/status_icon_mac.mm @@ -96,7 +96,7 @@ - (void)handleClick:(id)sender { return menu_.get() != nil; } -void StatusIconMac::UpdatePlatformContextMenu(StatusIconMenuModel* model) { +void StatusIconMac::UpdatePlatformContextMenu(ui::MenuModel* model) { if (!model) { menu_.reset(); } else { diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/libgtkui/BUILD.gn index ccbed52a0a3fc..60d3b581213ad 100644 --- a/chrome/browser/ui/libgtkui/BUILD.gn +++ b/chrome/browser/ui/libgtkui/BUILD.gn @@ -66,10 +66,15 @@ template("libgtkui") { ] configs += [ - "//build/config/linux/pangocairo", "//build/config/linux:x11", ] + if (is_component_build) { + configs += [ + "//build/config/linux/pangocairo", + ] + } + if (use_gio) { sources += [ "settings_provider_gsettings.cc", diff --git a/chrome/browser/ui/libgtkui/app_indicator_icon.cc b/chrome/browser/ui/libgtkui/app_indicator_icon.cc index 5aeb9d4d115cc..8693780c99abf 100644 --- a/chrome/browser/ui/libgtkui/app_indicator_icon.cc +++ b/chrome/browser/ui/libgtkui/app_indicator_icon.cc @@ -227,7 +227,6 @@ void AppIndicatorIcon::SetImage(const gfx::ImageSkia& image) { } void AppIndicatorIcon::SetToolTip(const base::string16& tool_tip) { - DCHECK(!tool_tip_.empty()); tool_tip_ = base::UTF16ToUTF8(tool_tip); UpdateClickActionReplacementMenuItem(); } @@ -372,8 +371,8 @@ void AppIndicatorIcon::UpdateClickActionReplacementMenuItem() { if (!delegate()->HasClickAction() && menu_model_) return; - DCHECK(!tool_tip_.empty()); - menu_->UpdateClickActionReplacementMenuItem( + if(!tool_tip_.empty()) + menu_->UpdateClickActionReplacementMenuItem( tool_tip_.c_str(), base::Bind(&AppIndicatorIcon::OnClickActionReplacementMenuItemActivated, base::Unretained(this))); diff --git a/chrome/browser/ui/libgtkui/app_indicator_icon_menu.cc b/chrome/browser/ui/libgtkui/app_indicator_icon_menu.cc index 40399a35f8d2c..1d3a0da948dca 100644 --- a/chrome/browser/ui/libgtkui/app_indicator_icon_menu.cc +++ b/chrome/browser/ui/libgtkui/app_indicator_icon_menu.cc @@ -116,7 +116,7 @@ void AppIndicatorIconMenu::OnMenuItemActivated(GtkWidget* menu_item) { return; // The menu item can still be activated by hotkeys even if it is disabled. - if (menu_model_->IsEnabledAt(id)) + if (model->IsEnabledAt(id)) ExecuteCommand(model, id); } diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc index 031f314780ada..1638a066c4985 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc +++ b/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc @@ -329,13 +329,13 @@ GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( std::string title_string = title; if (title_string.empty()) { title_string = - (type == SELECT_UPLOAD_FOLDER) + (false) ? l10n_util::GetStringUTF8(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE) : l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); } G_GNUC_BEGIN_IGNORE_DEPRECATIONS; std::string accept_button_label = - (type == SELECT_UPLOAD_FOLDER) + (false) ? l10n_util::GetStringUTF8( IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON) : GTK_STOCK_OPEN; diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index 08c2802410401..2c1fe566b248a 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc @@ -261,8 +261,10 @@ bool ChromeOmniboxClient::ProcessExtensionKeyword( void ChromeOmniboxClient::OnInputStateChanged() { if (!controller_->GetWebContents()) return; +#if 0 SearchTabHelper::FromWebContents( controller_->GetWebContents())->OmniboxInputStateChanged(); +#endif } void ChromeOmniboxClient::OnFocusChanged( @@ -270,8 +272,10 @@ void ChromeOmniboxClient::OnFocusChanged( OmniboxFocusChangeReason reason) { if (!controller_->GetWebContents()) return; +#if 0 SearchTabHelper::FromWebContents( controller_->GetWebContents())->OmniboxFocusChanged(state, reason); +#endif } void ChromeOmniboxClient::OnResultChanged( diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index e22c7c8c4de2d..2f240d0a6594e 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc @@ -580,7 +580,8 @@ void ManagePasswordsUIController::DidFinishNavigation( void ManagePasswordsUIController::OnVisibilityChanged( content::Visibility visibility) { if (visibility == content::Visibility::HIDDEN) - TabDialogs::FromWebContents(web_contents())->HideManagePasswordsBubble(); + if (TabDialogs::FromWebContents(web_contents())) + TabDialogs::FromWebContents(web_contents())->HideManagePasswordsBubble(); } // static diff --git a/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.cc b/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.cc index 121eb179489f1..7adb3966f9832 100644 --- a/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.cc +++ b/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h" +#include "extensions/browser/app_window/app_window_registry.h" #include "chrome/browser/chooser_controller/chooser_controller.h" #include "chrome/browser/ui/browser.h" @@ -15,7 +16,14 @@ ChooserBubbleDelegate::ChooserBubbleDelegate( : owning_frame_(owner), browser_(chrome::FindBrowserWithWebContents( content::WebContents::FromRenderFrameHost(owner))), - chooser_controller_(std::move(chooser_controller)) {} + app_window_(nullptr), + chooser_controller_(std::move(chooser_controller)) { + if (!browser_) { + content::WebContents* web_contents = (content::WebContents*)content::WebContents::FromRenderFrameHost((content::RenderFrameHost*)owning_frame_); + extensions::AppWindowRegistry* registry = extensions::AppWindowRegistry::Get(web_contents->GetBrowserContext()); + app_window_ = registry->GetAppWindowForWebContents(web_contents); + } +} ChooserBubbleDelegate::~ChooserBubbleDelegate() {} diff --git a/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h b/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h index 418e6e1c0519a..663953fa9b6d6 100644 --- a/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h +++ b/chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h @@ -15,6 +15,10 @@ namespace content { class RenderFrameHost; } +namespace extensions { + class AppWindow; +} + // ChooserBubbleDelegate overrides GetName() to identify the bubble // you define for collecting metrics. Create an instance of this // class and pass it to BubbleManager::ShowBubble() to show the bubble. @@ -32,6 +36,7 @@ class ChooserBubbleDelegate : public BubbleDelegate { private: const content::RenderFrameHost* const owning_frame_; Browser* const browser_; + extensions::AppWindow* app_window_; // |chooser_controller_| is not owned by this class, it is owned by // DeviceChooserContentView[Cocoa]. // This field only temporarily owns the ChooserController. It is moved diff --git a/chrome/browser/ui/scoped_tabbed_browser_displayer.cc b/chrome/browser/ui/scoped_tabbed_browser_displayer.cc index 9ad5bffbe9aca..239d6c610381c 100644 --- a/chrome/browser/ui/scoped_tabbed_browser_displayer.cc +++ b/chrome/browser/ui/scoped_tabbed_browser_displayer.cc @@ -13,7 +13,7 @@ namespace chrome { ScopedTabbedBrowserDisplayer::ScopedTabbedBrowserDisplayer(Profile* profile) { browser_ = FindTabbedBrowser(profile, false); if (!browser_) - browser_ = new Browser(Browser::CreateParams(profile, true)); + browser_ = new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile, true)); } ScopedTabbedBrowserDisplayer::~ScopedTabbedBrowserDisplayer() { diff --git a/chrome/browser/ui/signin_view_controller_delegate.cc b/chrome/browser/ui/signin_view_controller_delegate.cc index bfbdde447e205..7541437b5739d 100644 --- a/chrome/browser/ui/signin_view_controller_delegate.cc +++ b/chrome/browser/ui/signin_view_controller_delegate.cc @@ -81,6 +81,8 @@ void SigninViewControllerDelegate::ResetSigninViewControllerDelegate() { void SigninViewControllerDelegate::LoadingStateChanged( content::WebContents* source, bool to_different_document) { + if (!source->GetWebUI()) + return; if (CanGoBack(source)) source->GetWebUI()->CallJavascriptFunctionUnsafe( "inline.login.showBackButton"); diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index a52bf25cf6352..df3221f2e8732 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc @@ -3,6 +3,9 @@ // found in the LICENSE file. #include "chrome/browser/ui/startup/startup_browser_creator.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "content/nw/src/common/shell_switches.h" +#include "content/public/common/content_features.h" #include @@ -69,6 +72,15 @@ #include "net/base/port_util.h" #include "printing/buildflags/buildflags.h" +#include "extensions/browser/extension_system.h" +#include "chrome/browser/extensions/component_loader.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/grit/browser_resources.h" +#include "extensions/common/constants.h" +#include "chrome/browser/ui/extensions/app_launch_params.h" +#include "chrome/browser/ui/extensions/application_launch.h" + #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/app_mode/app_launch_utils.h" #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" @@ -532,7 +544,7 @@ std::vector StartupBrowserCreator::GetURLsFromCommandLine( const GURL reset_settings_url = settings_url.Resolve(chrome::kResetProfileSettingsSubPage); url_points_to_an_approved_settings_page = url == reset_settings_url; -#if defined(OS_WIN) +#if 0 // On Windows, also allow a hash for the Chrome Cleanup Tool. const GURL reset_settings_url_with_cct_hash = reset_settings_url.Resolve( std::string("#") + @@ -705,10 +717,56 @@ bool StartupBrowserCreator::ProcessCmdLineImpl( // chrome to shut down. // TODO(jackhou): Do this properly once keep-alive is handled by the // background page of apps. Tracked at http://crbug.com/175381 - if (chrome::GetBrowserCount(last_used_profile) != 0) + // if (chrome::GetBrowserCount(last_used_profile) != 0) return true; } + if (!process_startup) + return true; + if (command_line.HasSwitch(switches::kEnableSpellChecking)) + SpellcheckServiceFactory::GetForContext(last_used_profile); + + const base::CommandLine::StringVector& params = command_line.GetArgs(); + if (command_line.HasSwitch("nwapp")) { + if (!apps::AppLoadService::Get(last_used_profile)->LoadAndLaunch( + base::FilePath(command_line.GetSwitchValueNative("nwapp")), command_line, cur_dir)) { + return false; + } + return true; + } + + if (!command_line.HasSwitch("nwjs-test-mode")) { + if (params.size() > 0) { + if (!apps::AppLoadService::Get(last_used_profile)->LoadAndLaunch( + base::FilePath(params[0]), command_line, cur_dir)) { + return false; + } + return true; + } else { + ExtensionService* extension_service = + extensions::ExtensionSystem::Get(last_used_profile)->extension_service(); + extensions::ComponentLoader* component_loader = extension_service->component_loader(); + std::string id; + if (base::FeatureList::IsEnabled(::features::kNWNewWin)) { + id = component_loader->GetExtensionID(IDR_NWJS_DEFAPP_MANIFEST_NEWWIN, + base::FilePath(FILE_PATH_LITERAL("nwjs_newwin_app"))); + } else { + id = component_loader->GetExtensionID(IDR_NWJS_DEFAPP_MANIFEST, + base::FilePath(FILE_PATH_LITERAL("nwjs_default_app"))); + } + + LOG(INFO) << "loading default app: " << id; + const extensions::Extension* extension = extension_service->GetExtensionById(id, true); + if (!extension) { + LOG(FATAL) << "Failed to load default app"; + return false; + } + OpenApplication( + AppLaunchParams(last_used_profile, extension, extensions::LAUNCH_CONTAINER_WINDOW, + WindowOpenDisposition::NEW_WINDOW, extensions::SOURCE_CHROME_INTERNAL)); + return true; + } + } #if defined(OS_WIN) // Log whether this process was a result of an action in the Windows Jumplist. if (command_line.HasSwitch(switches::kWinJumplistAction)) { diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index b8bb2042e29f1..cd6ad6f5a562f 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc @@ -192,7 +192,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { web_contents->GetBrowserContext())); chrome_browser_net::NetErrorTabHelper::CreateForWebContents(web_contents); chrome_browser_net::PredictorTabHelper::CreateForWebContents(web_contents); - ChromeLanguageDetectionTabHelper::CreateForWebContents(web_contents); + //ChromeLanguageDetectionTabHelper::CreateForWebContents(web_contents); ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( web_contents, autofill::ChromeAutofillClient::FromWebContents(web_contents)); @@ -200,7 +200,7 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { subresource_filter::kSafeBrowsingSubresourceFilter)) { ChromeSubresourceFilterClient::CreateForWebContents(web_contents); } - ChromeTranslateClient::CreateForWebContents(web_contents); + //ChromeTranslateClient::CreateForWebContents(web_contents); ClientHintsObserver::CreateForWebContents(web_contents); ConnectionHelpTabHelper::CreateForWebContents(web_contents); CoreTabHelper::CreateForWebContents(web_contents); @@ -237,8 +237,10 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { PrefsTabHelper::CreateForWebContents(web_contents); prerender::PrerenderTabHelper::CreateForWebContents(web_contents); PreviewsInfoBarTabHelper::CreateForWebContents(web_contents); +#if 0 safe_browsing::TriggerCreator::MaybeCreateTriggersForWebContents( profile, web_contents); +#endif SearchEngineTabHelper::CreateForWebContents(web_contents); SecurityStateTabHelper::CreateForWebContents(web_contents); if (SiteEngagementService::IsEnabled()) @@ -287,10 +289,12 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) { new ChromePDFWebContentsHelperClient())); PluginObserver::CreateForWebContents(web_contents); SadTabHelper::CreateForWebContents(web_contents); +#if 0 safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(web_contents); safe_browsing::SafeBrowsingNavigationObserver::MaybeCreateForWebContents( web_contents); SearchTabHelper::CreateForWebContents(web_contents); +#endif TabContentsSyncedTabDelegate::CreateForWebContents(web_contents); TabDialogs::CreateForWebContents(web_contents); ThumbnailTabHelper::CreateForWebContents(web_contents); diff --git a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc index ae3381cc8b4f9..a927d200a9558 100644 --- a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc +++ b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc @@ -22,10 +22,12 @@ const char ComponentToolbarActionsFactory::kMediaRouterActionId[] = ComponentToolbarActionsFactory::ComponentToolbarActionsFactory( Profile* profile) { +#if defined(NWJS_SDK) if (media_router::MediaRouterEnabled(profile) && MediaRouterActionController::IsActionShownByPolicy(profile)) { initial_ids_.insert(kMediaRouterActionId); } +#endif } ComponentToolbarActionsFactory::~ComponentToolbarActionsFactory() {} @@ -57,10 +59,11 @@ ComponentToolbarActionsFactory::GetComponentToolbarActionForId( // (since each will have an action in the toolbar or overflow menu), this // should be okay. If this changes, we should rethink this design to have, // e.g., RegisterChromeAction(). +#if defined(NWJS_SDK) if (action_id == kMediaRouterActionId) return std::unique_ptr( new MediaRouterAction(browser, bar)); - +#endif NOTREACHED(); return std::unique_ptr(); } diff --git a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc index 1306401674413..42b0d0f821a29 100644 --- a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc +++ b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc @@ -26,6 +26,9 @@ AppWindowDesktopWindowTreeHostWin::~AppWindowDesktopWindowTreeHostWin() { bool AppWindowDesktopWindowTreeHostWin::GetClientAreaInsets( gfx::Insets* insets) const { +#if 1 + return false; +#else // The inset added below is only necessary for the native glass frame, i.e. // not for colored frames drawn by Chrome, or when DWM is disabled. // In fullscreen the frame is not visible. @@ -36,6 +39,7 @@ bool AppWindowDesktopWindowTreeHostWin::GetClientAreaInsets( *insets = app_window_->glass_frame_view()->GetClientAreaInsets(); return true; +#endif } void AppWindowDesktopWindowTreeHostWin::HandleFrameChanged() { @@ -58,6 +62,9 @@ void AppWindowDesktopWindowTreeHostWin::PostHandleMSG(UINT message, } void AppWindowDesktopWindowTreeHostWin::UpdateDWMFrame() { +#if 1 + return; +#else if (!GetWidget()->client_view() || !app_window_->glass_frame_view()) return; @@ -77,4 +84,5 @@ void AppWindowDesktopWindowTreeHostWin::UpdateDWMFrame() { } DwmExtendFrameIntoClientArea(GetHWND(), &margins); +#endif } diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc index 30c657afe0c8f..04ed596b39631 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc @@ -27,6 +27,14 @@ #include "ui/views/controls/webview/webview.h" #include "ui/views/widget/widget.h" +#if defined(NWJS_SDK) +#include "base/command_line.h" +#include "chrome/browser/devtools/devtools_window.h" +#include "content/nw/src/common/shell_switches.h" +#endif + +#include "ui/display/screen.h" + using extensions::AppWindow; namespace { @@ -37,9 +45,12 @@ const int kDefaultPanelWidth = 200; const int kDefaultPanelHeight = 300; const AcceleratorMapping kAppWindowAcceleratorMap[] = { - { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW }, - { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW }, + // { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW }, + // { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW }, { ui::VKEY_F4, ui::EF_ALT_DOWN, IDC_CLOSE_WINDOW }, +#if defined(NWJS_SDK) + { ui::VKEY_F12, ui::EF_NONE, IDC_DEV_TOOLS_TOGGLE }, +#endif }; // These accelerators will only be available in kiosk mode. These allow the @@ -110,6 +121,10 @@ void ChromeNativeAppWindowViews::OnBeforeWidgetInit( views::Widget* widget) { } +bool ChromeNativeAppWindowViews::NWCanClose(bool user_force) const { + return app_window()->NWCanClose(user_force); +} + void ChromeNativeAppWindowViews::OnBeforePanelWidgetInit( views::Widget::InitParams* init_params, views::Widget* widget) { @@ -142,6 +157,15 @@ void ChromeNativeAppWindowViews::InitializeDefaultWindow( // correctly. So we set the window bounds and constraints now. gfx::Insets frame_insets = GetFrameInsets(); gfx::Rect window_bounds = create_params.GetInitialWindowBounds(frame_insets); +#if defined(OS_LINUX) + if (create_params.GetContentMinimumSize(frame_insets).IsEmpty() && + create_params.GetContentMaximumSize(frame_insets).IsEmpty() && + !create_params.resizable) { //NWJS#6592 + gfx::Size size(create_params.content_spec.bounds.width(), + create_params.content_spec.bounds.height()); + SetContentSizeConstraints(size, size); + } else +#endif SetContentSizeConstraints(create_params.GetContentMinimumSize(frame_insets), create_params.GetContentMaximumSize(frame_insets)); if (!window_bounds.IsEmpty()) { @@ -149,10 +173,23 @@ void ChromeNativeAppWindowViews::InitializeDefaultWindow( bool position_specified = window_bounds.x() != BoundsSpecification::kUnspecifiedPosition && window_bounds.y() != BoundsSpecification::kUnspecifiedPosition; + position_specified |= create_params.position == AppWindow::POS_MOUSE; if (!position_specified) widget()->CenterWindow(window_bounds.size()); - else + else if (create_params.position == AppWindow::POS_MOUSE) { + gfx::Point cursor_pos(display::Screen::GetScreen()->GetCursorScreenPoint()); + window_bounds.set_origin(cursor_pos); widget()->SetBounds(window_bounds); + }else + widget()->SetBounds(window_bounds); + } else { + if (create_params.position == AppWindow::POS_CENTER) + widget()->CenterWindow(gfx::Size(640, 480)); + else if (create_params.position == extensions::AppWindow::POS_MOUSE) { + gfx::Point cursor_pos(display::Screen::GetScreen()->GetCursorScreenPoint()); + gfx::Rect bounds(cursor_pos, gfx::Size(640, 480)); + widget()->SetBounds(bounds); + } } #if defined(OS_CHROMEOS) @@ -254,6 +291,9 @@ bool ChromeNativeAppWindowViews::IsAlwaysOnTop() const { // views::WidgetDelegate implementation. gfx::ImageSkia ChromeNativeAppWindowViews::GetWindowAppIcon() { + gfx::Image icon_override = app_window()->icon_override(); + if (!icon_override.IsEmpty()) + return *icon_override.ToImageSkia(); // Resulting icon is cached in aura::client::kAppIconKey window property. const gfx::Image& custom_image = app_window()->custom_app_icon(); if (app_window()->app_icon_url().is_valid() && @@ -285,6 +325,9 @@ gfx::ImageSkia ChromeNativeAppWindowViews::GetWindowAppIcon() { } gfx::ImageSkia ChromeNativeAppWindowViews::GetWindowIcon() { + gfx::Image icon_override = app_window()->icon_override(); + if (!icon_override.IsEmpty()) + return *icon_override.ToImageSkia(); // Resulting icon is cached in aura::client::kWindowIconKey window property. content::WebContents* web_contents = app_window()->web_contents(); if (web_contents) { @@ -321,6 +364,14 @@ bool ChromeNativeAppWindowViews::AcceleratorPressed( accelerator_table.find(accelerator); DCHECK(iter != accelerator_table.end()); int command_id = iter->second; +#if defined(NWJS_SDK) + content::WebContents* web_contents; + bool enable_devtools = true; + const base::CommandLine* command_line = + base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableDevTools)) + enable_devtools = false; +#endif switch (command_id) { case IDC_CLOSE_WINDOW: Close(); @@ -336,7 +387,25 @@ bool ChromeNativeAppWindowViews::AcceleratorPressed( case IDC_ZOOM_PLUS: zoom::PageZoom::Zoom(web_view()->GetWebContents(), content::PAGE_ZOOM_IN); return true; - default: +#if defined(NWJS_SDK) + case IDC_DEV_TOOLS: + if (!enable_devtools) + return true; + web_contents = app_window()->web_contents(); + if (web_contents) { + DevToolsWindow::OpenDevToolsWindow(web_contents); + } + return true; + case IDC_DEV_TOOLS_TOGGLE: + if (!enable_devtools) + return true; + web_contents = app_window()->web_contents(); + if (web_contents) { + DevToolsWindow::OpenDevToolsWindow(web_contents, DevToolsToggleAction::Toggle()); + } + return true; +#endif + default: NOTREACHED() << "Unknown accelerator sent to app window."; } return NativeAppWindowViews::AcceleratorPressed(accelerator); diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h index 401601f139d83..e8ec21f282ef6 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h @@ -55,6 +55,7 @@ class ChromeNativeAppWindowViews views::Widget* widget) override; bool WidgetHasHitTestMask() const override; void GetWidgetHitTestMask(gfx::Path* mask) const override; + bool NWCanClose(bool user_force = false) const override; // views::View implementation. bool AcceleratorPressed(const ui::Accelerator& accelerator) override; diff --git a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc index baf7d8616a5db..bda9fd9bebdb3 100644 --- a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc +++ b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc @@ -62,6 +62,9 @@ gfx::Insets GlassAppWindowFrameViewWin::GetClientAreaInsets() const { } gfx::Rect GlassAppWindowFrameViewWin::GetBoundsForClientView() const { +#if 1 + return bounds(); +#else if (widget_->IsFullscreen()) return bounds(); @@ -70,6 +73,7 @@ gfx::Rect GlassAppWindowFrameViewWin::GetBoundsForClientView() const { insets.top(), std::max(0, width() - insets.left() - insets.right()), std::max(0, height() - insets.top() - insets.bottom())); +#endif } gfx::Rect GlassAppWindowFrameViewWin::GetWindowBoundsForClientBounds( @@ -96,6 +100,11 @@ int GlassAppWindowFrameViewWin::NonClientHitTest(const gfx::Point& point) { if (!bounds().Contains(point)) return HTNOWHERE; + int client_component = widget_->client_view()->NonClientHitTest(point); + if (client_component != HTNOWHERE) + return client_component; + + // Check the frame first, as we allow a small area overlapping the contents // to be used for resize handles. bool can_ever_resize = widget_->widget_delegate() @@ -115,10 +124,6 @@ int GlassAppWindowFrameViewWin::NonClientHitTest(const gfx::Point& point) { if (frame_component != HTNOWHERE) return frame_component; - int client_component = widget_->client_view()->NonClientHitTest(point); - if (client_component != HTNOWHERE) - return client_component; - // Caption is a safe default. return HTCAPTION; } diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc index 4b99c50da6978..68be9ccc90a06 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc @@ -4,6 +4,10 @@ #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h" +#include "chrome/browser/apps/app_window_registry_util.h" +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/native_app_window.h" + #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" @@ -293,7 +297,12 @@ gfx::Rect AutofillPopupBaseView::CalculateClippingBounds() const { gfx::NativeWindow window = platform_util::GetTopLevel(delegate_->container_view()); Browser* browser = chrome::FindBrowserWithWindow(window); - DCHECK(browser); + //DCHECK(browser); + if (!browser) { + extensions::AppWindow* app_window = + AppWindowRegistryUtil::GetAppWindowForNativeWindowAnyProfile(window); + return app_window->GetBaseWindow()->GetBounds(); + } // This is not the same as "GetClientAreaBoundsInScreen()", but it gives us // the lower bounds the popup will have to clip to on the screen. diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc index 476e0e66dfa91..f26985a539232 100644 --- a/chrome/browser/ui/views/chrome_views_delegate.cc +++ b/chrome/browser/ui/views/chrome_views_delegate.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/chrome_views_delegate.h" +#include "content/nw/src/nw_content.h" #include #include "base/logging.h" diff --git a/chrome/browser/ui/views/chrome_views_delegate_linux.cc b/chrome/browser/ui/views/chrome_views_delegate_linux.cc index 3a3712ea67300..d239ccacb80c0 100644 --- a/chrome/browser/ui/views/chrome_views_delegate_linux.cc +++ b/chrome/browser/ui/views/chrome_views_delegate_linux.cc @@ -6,6 +6,8 @@ #include "base/environment.h" #include "base/nix/xdg_util.h" +#include "content/nw/src/nw_content.h" + #include "chrome/browser/ui/views/native_widget_factory.h" #include "chrome/common/channel_info.h" #include "chrome/grit/chrome_unscaled_resources.h" @@ -50,6 +52,9 @@ views::NativeWidget* ChromeViewsDelegate::CreateNativeWidget( } gfx::ImageSkia* ChromeViewsDelegate::GetDefaultWindowIcon() const { + gfx::ImageSkia* ret = nw::GetAppIcon(); + if (ret) + return ret; ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); return rb.GetImageSkiaNamed(GetWindowIconResourceId()); } diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 2c98dc0f49203..67b9d33a668f6 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -162,6 +162,9 @@ #include "chrome/browser/ui/views/frame/browser_view_commands_mac.h" #endif +#include "extensions/browser/app_window/app_window.h" +#include "extensions/browser/app_window/app_window_registry.h" + #if defined(USE_AURA) #include "chrome/browser/ui/views/theme_profile_key.h" #include "ui/aura/client/window_parenting_client.h" @@ -446,6 +449,8 @@ BrowserView::~BrowserView() { } void BrowserView::Init(Browser* browser) { + // type popup is for devtools window. that's what we want + CHECK(browser->is_type_popup()) << "opening browser window."; browser_.reset(browser); browser_->tab_strip_model()->AddObserver(this); immersive_mode_controller_.reset(chrome::CreateImmersiveModeController()); @@ -828,7 +833,7 @@ void BrowserView::OnActiveTabChanged(content::WebContents* old_contents, // Update all the UI bits. UpdateTitleBar(); - TranslateBubbleView::CloseCurrentBubble(); + //TranslateBubbleView::CloseCurrentBubble(); } void BrowserView::ZoomChangedForActiveTab(bool can_show_bubble) { @@ -1226,6 +1231,7 @@ ShowTranslateBubbleResult BrowserView::ShowTranslateBubble( return ShowTranslateBubbleResult::EDITABLE_FIELD_IS_ACTIVE; } +#if 0 translate::LanguageState& language_state = ChromeTranslateClient::FromWebContents(web_contents)->GetLanguageState(); language_state.SetTranslateEnabled(true); @@ -1235,6 +1241,7 @@ ShowTranslateBubbleResult BrowserView::ShowTranslateBubble( toolbar_->ShowTranslateBubble(web_contents, step, error_type, is_user_gesture); +#endif return ShowTranslateBubbleResult::SUCCESS; } @@ -1697,6 +1704,22 @@ bool BrowserView::ShouldShowWindowTitle() const { } gfx::ImageSkia BrowserView::GetWindowAppIcon() { +#if 1 + if (browser_->is_devtools()) { + WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents(); + DevToolsWindow* devtools_window = DevToolsWindow::AsDevToolsWindow(contents); + if (devtools_window) { + WebContents* inspected_contents = devtools_window->GetInspectedWebContents(); + Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); + extensions::AppWindowRegistry* registry = extensions::AppWindowRegistry::Get(profile); + if (registry) { + extensions::AppWindow* app_window = registry->GetAppWindowForWebContents(inspected_contents); + if (app_window) + return app_window->custom_app_icon().AsImageSkia(); + } + } + } +#endif extensions::HostedAppBrowserController* app_controller = browser()->hosted_app_controller(); return app_controller ? app_controller->GetWindowAppIcon() : GetWindowIcon(); @@ -1704,8 +1727,21 @@ gfx::ImageSkia BrowserView::GetWindowAppIcon() { gfx::ImageSkia BrowserView::GetWindowIcon() { // Use the default icon for devtools. - if (browser_->is_devtools()) + if (browser_->is_devtools()) { + WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents(); + DevToolsWindow* devtools_window = DevToolsWindow::AsDevToolsWindow(contents); + if (devtools_window) { + WebContents* inspected_contents = devtools_window->GetInspectedWebContents(); + Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); + extensions::AppWindowRegistry* registry = extensions::AppWindowRegistry::Get(profile); + if (registry) { + extensions::AppWindow* app_window = registry->GetAppWindowForWebContents(inspected_contents); + if (app_window) + return app_window->custom_app_icon().AsImageSkia(); + } + } return gfx::ImageSkia(); + } // Hosted apps always show their app icon. extensions::HostedAppBrowserController* app_controller = diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index b55d68ca07d9a..e0fa812b5b204 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -230,8 +230,10 @@ void LocationBarView::Init() { new autofill::SaveCardIconView(command_updater(), browser_, this); page_action_icons_.push_back(save_credit_card_icon_view_); } +#if 0 translate_icon_view_ = new TranslateIconView(command_updater(), this); page_action_icons_.push_back(translate_icon_view_); +#endif #if defined(OS_CHROMEOS) if (browser_) @@ -443,7 +445,7 @@ gfx::Size LocationBarView::CalculatePreferredSize() const { int trailing_width = edge_thickness; if (star_view_) trailing_width += IncrementalMinimumWidth(star_view_); - trailing_width += IncrementalMinimumWidth(translate_icon_view_); + //trailing_width += IncrementalMinimumWidth(translate_icon_view_); if (save_credit_card_icon_view_) trailing_width += IncrementalMinimumWidth(save_credit_card_icon_view_); trailing_width += IncrementalMinimumWidth(manage_passwords_icon_view_) + @@ -538,7 +540,7 @@ void LocationBarView::Layout() { if (intent_picker_view_) add_trailing_decoration(intent_picker_view_); #endif - add_trailing_decoration(translate_icon_view_); + //add_trailing_decoration(translate_icon_view_); if (save_credit_card_icon_view_) add_trailing_decoration(save_credit_card_icon_view_); add_trailing_decoration(manage_passwords_icon_view_); diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc index 2d1ae56e6ab5e..324f95ac90b2c 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc @@ -161,7 +161,7 @@ void PresentationReceiverWindowView::Init() { DCHECK(web_contents); SecurityStateTabHelper::CreateForWebContents(web_contents); - ChromeTranslateClient::CreateForWebContents(web_contents); + //ChromeTranslateClient::CreateForWebContents(web_contents); autofill::ChromeAutofillClient::CreateForWebContents(web_contents); ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( web_contents, diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h index 86296c4296689..f383761e8a97b 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.h +++ b/chrome/browser/ui/views/overlay/overlay_window_views.h @@ -15,6 +15,9 @@ class ImageButton; class ToggleImageButton; } // namespace views +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" + // The Chrome desktop implementation of OverlayWindow. This will only be // implemented in views, which will support all desktop platforms. class OverlayWindowViews : public content::OverlayWindow, public views::Widget { @@ -90,4 +93,6 @@ class OverlayWindowViews : public content::OverlayWindow, public views::Widget { DISALLOW_COPY_AND_ASSIGN(OverlayWindowViews); }; +#pragma clang diagnostic pop + #endif // CHROME_BROWSER_UI_VIEWS_OVERLAY_OVERLAY_WINDOW_VIEWS_H_ diff --git a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc index 7f73dca4c6c01..52c106f367d43 100644 --- a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc +++ b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.cc @@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.h" +#include "extensions/components/native_app_window/native_app_window_views.h" + #include "base/strings/string16.h" #include "chrome/browser/chooser_controller/chooser_controller.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -22,11 +24,15 @@ namespace { constexpr views::BubbleBorder::Arrow kChooserAnchorArrow = views::BubbleBorder::TOP_LEFT; -views::View* GetChooserAnchorView(Browser* browser) { +views::View* GetChooserAnchorView(Browser* browser, extensions::AppWindow* app_window) { + if (!browser) + return nullptr; return bubble_anchor_util::GetPageInfoAnchorView(browser); } gfx::Rect GetChooserAnchorRect(Browser* browser) { + if (!browser) + return gfx::Rect(); return bubble_anchor_util::GetPageInfoAnchorRect(browser); } @@ -38,7 +44,7 @@ class ChooserBubbleUiViewDelegate : public views::BubbleDialogDelegateView, public views::TableViewObserver { public: ChooserBubbleUiViewDelegate( - Browser* browser, + Browser* browser, extensions::AppWindow* app_window, std::unique_ptr chooser_controller); ~ChooserBubbleUiViewDelegate() override; @@ -72,16 +78,17 @@ class ChooserBubbleUiViewDelegate : public views::BubbleDialogDelegateView, private: DeviceChooserContentView* device_chooser_content_view_; BubbleReference bubble_reference_; + extensions::AppWindow* app_window_; DISALLOW_COPY_AND_ASSIGN(ChooserBubbleUiViewDelegate); }; ChooserBubbleUiViewDelegate::ChooserBubbleUiViewDelegate( - Browser* browser, + Browser* browser, extensions::AppWindow* app_window, std::unique_ptr chooser_controller) - : views::BubbleDialogDelegateView(GetChooserAnchorView(browser), + : views::BubbleDialogDelegateView(GetChooserAnchorView(browser, app_window), kChooserAnchorArrow), - device_chooser_content_view_(nullptr) { + device_chooser_content_view_(nullptr), app_window_(app_window){ // ------------------------------------ // | Chooser bubble title | // | -------------------------------- | @@ -166,7 +173,7 @@ void ChooserBubbleUiViewDelegate::OnSelectionChanged() { } void ChooserBubbleUiViewDelegate::UpdateAnchor(Browser* browser) { - views::View* anchor_view = GetChooserAnchorView(browser); + views::View* anchor_view = GetChooserAnchorView(browser, app_window_); SetAnchorView(anchor_view); if (!anchor_view) SetAnchorRect(GetChooserAnchorRect(browser)); @@ -185,12 +192,13 @@ void ChooserBubbleUiViewDelegate::UpdateTableView() const { // ChooserBubbleUi ChooserBubbleUi::ChooserBubbleUi( Browser* browser, + void* app_window, std::unique_ptr chooser_controller) - : browser_(browser), chooser_bubble_ui_view_delegate_(nullptr) { - DCHECK(browser_); + : browser_(browser), app_window_((extensions::AppWindow*)app_window), chooser_bubble_ui_view_delegate_(nullptr) { + //DCHECK(browser_); DCHECK(chooser_controller); chooser_bubble_ui_view_delegate_ = - new ChooserBubbleUiViewDelegate(browser, std::move(chooser_controller)); + new ChooserBubbleUiViewDelegate(browser_, app_window_, std::move(chooser_controller)); } ChooserBubbleUi::~ChooserBubbleUi() { diff --git a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.h b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.h index af5c2878cc421..9230e84ecaf8f 100644 --- a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.h +++ b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui.h @@ -15,6 +15,10 @@ namespace views { class BubbleDialogDelegateView; } +namespace extensions { + class AppWindow; +} + class Browser; class ChooserController; class ChooserBubbleUiViewDelegate; @@ -26,7 +30,7 @@ class ChooserBubbleUiViewDelegate; // BubbleManager. class ChooserBubbleUi : public BubbleUi, public views::WidgetObserver { public: - ChooserBubbleUi(Browser* browser, + ChooserBubbleUi(Browser* browser, void* app_window, std::unique_ptr chooser_controller); ~ChooserBubbleUi() override; @@ -47,6 +51,7 @@ class ChooserBubbleUi : public BubbleUi, public views::WidgetObserver { void CreateAndShowCocoa(views::BubbleDialogDelegateView* delegate); Browser* const browser_; // Weak. + extensions::AppWindow* app_window_; // Weak. Owned by its parent view. ChooserBubbleUiViewDelegate* chooser_bubble_ui_view_delegate_; diff --git a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui_views.cc b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui_views.cc index 1e5f080e30813..61d64b18b9f2c 100644 --- a/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui_views.cc +++ b/chrome/browser/ui/views/permission_bubble/chooser_bubble_ui_views.cc @@ -8,6 +8,9 @@ #include "build/build_config.h" #include "build/buildflag.h" + +#include "extensions/components/native_app_window/native_app_window_views.h" + #include "chrome/browser/chooser_controller/chooser_controller.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -21,7 +24,7 @@ // functions provide. std::unique_ptr ChooserBubbleDelegate::BuildBubbleUi() { - return std::make_unique(browser_, + return std::make_unique(browser_, app_window_, std::move(chooser_controller_)); } @@ -32,14 +35,14 @@ void ChooserBubbleUi::CreateAndShow(views::BubbleDialogDelegateView* delegate) { return ChooserBubbleUi::CreateAndShowCocoa(delegate); #endif // Set |parent_window_| because some valid anchors can become hidden. - views::Widget* widget = views::Widget::GetWidgetForNativeWindow( + views::Widget* widget = nullptr; + if (browser_) { + widget = views::Widget::GetWidgetForNativeWindow( browser_->window()->GetNativeWindow()); gfx::NativeView parent = widget->GetNativeView(); DCHECK(parent); delegate->set_parent_window(parent); - if (browser_->window()->IsActive()) - views::BubbleDialogDelegateView::CreateBubble(delegate)->Show(); - else - views::BubbleDialogDelegateView::CreateBubble(delegate)->ShowInactive(); + } + views::BubbleDialogDelegateView::CreateBubble(delegate)->Show(); } #endif // !OS_MACOSX || MAC_VIEWS_BROWSER diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc index eed6bb2eaf756..c2b1ce79bef7d 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc @@ -10,13 +10,11 @@ StatusIconLinuxWrapper::StatusIconLinuxWrapper( std::unique_ptr status_icon) - : status_icon_(std::move(status_icon)), menu_model_(nullptr) { + : status_icon_(std::move(status_icon)) { status_icon_->set_delegate(this); } StatusIconLinuxWrapper::~StatusIconLinuxWrapper() { - if (menu_model_) - menu_model_->RemoveObserver(this); } void StatusIconLinuxWrapper::SetImage(const gfx::ImageSkia& image) { @@ -63,14 +61,6 @@ StatusIconLinuxWrapper::CreateWrappedStatusIcon( } void StatusIconLinuxWrapper::UpdatePlatformContextMenu( - StatusIconMenuModel* model) { - // If a menu already exists, remove ourself from its oberver list. - if (menu_model_) - menu_model_->RemoveObserver(this); - + ui::MenuModel* model) { status_icon_->UpdatePlatformContextMenu(model); - menu_model_ = model; - - if (model) - model->AddObserver(this); } diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h index 68704787c4650..487407ceb6202 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h @@ -44,7 +44,7 @@ class StatusIconLinuxWrapper : public StatusIcon, // Invoked after a call to SetContextMenu() to let the platform-specific // subclass update the native context menu based on the new model. If NULL is // passed, subclass should destroy the native context menu. - void UpdatePlatformContextMenu(StatusIconMenuModel* model) override; + void UpdatePlatformContextMenu(ui::MenuModel* model) override; private: // A status icon wrapper should only be created by calling @@ -57,8 +57,6 @@ class StatusIconLinuxWrapper : public StatusIcon, std::unique_ptr status_icon_; - StatusIconMenuModel* menu_model_; - DISALLOW_COPY_AND_ASSIGN(StatusIconLinuxWrapper); }; diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.cc b/chrome/browser/ui/views/status_icons/status_icon_win.cc index 96738557a56c6..0f490f4aecff2 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_win.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_win.cc @@ -43,6 +43,8 @@ StatusIconWin::~StatusIconWin() { NOTIFYICONDATA icon_data; InitIconData(&icon_data); Shell_NotifyIcon(NIM_DELETE, &icon_data); + if (tray_ && tray_->key_handler() == this) + tray_->set_key_handler(nullptr); } void StatusIconWin::HandleClickEvent(const gfx::Point& cursor_pos, @@ -65,6 +67,8 @@ void StatusIconWin::HandleClickEvent(const gfx::Point& cursor_pos, views::MenuRunner::HAS_MNEMONICS)); menu_runner_->RunMenuAt(NULL, NULL, gfx::Rect(cursor_pos, gfx::Size()), views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE); + if (tray_) + tray_->set_key_handler(this); } void StatusIconWin::HandleBalloonClickEvent() { @@ -145,7 +149,7 @@ void StatusIconWin::ForceVisible() { //////////////////////////////////////////////////////////////////////////////// // StatusIconWin, private: -void StatusIconWin::UpdatePlatformContextMenu(StatusIconMenuModel* menu) { +void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) { // |menu_model_| is about to be destroyed. Destroy the menu (which closes it) // so that it doesn't attempt to continue using |menu_model_|. menu_runner_.reset(); diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.h b/chrome/browser/ui/views/status_icons/status_icon_win.h index 05e45bc14723e..f4e8778f4ace4 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_win.h +++ b/chrome/browser/ui/views/status_icons/status_icon_win.h @@ -57,7 +57,7 @@ class StatusIconWin : public StatusIcon { protected: // Overridden from StatusIcon: - void UpdatePlatformContextMenu(StatusIconMenuModel* menu) override; + void UpdatePlatformContextMenu(ui::MenuModel* menu) override; private: void InitIconData(NOTIFYICONDATA* icon_data); diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc index c0c672ea22031..2bbe225706161 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/status_icons/status_tray_win.h" +#include "ui/views/controls/menu/menu_controller.h" #include #include @@ -101,7 +102,7 @@ class StatusTrayStateChangerProxyImpl : public StatusTrayStateChangerProxy { }; StatusTrayWin::StatusTrayWin() - : next_icon_id_(1), + : key_handler_(nullptr), next_icon_id_(1), atom_(0), instance_(NULL), window_(NULL) { @@ -211,6 +212,13 @@ LRESULT CALLBACK StatusTrayWin::WndProc(HWND hwnd, // it gets that Windows is exiting. Make sure we shutdown in an orderly // fashion. chrome::SessionEnding(); + } else if (message == WM_KEYDOWN || message == WM_KEYUP) { + MSG msg = {hwnd, message, wparam, lparam, + static_cast(GetMessageTime())}; + ui::KeyEvent key(msg); + views::MenuController* controller = views::MenuController::GetActiveInstance(); + if (controller) + controller->OnWillDispatchKeyEvent(&key); } return ::DefWindowProc(hwnd, message, wparam, lparam); } diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.h b/chrome/browser/ui/views/status_icons/status_tray_win.h index d10f023c34db4..c4ad87b559f92 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.h +++ b/chrome/browser/ui/views/status_icons/status_tray_win.h @@ -39,6 +39,9 @@ class StatusTrayWin : public StatusTray { LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + StatusIconWin* key_handler() { return key_handler_; } + void set_key_handler(StatusIconWin* win) { key_handler_ = win; } + protected: // Overriden from StatusTray: std::unique_ptr CreatePlatformStatusIcon( @@ -48,7 +51,7 @@ class StatusTrayWin : public StatusTray { private: FRIEND_TEST_ALL_PREFIXES(StatusTrayWinTest, EnsureVisibleTest); - + StatusIconWin* key_handler_; // Static callback invoked when a message comes in to our messaging window. static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 52395e265bbe0..a73a9f4c6f142 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc @@ -322,6 +322,7 @@ void ToolbarView::ShowTranslateBubble( translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) { +#if 0 views::View* anchor_view = location_bar(); PageActionIconView* translate_icon_view = location_bar()->translate_icon_view(); @@ -338,6 +339,7 @@ void ToolbarView::ShowTranslateBubble( : TranslateBubbleView::AUTOMATIC); if (bubble_widget && translate_icon_view) translate_icon_view->OnBubbleWidgetCreated(bubble_widget); +#endif } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index 53ac5890861a9..48a4263a0f36e 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc @@ -103,6 +103,7 @@ views::Widget* TranslateBubbleView::ShowBubble( translate::TranslateStep step, translate::TranslateErrors::Type error_type, DisplayReason reason) { +#if 0 if (translate_bubble_view_) { // When the user reads the advanced setting panel, the bubble should not be // changed because they are focusing on the bubble. @@ -160,6 +161,8 @@ views::Widget* TranslateBubbleView::ShowBubble( view->ShowForReason(reason); translate::ReportUiAction(translate::BUBBLE_SHOWN); return bubble_widget; +#endif + return nullptr; } // static diff --git a/chrome/browser/ui/webui/chrome_web_contents_handler.cc b/chrome/browser/ui/webui/chrome_web_contents_handler.cc index 8d2a5e65217fb..5bcc1009e054a 100644 --- a/chrome/browser/ui/webui/chrome_web_contents_handler.cc +++ b/chrome/browser/ui/webui/chrome_web_contents_handler.cc @@ -88,7 +88,7 @@ void ChromeWebContentsHandler::AddNewContents( const bool browser_created = !browser; if (!browser) { browser = new Browser( - Browser::CreateParams(Browser::TYPE_TABBED, profile, user_gesture)); + Browser::CreateParams(Browser::TYPE_POPUP, profile, user_gesture)); } NavigateParams params(browser, std::move(new_contents)); params.source_contents = source; diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 4ad61d2d8cad6..8276b4c32712d 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -175,7 +175,7 @@ #if defined(OS_WIN) #include "chrome/browser/ui/webui/conflicts_ui.h" #include "chrome/browser/ui/webui/set_as_default_browser_ui_win.h" -#include "chrome/browser/ui/webui/welcome_win10_ui.h" +//#include "chrome/browser/ui/webui/welcome_win10_ui.h" #endif #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) @@ -230,7 +230,7 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { return new T(web_ui); } -#if !defined(OS_ANDROID) +#if 0//!defined(OS_ANDROID) template <> WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { @@ -238,11 +238,13 @@ WebUIController* NewWebUI(WebUI* web_ui, } #endif +#if defined(NWJS_SDK) // Special case for older about: handlers. template<> WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { return new AboutUI(web_ui, url.host()); } +#endif #if defined(OS_CHROMEOS) template<> @@ -278,20 +280,23 @@ WebUIController* NewWebUI(WebUI* web_ui, web_ui, service, dom_distiller::kDomDistillerScheme); } -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +//#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) + +#if 0 template <> WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { return new WelcomeUI(web_ui, url); } #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) -#if defined(OS_WIN) +#if 0 template <> WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) { return new WelcomeWin10UI(web_ui, url); } #endif // defined(OS_WIN) +#if defined(NWJS_SDK) bool IsAboutUI(const GURL& url) { return (url.host_piece() == chrome::kChromeUIChromeURLsHost || url.host_piece() == chrome::kChromeUICreditsHost || @@ -307,6 +312,7 @@ bool IsAboutUI(const GURL& url) { #endif ); // NOLINT } +#endif // Returns a function that can be used to create the right type of WebUI for a // tab, based on its URL. Returns NULL if the URL doesn't have WebUI associated @@ -332,8 +338,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, // print dialog. if (url.host_piece() == chrome::kChromeUIBluetoothInternalsHost) return &NewWebUI; +#if 0 if (url.host_piece() == chrome::kChromeUIComponentsHost) return &NewWebUI; +#endif if (url.spec() == chrome::kChromeUIConstrainedHTMLTestURL) return &NewWebUI; if (url.host_piece() == chrome::kChromeUICrashesHost) @@ -348,6 +356,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; if (url.host_piece() == chrome::kChromeUIGCMInternalsHost) return &NewWebUI; +#if 0 if (url.host_piece() == chrome::kChromeUIInterstitialHost) return &NewWebUI; if (url.host_piece() == chrome::kChromeUIInterventionsInternalsHost) @@ -392,6 +401,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; if (url.host_piece() == chrome::kChromeUIUsbInternalsHost) return &NewWebUI; +#endif if (url.host_piece() == chrome::kChromeUIUserActionsHost) return &NewWebUI; if (url.host_piece() == chrome::kChromeUIVersionHost) @@ -409,6 +419,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, } #endif // defined(OS_CHROMEOS) +#if 0 if (profile->IsGuestSession() && (url.host_piece() == chrome::kChromeUIBookmarksHost || url.host_piece() == chrome::kChromeUIHistoryHost || @@ -421,6 +432,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, // Downloads list on Android uses the built-in download manager. if (url.host_piece() == chrome::kChromeUIDownloadsHost) return &NewWebUI; +#endif // Identity API is not available on Android. if (url.host_piece() == chrome::kChromeUIIdentityInternalsHost) return &NewWebUI; @@ -429,16 +441,20 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, // Settings are implemented with native UI elements on Android. if (url.host_piece() == chrome::kChromeUISettingsHost) return &NewWebUI; +#if defined(NWJS_SDK) if (url.host_piece() == chrome::kChromeUIExtensionsHost) return &NewWebUI; +#endif +#if 0 if (url.host_piece() == chrome::kChromeUIHistoryHost) return &NewWebUI; +#endif if (url.host_piece() == chrome::kChromeUISyncFileSystemInternalsHost) return &NewWebUI; if (url.host_piece() == chrome::kChromeUISystemInfoHost) return &NewWebUI; #endif // !defined(OS_ANDROID) -#if defined(OS_WIN) +#if 0 if (url.host_piece() == chrome::kChromeUIConflictsHost) return &NewWebUI; if (url.host_piece() == chrome::kChromeUIMetroFlowHost) @@ -514,6 +530,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) if (url.host_piece() == chrome::kChromeUIChromeSigninHost) return &NewWebUI; +#endif +#if 0 if (url.host_piece() == chrome::kChromeUIMdUserManagerHost) return &NewWebUI; if (url.host_piece() == chrome::kChromeUISigninErrorHost && @@ -529,7 +547,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, if (url.host_piece() == chrome::kChromeUIWelcomeHost) return &NewWebUI; #endif -#if defined(OS_WIN) +#if 0 if (url.host_piece() == chrome::kChromeUIWelcomeWin10Host) return &NewWebUI; #endif // defined(OS_WIN) @@ -564,9 +582,11 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, #endif #if BUILDFLAG(ENABLE_EXTENSIONS) +#if defined(NWJS_SDK) if (url.host_piece() == chrome::kChromeUIExtensionsFrameHost) return &NewWebUI; #endif +#endif #if BUILDFLAG(ENABLE_PLUGINS) if (url.host_piece() == chrome::kChromeUIFlashHost) return &NewWebUI; @@ -584,7 +604,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, #endif if (url.host_piece() == chrome::kChromeUIWebRtcLogsHost) return &NewWebUI; -#if !defined(OS_ANDROID) +#if defined(NWJS_SDK) if (url.host_piece() == chrome::kChromeUIMediaRouterHost && media_router::MediaRouterEnabled(profile)) { return &NewWebUI; @@ -593,24 +613,30 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, media_router::MediaRouterEnabled(profile)) { return &NewWebUI; } -#endif -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) + +#if 0 if (url.host_piece() == chrome::kChromeUICastHost && media_router::MediaRouterEnabled(profile)) { return &NewWebUI; } #endif +#endif + #if defined(OS_LINUX) || defined(OS_ANDROID) if (url.host_piece() == chrome::kChromeUISandboxHost) { return &NewWebUI; } #endif + #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) if (url.host_piece() == chrome::kChromeUIDiscardsHost) return &NewWebUI; #endif + +#if defined(NWJS_SDK) if (IsAboutUI(url)) return &NewWebUI; +#endif if (base::FeatureList::IsEnabled(features::kBundledConnectionHelpFeature) && url.host_piece() == security_interstitials::kChromeUIConnectionHelpHost) { @@ -622,10 +648,12 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI; } +#if 0 if (SiteEngagementService::IsEnabled() && url.host_piece() == chrome::kChromeUISiteEngagementHost) { return &NewWebUI; } +#endif if (MediaEngagementService::IsEnabled() && url.host_piece() == chrome::kChromeUIMediaEngagementHost) { @@ -774,8 +802,10 @@ base::RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes( if (!content::HasWebUIScheme(page_url)) return NULL; +#if 0 if (page_url.host_piece() == chrome::kChromeUIComponentsHost) return ComponentsUI::GetFaviconResourceBytes(scale_factor); +#endif #if defined(OS_WIN) if (page_url.host_piece() == chrome::kChromeUIConflictsHost) @@ -799,14 +829,17 @@ base::RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes( return AppLauncherPageUI::GetFaviconResourceBytes(scale_factor); #endif // !defined(OS_CHROMEOS) +#if 0 // Bookmarks are part of NTP on Android. if (page_url.host_piece() == chrome::kChromeUIBookmarksHost) return MdBookmarksUI::GetFaviconResourceBytes(scale_factor); +#endif // Flash is not available on android. if (page_url.host_piece() == chrome::kChromeUIFlashHost) return FlashUI::GetFaviconResourceBytes(scale_factor); +#if 0 // Android uses the native download manager. if (page_url.host_piece() == chrome::kChromeUIDownloadsHost) return MdDownloadsUI::GetFaviconResourceBytes(scale_factor); @@ -814,14 +847,16 @@ base::RefCountedMemory* ChromeWebUIControllerFactory::GetFaviconResourceBytes( // Android doesn't use the Options/Settings pages. if (page_url.host_piece() == chrome::kChromeUISettingsHost) return settings_utils::GetFaviconResourceBytes(scale_factor); +#endif // !defined(OS_ANDROID) -#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) && defined(NWJS_SDK) if (page_url.host_piece() == chrome::kChromeUIExtensionsHost || page_url.host_piece() == chrome::kChromeUIExtensionsFrameHost) { return extensions::ExtensionsUI::GetFaviconResourceBytes(scale_factor); } #endif // BUILDFLAG(ENABLE_EXTENSIONS) -#endif // !defined(OS_ANDROID) + +#endif return NULL; } diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service.cc b/chrome/browser/ui/webui/media_router/media_router_ui_service.cc index 99597ff78cb29..b5f592ffc53fe 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui_service.cc +++ b/chrome/browser/ui/webui/media_router/media_router_ui_service.cc @@ -11,12 +11,18 @@ namespace media_router { MediaRouterUIService::MediaRouterUIService(Profile* profile) +#if defined(NWJS_SDK) : action_controller_(new MediaRouterActionController(profile)) {} +#else + {} +#endif MediaRouterUIService::~MediaRouterUIService() {} void MediaRouterUIService::Shutdown() { +#if defined(NWJS_SDK) action_controller_.reset(); +#endif } // static @@ -25,7 +31,11 @@ MediaRouterUIService* MediaRouterUIService::Get(Profile* profile) { } MediaRouterActionController* MediaRouterUIService::action_controller() { +#if defined(NWJS_SDK) return action_controller_.get(); +#else + return nullptr; +#endif } } // namespace media_router diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service.h b/chrome/browser/ui/webui/media_router/media_router_ui_service.h index 5a4c3338f5cad..4b7798bd81b4a 100644 --- a/chrome/browser/ui/webui/media_router/media_router_ui_service.h +++ b/chrome/browser/ui/webui/media_router/media_router_ui_service.h @@ -30,7 +30,9 @@ class MediaRouterUIService : public KeyedService { private: friend class MediaRouterUIBrowserTest; +#if defined(NWJS_SDK) std::unique_ptr action_controller_; +#endif DISALLOW_COPY_AND_ASSIGN(MediaRouterUIService); }; diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc index a09caf9445320..b39550e7a2c46 100644 --- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc @@ -40,6 +40,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/geometry/size.h" +#include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" + namespace { constexpr base::FilePath::CharType kPdfExtension[] = FILE_PATH_LITERAL("pdf"); @@ -187,6 +189,10 @@ void PdfPrinterHandler::StartPrint( const scoped_refptr& print_data, PrintCallback callback) { print_data_ = print_data; + if (!chrome::NWPrintGetPDFPath().empty() && chrome::NWPrintGetCustomPrinting()) { + print_to_pdf_path_ = chrome::NWPrintGetPDFPath(); + print_callback_ = std::move(callback); + } if (!print_to_pdf_path_.empty()) { // User has already selected a path, no need to show the dialog again. PostPrintToPdfTask(); diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 07e885d8b1946..d39bf04e25a84 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" +#include "base/json/json_writer.h" #include #include @@ -95,6 +96,12 @@ constexpr size_t kMaxCloudPrintPdfDataSizeInBytes = 80 * 1024 * 1024 / 2; // This enum is used to back an UMA histogram, and should therefore be treated // as append only. +CR_DEFINE_STATIC_LOCAL(std::string, g_nw_printer_name, ()); +CR_DEFINE_STATIC_LOCAL(base::FilePath, g_nw_print_to_pdf_path, ()); +CR_DEFINE_STATIC_LOCAL(std::unique_ptr, g_nw_print_options, ()); + +bool g_nw_custom_printing = false; + enum UserActionBuckets { PRINT_TO_PRINTER, PRINT_TO_PDF, @@ -411,6 +418,32 @@ printing::StickySettings* GetStickySettings() { } // namespace +namespace chrome { +void NWPrintSetCustomPrinting(bool value) { + g_nw_custom_printing = value; +} + +bool NWPrintGetCustomPrinting() { + return g_nw_custom_printing; +} + +void NWPrintSetOptions(const base::DictionaryValue* dict) { + g_nw_print_options = dict->CreateDeepCopy(); +} + +void NWPrintSetPDFPath(const base::FilePath& path) { + g_nw_print_to_pdf_path = path; +} + +const base::FilePath& NWPrintGetPDFPath() { + return g_nw_print_to_pdf_path; +} + +void NWPrintSetDefaultPrinter(const std::string& printer_name) { + g_nw_printer_name = printer_name; +} +} + class PrintPreviewHandler::AccessTokenService : public OAuth2TokenService::Consumer { public: @@ -708,6 +741,32 @@ void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) { bool success = settings->GetBoolean(printing::kSettingHeaderFooterEnabled, &display_header_footer); DCHECK(success); + std::string footer_string, header_string; + if (g_nw_print_options) { + bool landscape, backgrounds; + int margins_type; + int scale; + base::DictionaryValue* media_size_value = nullptr; + base::DictionaryValue* custom_margins = nullptr; + + if (g_nw_print_options->GetDictionary(printing::kSettingMediaSize, &media_size_value) && !media_size_value->empty()) + settings->Set(printing::kSettingMediaSize, media_size_value->CreateDeepCopy()); + if (g_nw_print_options->GetBoolean(printing::kSettingHeaderFooterEnabled, &display_header_footer)) + settings->SetBoolean(printing::kSettingHeaderFooterEnabled, display_header_footer); + if (g_nw_print_options->GetBoolean(printing::kSettingLandscape, &landscape)) + settings->SetBoolean(printing::kSettingLandscape, landscape); + if (g_nw_print_options->GetBoolean(printing::kSettingShouldPrintBackgrounds, &backgrounds)) + settings->SetBoolean(printing::kSettingShouldPrintBackgrounds, backgrounds); + if (g_nw_print_options->GetInteger(printing::kSettingMarginsType, &margins_type)) + settings->SetInteger(printing::kSettingMarginsType, margins_type); + if (g_nw_print_options->GetDictionary(printing::kSettingMarginsCustom, &custom_margins) && !custom_margins->empty()) + settings->Set(printing::kSettingMarginsCustom, custom_margins->CreateDeepCopy()); + if (g_nw_print_options->GetInteger(printing::kSettingScaleFactor, &scale)) + settings->SetInteger(printing::kSettingScaleFactor, scale); + g_nw_print_options->GetString("footerString", &footer_string); + g_nw_print_options->GetString("headerString", &header_string); + } + if (display_header_footer) { settings->SetString(printing::kSettingHeaderFooterTitle, initiator->GetTitle()); @@ -716,8 +775,13 @@ void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) { url_sanitizer.ClearUsername(); url_sanitizer.ClearPassword(); const GURL& initiator_url = initiator->GetLastCommittedURL(); - settings->SetString(printing::kSettingHeaderFooterURL, - initiator_url.ReplaceComponents(url_sanitizer).spec()); + if (footer_string.empty()) + settings->SetString(printing::kSettingHeaderFooterURL, + initiator_url.ReplaceComponents(url_sanitizer).spec()); + else + settings->SetString(printing::kSettingHeaderFooterURL, footer_string); + if (!header_string.empty()) + settings->SetString(printing::kSettingHeaderFooterTitle, header_string); } VLOG(1) << "Print preview request start"; @@ -736,6 +800,8 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { std::string json_str; CHECK(args->GetString(1, &json_str)); + int copies; + std::unique_ptr settings = GetSettingsDictionary(json_str); if (!settings) { @@ -744,6 +810,21 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { } const UserActionBuckets user_action = DetermineUserAction(*settings); + if (g_nw_print_options) { + base::ListValue* page_range_array = nullptr; + bool changed = false; + + if (g_nw_print_options->GetList(printing::kSettingPageRange, &page_range_array) && !page_range_array->empty()) { + changed = true; + settings->Set(printing::kSettingPageRange, page_range_array->CreateDeepCopy()); + } + if (g_nw_print_options->GetInteger(printing::kSettingCopies, &copies)) { + changed = true; + settings->SetInteger(printing::kSettingCopies, copies); + } + if (changed) + base::JSONWriter::Write(*settings, &json_str); + } int page_count = 0; if (!settings->GetInteger(printing::kSettingPreviewPageCount, &page_count) || @@ -815,6 +896,7 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { gfx::Size(width, height), data, base::BindOnce(&PrintPreviewHandler::OnPrintResult, weak_factory_.GetWeakPtr(), callback_id)); + chrome::NWPrintSetCustomPrinting(false); } void PrintPreviewHandler::HandleHidePreview(const base::ListValue* /*args*/) { @@ -985,7 +1067,7 @@ void PrintPreviewHandler::SendInitialSettings( print_preview_ui()->initiator_title()); initial_settings.SetBoolean(printing::kSettingPreviewModifiable, print_preview_ui()->source_is_modifiable()); - initial_settings.SetString(printing::kSettingPrinterName, default_printer); + initial_settings.SetString(printing::kSettingPrinterName, g_nw_printer_name.empty() ? default_printer : g_nw_printer_name); initial_settings.SetBoolean(kDocumentHasSelection, print_preview_ui()->source_has_selection()); initial_settings.SetBoolean(printing::kSettingShouldPrintSelectionOnly, @@ -1003,9 +1085,12 @@ void PrintPreviewHandler::SendInitialSettings( base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); initial_settings.SetBoolean(kIsInKioskAutoPrintMode, - cmdline->HasSwitch(switches::kKioskModePrinting)); + cmdline->HasSwitch(switches::kKioskModePrinting) || g_nw_custom_printing); initial_settings.SetBoolean(kIsInAppKioskMode, chrome::IsRunningInForcedAppMode()); + initial_settings.SetBoolean("nwPrintMode", g_nw_custom_printing); + if (g_nw_custom_printing || !g_nw_printer_name.empty()) + initial_settings.SetKey(kAppState, base::Value()); bool set_rules = false; if (prefs) { const std::string rules_str = diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 27d7caa30c3af..771105ccf128f 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h @@ -28,6 +28,18 @@ class PrintPreviewUI; namespace base { class DictionaryValue; class RefCountedMemory; +class ListValue; +} + +namespace chrome { + void PrintersToValues(const printing::PrinterList& printer_list, + base::ListValue* printers); + void NWPrintSetCustomPrinting(bool value); + bool NWPrintGetCustomPrinting(); + void NWPrintSetDefaultPrinter(const std::string& printer_name); + void NWPrintSetPDFPath(const base::FilePath& path); + const base::FilePath& NWPrintGetPDFPath(); + void NWPrintSetOptions(const base::DictionaryValue* dict); } namespace content { diff --git a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc index 6d8dc9b06a1d2..6eb6c6fe4dd28 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc @@ -39,19 +39,22 @@ const char kTypeKey[] = "type"; // The dictionary key for the CDD item containing custom vendor capabilities. const char kVendorCapabilityKey[] = "vendor_capability"; -namespace { +} + + +namespace chrome { -void PrintersToValues(const PrinterList& printer_list, +void PrintersToValues(const printing::PrinterList& printer_list, base::ListValue* printers) { - for (const PrinterBasicInfo& printer : printer_list) { + for (const printing::PrinterBasicInfo& printer : printer_list) { auto printer_info = std::make_unique(); - printer_info->SetString(kSettingDeviceName, printer.printer_name); + printer_info->SetString(printing::kSettingDeviceName, printer.printer_name); const auto printer_name_description = GetPrinterNameAndDescription(printer); const std::string& printer_name = printer_name_description.first; const std::string& printer_description = printer_name_description.second; - printer_info->SetString(kSettingPrinterName, printer_name); - printer_info->SetString(kSettingPrinterDescription, printer_description); + printer_info->SetString(printing::kSettingPrinterName, printer_name); + printer_info->SetString(printing::kSettingPrinterDescription, printer_description); auto options = std::make_unique(); for (const auto opt_it : printer.options) @@ -62,7 +65,7 @@ void PrintersToValues(const PrinterList& printer_list, base::ContainsKey(printer.options, kCUPSEnterprisePrinter) && printer.options.at(kCUPSEnterprisePrinter) == kValueTrue); - printer_info->Set(kSettingPrinterOptions, std::move(options)); + printer_info->Set(printing::kSettingPrinterOptions, std::move(options)); printers->Append(std::move(printer_info)); @@ -71,6 +74,9 @@ void PrintersToValues(const PrinterList& printer_list, } } +} // namespace chrome + +namespace printing { template base::Value GetFilteredList(const base::Value* list, Predicate pred) { auto out_list = list->Clone(); @@ -108,8 +114,6 @@ void SystemDialogDone(const base::Value& error) { // intentional no-op } -} // namespace - std::unique_ptr ValidateCddForPrintPreview( const base::DictionaryValue& cdd) { auto validated_cdd = @@ -134,8 +138,8 @@ std::unique_ptr ValidateCddForPrintPreview( } bool is_vendor_capability = key == kVendorCapabilityKey; - base::Value out_list = GetFilteredList( - list, is_vendor_capability ? VendorCapabilityInvalid : ValueIsNull); + base::Value out_list = printing::GetFilteredList( + list, is_vendor_capability ? printing::VendorCapabilityInvalid : printing::ValueIsNull); if (out_list.GetList().empty()) // leave out empty lists. continue; if (is_vendor_capability) { @@ -151,7 +155,7 @@ std::unique_ptr ValidateCddForPrintPreview( const base::Value* options_list = options_dict->FindKeyOfType(kOptionKey, base::Value::Type::LIST); options_dict->SetKey(kOptionKey, - GetFilteredList(options_list, ValueIsNull)); + printing::GetFilteredList(options_list, printing::ValueIsNull)); } } if (value.is_dict()) { @@ -171,7 +175,7 @@ void ConvertPrinterListForCallback( PrinterHandler::GetPrintersDoneCallback done_callback, const PrinterList& printer_list) { base::ListValue printers; - PrintersToValues(printer_list, &printers); + chrome::PrintersToValues(printer_list, &printers); VLOG(1) << "Enumerate printers finished, found " << printers.GetSize() << " printers"; @@ -205,14 +209,14 @@ void StartLocalPrint(const std::string& ticket_json, } bool system_dialog = false; - job_settings->GetBoolean(printing::kSettingShowSystemDialog, &system_dialog); + job_settings->GetBoolean(kSettingShowSystemDialog, &system_dialog); bool open_in_pdf = false; - job_settings->GetBoolean(printing::kSettingOpenPDFInPreview, &open_in_pdf); + job_settings->GetBoolean(kSettingOpenPDFInPreview, &open_in_pdf); if (system_dialog || open_in_pdf) { // Run the callback early, or the modal dialogs will prevent the preview // from closing until they do. std::move(callback).Run(base::Value()); - callback = base::BindOnce(&SystemDialogDone); + callback = base::BindOnce(&printing::SystemDialogDone); } print_view_manager->PrintForPrintPreview(std::move(job_settings), print_data, preview_web_contents->GetMainFrame(), diff --git a/chrome/browser/ui/webui/settings/change_password_handler.cc b/chrome/browser/ui/webui/settings/change_password_handler.cc index 6d64f7bbd087c..9eba5cad737f5 100644 --- a/chrome/browser/ui/webui/settings/change_password_handler.cc +++ b/chrome/browser/ui/webui/settings/change_password_handler.cc @@ -52,18 +52,22 @@ void ChangePasswordHandler::HandleInitialize(const base::ListValue* args) { } void ChangePasswordHandler::HandleChangePassword(const base::ListValue* args) { +#if 0 service_->OnUserAction( web_ui()->GetWebContents(), safe_browsing::PasswordProtectionService::CHROME_SETTINGS, safe_browsing::PasswordProtectionService::CHANGE_PASSWORD); +#endif } void ChangePasswordHandler::UpdateChangePasswordCardVisibility() { +#if 0 FireWebUIListener( "change-password-visibility", base::Value(service_->IsWarningEnabled() && safe_browsing::ChromePasswordProtectionService:: ShouldShowChangePasswordSettingUI(profile_))); +#endif } } // namespace settings diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index c7ca00e9642c2..2f786f688952c 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc @@ -135,6 +135,7 @@ void MdSettingsUI::RegisterProfilePrefs( MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) : content::WebUIController(web_ui), WebContentsObserver(web_ui->GetWebContents()) { +#if 0 #if BUILDFLAG(OPTIMIZE_WEBUI) std::vector exclude_from_gzip; #endif @@ -357,6 +358,7 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), html_source); +#endif } MdSettingsUI::~MdSettingsUI() { diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 75d91f07c7cdb..92b14e8b93ecc 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc @@ -709,6 +709,7 @@ void PeopleHandler::HandleStartSignin(const base::ListValue* args) { } void PeopleHandler::HandleStopSyncing(const base::ListValue* args) { +#if 0 bool delete_profile = false; args->GetBoolean(0, &delete_profile); @@ -727,6 +728,7 @@ void PeopleHandler::HandleStopSyncing(const base::ListValue* args) { webui::DeleteProfileAtPath(profile_->GetPath(), ProfileMetrics::DELETE_PROFILE_SETTINGS); } +#endif } #endif diff --git a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc index 366846e0b5d20..42e56f6c3d884 100644 --- a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc +++ b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc @@ -127,6 +127,7 @@ void TranslateInternalsHandler::OnTranslateEvent( } void TranslateInternalsHandler::OnRemovePrefItem(const base::ListValue* args) { +#if 0 content::WebContents* web_contents = web_ui()->GetWebContents(); Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); @@ -162,6 +163,7 @@ void TranslateInternalsHandler::OnRemovePrefItem(const base::ListValue* args) { } SendPrefsToJs(); +#endif } void TranslateInternalsHandler::OnOverrideCountry(const base::ListValue* args) { diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index 9a680cc59b575..3320b28b3ccd6 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc @@ -140,7 +140,7 @@ namespace web_app { // for the name of this directory. Hosts can't include an underscore. // By starting this string with an underscore, we ensure that there // are no naming conflicts. -static const char kCrxAppPrefix[] = "_crx_"; +static const char kCrxAppPrefix[] = "_nwjs_"; namespace internals { diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc index 2b245b28a966d..300f885f8092c 100644 --- a/chrome/browser/web_applications/web_app_win.cc +++ b/chrome/browser/web_applications/web_app_win.cc @@ -337,17 +337,22 @@ void CreateIconAndSetRelaunchDetails( const base::FilePath& icon_file, HWND hwnd, const web_app::ShortcutInfo& shortcut_info) { - base::CommandLine command_line = + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); +#if 0 shell_integration::CommandLineArgsForLauncher(shortcut_info.url, shortcut_info.extension_id, shortcut_info.profile_path); - +#endif base::FilePath chrome_exe; if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) { NOTREACHED(); return; } command_line.SetProgram(chrome_exe); + const base::CommandLine::StringVector& args = base::CommandLine::ForCurrentProcess()->GetArgs(); + if (args.size()) + command_line.AppendArgNative(args[0]); + ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(), shortcut_info.title, hwnd); diff --git a/chrome/browser/win/app_icon.cc b/chrome/browser/win/app_icon.cc index ab3d600a5ffaa..0cac88309363f 100644 --- a/chrome/browser/win/app_icon.cc +++ b/chrome/browser/win/app_icon.cc @@ -4,6 +4,8 @@ #include "chrome/browser/win/app_icon.h" +#include "content/nw/src/nw_content.h" + #include "chrome/common/chrome_constants.h" #include "chrome/install_static/install_details.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -21,6 +23,11 @@ int GetAppIconResourceId() { } // namespace HICON GetAppIcon() { +#if 0 + HICON ret = nw::GetWindowHIcon(); + if (ret) + return ret; +#endif // TODO(mgiuca): Use GetAppIconImageFamily/CreateExact instead of LoadIcon, to // get correct scaling. (See http://crbug.com/551256) const int icon_id = GetAppIconResourceId(); @@ -30,6 +37,11 @@ HICON GetAppIcon() { } HICON GetSmallAppIcon() { +#if 0 + HICON ret = nw::GetAppHIcon(); + if (ret) + return ret; +#endif // TODO(mgiuca): Use GetAppIconImageFamily/CreateExact instead of LoadIcon, to // get correct scaling. (See http://crbug.com/551256) const int icon_id = GetAppIconResourceId(); diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index fde31eb044edf..717cc7a49538d 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni @@ -75,7 +75,7 @@ template("chrome_repack_percent") { deps += [ "//ui/app_list/resources" ] } - output = "${invoker.output_dir}/chrome_${percent}_percent.pak" + output = "${invoker.output_dir}/nw_${percent}_percent.pak" } } @@ -98,7 +98,6 @@ template("chrome_extra_paks") { "$root_gen_dir/chrome/task_scheduler_internals_resources.pak", "$root_gen_dir/chrome/translate_internals_resources.pak", "$root_gen_dir/components/components_resources.pak", - "$root_gen_dir/content/browser/tracing/tracing_resources.pak", "$root_gen_dir/content/content_resources.pak", "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak", "$root_gen_dir/net/net_resources.pak", @@ -128,6 +127,12 @@ template("chrome_extra_paks") { if (defined(invoker.additional_paks)) { sources += invoker.additional_paks } + if (nwjs_sdk) { + sources += [ + "$root_gen_dir/content/browser/tracing/tracing_resources.pak", + "$root_gen_dir/content/browser/devtools/devtools_resources.pak", + ] + } if (is_android) { sources += [ "$root_gen_dir/chrome/webapks_ui_resources.pak" ] @@ -137,7 +142,6 @@ template("chrome_extra_paks") { sources += [ "$root_gen_dir/chrome/component_extension_resources.pak", "$root_gen_dir/chrome/settings_resources.pak", - "$root_gen_dir/content/browser/devtools/devtools_resources.pak", "$root_gen_dir/headless/headless_lib_resources.pak", ] deps += [ diff --git a/chrome/chrome_watcher/BUILD.gn b/chrome/chrome_watcher/BUILD.gn index c47f8a8b78243..5a1722bf9131b 100644 --- a/chrome/chrome_watcher/BUILD.gn +++ b/chrome/chrome_watcher/BUILD.gn @@ -48,6 +48,7 @@ process_version_rc_template("chrome_watcher_resources") { } shared_library("chrome_watcher") { + output_name = "nw_watcher" sources = [ "chrome_watcher_main.cc", ] diff --git a/chrome/chrome_watcher/chrome_watcher.def b/chrome/chrome_watcher/chrome_watcher.def index 463248f7de1d4..a9b6344f8b22a 100644 --- a/chrome/chrome_watcher/chrome_watcher.def +++ b/chrome/chrome_watcher/chrome_watcher.def @@ -2,7 +2,7 @@ ; Use of this source code is governed by a BSD-style license that can be ; found in the LICENSE file. -LIBRARY "chrome_watcher.dll" +LIBRARY "nw_watcher.dll" EXPORTS WatcherMain diff --git a/chrome/chrome_watcher/chrome_watcher_main.cc b/chrome/chrome_watcher/chrome_watcher_main.cc index 5d65ba001114f..4e1e80ed6da72 100644 --- a/chrome/chrome_watcher/chrome_watcher_main.cc +++ b/chrome/chrome_watcher/chrome_watcher_main.cc @@ -400,9 +400,7 @@ extern "C" int WatcherMain(const base::char16* registry_path, base::AtExitManager exit_manager; // Initialize the commandline singleton from the environment. base::CommandLine::Init(0, nullptr); - const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); - logging::InitChromeWatcherLogging(cmd_line, logging::APPEND_TO_OLD_LOG_FILE); logging::LogEventProvider::Initialize(kChromeWatcherTraceProviderName); // Arrange to be shut down as late as possible, as we want to outlive @@ -413,6 +411,7 @@ extern "C" int WatcherMain(const base::char16* registry_path, base::EnableTerminationOnHeapCorruption(); base::EnableTerminationOnOutOfMemory(); base::win::RegisterInvalidParamHandler(); + const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); base::win::SetupCRT(cmd_line); // Run a UI message loop on the main thread. diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index b45794f858d4f..f8fbb267db7a7 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn @@ -195,6 +195,8 @@ static_library("common") { "web_application_info_provider_param_traits.h", "webui_url_constants.cc", "webui_url_constants.h", + "safe_browsing/pe_image_reader_win.cc", + "safe_browsing/pe_image_reader_win.h", ] defines = [] @@ -250,8 +252,8 @@ static_library("common") { "//components/safe_browsing/web_ui:constants", "//components/services/heap_profiling/public/cpp", "//components/strings", - "//components/translate/content/common", - "//components/translate/core/common", + #"//components/translate/content/common", + #"//components/translate/core/common", "//components/url_formatter", "//components/variations", "//components/visitedlink/common", @@ -366,6 +368,7 @@ static_library("common") { ] public_deps += [ "//chrome/common/extensions:mojo_bindings", + "//content/nw/src/api:nw_api", "//chrome/common/extensions/api", "//chrome/common/extensions/api:extensions_features", "//device/usb", diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc index 6bee95004b6d7..32b4931428b15 100644 --- a/chrome/common/child_process_logging_win.cc +++ b/chrome/common/child_process_logging_win.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/common/child_process_logging.h" +#include "chrome_elf/chrome_elf_main.h" #include diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index d4e0823a55994..c509b9a0eab10 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -10,11 +10,11 @@ #define FPL FILE_PATH_LITERAL #if defined(OS_MACOSX) -#define CHROMIUM_PRODUCT_STRING "Chromium" +#define CHROMIUM_PRODUCT_STRING "nwjs" #if defined(GOOGLE_CHROME_BUILD) #define PRODUCT_STRING "Google Chrome" #elif defined(CHROMIUM_BUILD) -#define PRODUCT_STRING "Chromium" +#define PRODUCT_STRING "nwjs" #else #error Unknown branding #endif @@ -43,13 +43,13 @@ const char kChromeVersion[] = CHROME_VERSION_STRING; #if defined(OS_WIN) const base::FilePath::CharType kBrowserProcessExecutableNameChromium[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kBrowserProcessExecutableName[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kHelperProcessExecutableNameChromium[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kHelperProcessExecutableName[] = - FPL("chrome.exe"); + FPL("nw.exe"); #elif defined(OS_MACOSX) const base::FilePath::CharType kBrowserProcessExecutableNameChromium[] = FPL(CHROMIUM_PRODUCT_STRING); @@ -69,8 +69,8 @@ const base::FilePath::CharType kHelperProcessExecutableName[] = const base::FilePath::CharType kHelperProcessExecutableNameChromium[] = FPL(""); #elif defined(OS_POSIX) const base::FilePath::CharType kBrowserProcessExecutableNameChromium[] = - FPL("chrome"); -const base::FilePath::CharType kBrowserProcessExecutableName[] = FPL("chrome"); + FPL("nw"); +const base::FilePath::CharType kBrowserProcessExecutableName[] = FPL("nw"); // Helper processes end up with a name of "exe" due to execing via // /proc/self/exe. See bug 22703. const base::FilePath::CharType kHelperProcessExecutableNameChromium[] = @@ -80,13 +80,13 @@ const base::FilePath::CharType kHelperProcessExecutableName[] = FPL("exe"); #if defined(OS_WIN) const base::FilePath::CharType kBrowserProcessExecutablePathChromium[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kBrowserProcessExecutablePath[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kHelperProcessExecutablePathChromium[] = - FPL("chrome.exe"); + FPL("nw.exe"); const base::FilePath::CharType kHelperProcessExecutablePath[] = - FPL("chrome.exe"); + FPL("nw.exe"); #elif defined(OS_MACOSX) const base::FilePath::CharType kBrowserProcessExecutablePathChromium[] = FPL(CHROMIUM_PRODUCT_STRING ".app/Contents/MacOS/" CHROMIUM_PRODUCT_STRING); @@ -101,15 +101,15 @@ const base::FilePath::CharType kHelperProcessExecutablePath[] = const base::FilePath::CharType kBrowserProcessExecutablePath[] = FPL("chrome"); const base::FilePath::CharType kHelperProcessExecutablePath[] = FPL("chrome"); const base::FilePath::CharType kBrowserProcessExecutablePathChromium[] = - FPL("chrome"); + FPL("nw"); const base::FilePath::CharType kHelperProcessExecutablePathChromium[] = - FPL("chrome"); + FPL("nw"); #elif defined(OS_POSIX) const base::FilePath::CharType kBrowserProcessExecutablePathChromium[] = - FPL("chrome"); + FPL("nw"); const base::FilePath::CharType kBrowserProcessExecutablePath[] = FPL("chrome"); const base::FilePath::CharType kHelperProcessExecutablePathChromium[] = - FPL("chrome"); + FPL("nw"); const base::FilePath::CharType kHelperProcessExecutablePath[] = FPL("chrome"); #endif // OS_* @@ -121,9 +121,9 @@ const base::FilePath::CharType kFrameworkExecutableName[] = #endif // OS_MACOSX #if defined(OS_WIN) -const base::FilePath::CharType kBrowserResourcesDll[] = FPL("chrome.dll"); +const base::FilePath::CharType kBrowserResourcesDll[] = FPL("nw.dll"); const base::FilePath::CharType kStatusTrayWindowClass[] = - FPL("Chrome_StatusTrayWindow"); + FPL("NWJS_StatusTrayWindow"); #endif // defined(OS_WIN) const char kInitialProfile[] = "Default"; diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index 231520b1bb177..c5a64dd4cfba2 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc @@ -4,6 +4,7 @@ #include "chrome/common/chrome_content_client.h" +#include "components/crash/content/app/crash_reporter_client.h" #include #include @@ -107,6 +108,8 @@ #include "chrome/common/media/chrome_media_drm_bridge_client.h" #endif +#include "content/nw/src/common/nw_content_common_hooks.h" + namespace { #if BUILDFLAG(ENABLE_PLUGINS) @@ -369,6 +372,53 @@ bool GetComponentUpdatedPepperFlash(content::PepperPluginInfo* plugin) { } #endif // defined(OS_CHROMEOS) +#if 1 +// This should be used on ChromeOS only - other platforms do not bundle Flash. +bool GetBundledPepperFlash(content::PepperPluginInfo* plugin) { +#if 1 + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + // Ignore bundled Pepper Flash if there is Pepper Flash specified from the + // command-line. + if (command_line->HasSwitch(switches::kPpapiFlashPath)) + return false; + + bool force_disable = + command_line->HasSwitch(switches::kDisableBundledPpapiFlash); + if (force_disable) + return false; + + base::FilePath flash_path; + if (!base::PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN, &flash_path)) + return false; + base::FilePath flash_filename; + if (!base::PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &flash_filename)) + return false; + base::FilePath manifest_path( + flash_path.AppendASCII("manifest.json")); + + std::string manifest_data; + if (!base::ReadFileToString(manifest_path, &manifest_data)) + return false; + std::unique_ptr manifest_value( + base::JSONReader::Read(manifest_data, base::JSON_ALLOW_TRAILING_COMMAS)); + if (!manifest_value.get()) + return false; + base::DictionaryValue* manifest = NULL; + if (!manifest_value->GetAsDictionary(&manifest)) + return false; + + base::Version version; + if (!CheckPepperFlashManifest(*manifest, &version)) + return false; + *plugin = CreatePepperFlashInfo(flash_filename, version.GetString(), false); + return true; +#else + return false; +#endif // FLAPPER_AVAILABLE +} +#endif // defined(OS_CHROMEOS) + bool GetSystemPepperFlash(content::PepperPluginInfo* plugin) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); // Do not try and find System Pepper Flash if there is a specific path on @@ -400,6 +450,10 @@ std::string GetUserAgent() { LOG(WARNING) << "Ignored invalid value for flag --" << switches::kUserAgent; } + std::string user_agent; + if (nw::GetUserAgentFromManifest(&user_agent)) { + return user_agent; + } std::string product = GetProduct(); #if defined(OS_ANDROID) if (command_line->HasSwitch(switches::kUseMobileUserAgent)) @@ -445,6 +499,11 @@ void ChromeContentClient::SetActiveURL(const GURL& url, top_origin_key.Set(top_origin); } +void ChromeContentClient::SetNWReportURL(const GURL& url) { + static crash_reporter::CrashKeyString<1024> nwjs_url("url-nwjs"); + nwjs_url.Set(url.possibly_invalid_spec()); +} + void ChromeContentClient::SetGpuInfo(const gpu::GPUInfo& gpu_info) { gpu::SetKeysForCrashLogging(gpu_info); } @@ -501,6 +560,13 @@ void ChromeContentClient::AddPepperPlugins( if (GetCommandLinePepperFlash(command_line_flash.get())) flash_versions.push_back(std::move(command_line_flash)); + //NWJS: revert 00777c52ac61dba4cd3d9047ede488f337d4a9a5 +#if 1 + auto bundled_flash = std::make_unique(); + if (GetBundledPepperFlash(bundled_flash.get())) + flash_versions.push_back(std::move(bundled_flash)); +#endif // defined(OS_CHROMEOS) + auto system_flash = std::make_unique(); if (GetSystemPepperFlash(system_flash.get())) flash_versions.push_back(std::move(system_flash)); diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h index 3258d3a8250f8..210bfffed0f2c 100644 --- a/chrome/common/chrome_content_client.h +++ b/chrome/common/chrome_content_client.h @@ -70,6 +70,7 @@ class ChromeContentClient : public content::ContentClient { #endif void SetActiveURL(const GURL& url, std::string top_origin) override; + void SetNWReportURL(const GURL& url) override; void SetGpuInfo(const gpu::GPUInfo& gpu_info) override; void AddPepperPlugins( std::vector* plugins) override; diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 49b56bdb031c4..f3bd3e923b3d3 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc @@ -353,7 +353,7 @@ bool PathProvider(int key, base::FilePath* result) { // was shipped along with chrome. The value can be overridden // if it is installed via component updater. case chrome::DIR_PNACL_COMPONENT: -#if defined(OS_MACOSX) +#if 0 // PNaCl really belongs in the InternalPluginsDirectory but actually // copying it there would result in the files also being shipped, which // we don't want yet. So for now, just find them in the directory where diff --git a/chrome/common/chrome_paths_linux.cc b/chrome/common/chrome_paths_linux.cc index 5659ef5d6f977..0032213da08c3 100644 --- a/chrome/common/chrome_paths_linux.cc +++ b/chrome/common/chrome_paths_linux.cc @@ -16,6 +16,8 @@ #include "chrome/common/channel_info.h" #include "chrome/common/chrome_paths_internal.h" +#include "content/nw/src/nw_base.h" + namespace chrome { using base::nix::GetXDGDirectory; @@ -90,7 +92,7 @@ bool GetDefaultUserDataDirectory(base::FilePath* result) { #if defined(GOOGLE_CHROME_BUILD) *result = config_dir.Append("google-chrome" + GetChannelSuffixForDataDir()); #else - *result = config_dir.Append("chromium"); + *result = config_dir.Append(nw::package()->GetName()); #endif return true; } diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm index 406298ba2b335..865ed4c2ac33f 100644 --- a/chrome/common/chrome_paths_mac.mm +++ b/chrome/common/chrome_paths_mac.mm @@ -18,6 +18,8 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths_internal.h" +#include "content/nw/src/nw_base.h" + namespace { const base::FilePath* g_override_versioned_directory = NULL; @@ -59,7 +61,7 @@ #if defined(GOOGLE_CHROME_BUILD) product_dir_name = "Google/Chrome"; #else - product_dir_name = "Chromium"; + product_dir_name = "nwjs"; #endif } @@ -68,6 +70,7 @@ return strdup(product_dir_name); } +#if 0 // ProductDirName returns the name of the directory inside // ~/Library/Application Support that should hold the product application // data. This can be overridden by setting the CrProductDirName key in the @@ -89,6 +92,7 @@ ProductDirNameForBundle(chrome::OuterAppBundle()); return std::string(product_dir_name); } +#endif bool GetDefaultUserDataDirectoryForProduct(const std::string& product_dir, base::FilePath* result) { @@ -105,7 +109,7 @@ bool GetDefaultUserDataDirectoryForProduct(const std::string& product_dir, namespace chrome { bool GetDefaultUserDataDirectory(base::FilePath* result) { - return GetDefaultUserDataDirectoryForProduct(ProductDirName(), result); + return GetDefaultUserDataDirectoryForProduct(nw::package()->GetName(), result); } bool GetUserDocumentsDirectory(base::FilePath* result) { diff --git a/chrome/common/chrome_paths_win.cc b/chrome/common/chrome_paths_win.cc index b137ad00d8b90..38f6b524d1a67 100644 --- a/chrome/common/chrome_paths_win.cc +++ b/chrome/common/chrome_paths_win.cc @@ -19,6 +19,8 @@ #include "chrome/install_static/install_util.h" #include "components/nacl/common/nacl_switches.h" +#include "content/nw/src/nw_base.h" + namespace chrome { namespace { @@ -45,7 +47,8 @@ bool GetUserDirectory(int csidl_folder, base::FilePath* result) { bool GetDefaultUserDataDirectory(base::FilePath* result) { if (!base::PathService::Get(base::DIR_LOCAL_APP_DATA, result)) return false; - *result = result->Append(install_static::GetChromeInstallSubDirectory()); + if (nw::package()) //FIXME: crashpad initialized early in cr49 + *result = result->Append(base::FilePath::FromUTF8Unsafe(nw::package()->GetName())); *result = result->Append(chrome::kUserDataDirname); return true; } diff --git a/chrome/common/extensions/api/BUILD.gn b/chrome/common/extensions/api/BUILD.gn index 8cdf32f000e57..5fa2ea38f4582 100644 --- a/chrome/common/extensions/api/BUILD.gn +++ b/chrome/common/extensions/api/BUILD.gn @@ -228,6 +228,7 @@ json_features("api_features") { provider_class = "APIFeatureProvider" sources = [ "../../../../extensions/common/api/_api_features.json", + "../../../../content/nw/src/api/_api_features.json", "_api_features.json", ] } diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index cec0caa8c6a01..0349aa694e088 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json @@ -57,10 +57,10 @@ "A9A9FC0228ADF541F0334F22BEFB8F9C245B21D7" // http://crbug.com/839189 ] }, - "action": { - "dependencies": ["manifest:action"], - "contexts": ["blessed_extension"] - }, +// "action": { +// "dependencies": ["manifest:action"], +// "contexts": ["blessed_extension"] +// }, "activityLogPrivate": { "dependencies": ["permission:activityLogPrivate"], "contexts": ["blessed_extension"] @@ -753,10 +753,13 @@ }, "usersPrivate": [{ "dependencies": ["permission:usersPrivate"], + "platforms": ["chromeos"], "contexts": ["blessed_extension"] }, { "channel": "stable", "contexts": ["webui"], + "dependencies": ["permission:usersPrivate"], + "platforms": ["chromeos"], "matches": [ "chrome://settings/*" ] diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index dba119596b2aa..5e06ae777414a 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json @@ -225,16 +225,7 @@ ], "developerPrivate": { "channel": "stable", - "extension_types": ["platform_app"], - "whitelist": [ - "AE27D69DBE571F4B1694F05C89B710C646792231", // Published ADT. - "FA0501B579070BB9CBD4FCAEC8CB0EDF22BA2F04", // Apps Editor published. - "4A4EA121622FCA3D78ED2AB534197F43D7189EE0", // Spark nightly build. - "9FDE6E7F06FCFA11D9A05041C7FF6D8AE662F5D1", // Spark release. - "50B4A905D522C06E27CA6D099E3E54BDA1F152C5", // Spark Beta channel. - "BA0C8BB92084C9741312D90D3EA882526853455F", // Spark dev channel. - "5F57A9AE8DFF5D6BB09DF8606270402612E871E5" // http://crbug.com/422624 - ] + "extension_types": ["platform_app"] }, "devtools": { "channel": "stable", @@ -438,6 +429,7 @@ }, "webcamPrivate": { "channel": "stable", + "platforms": ["chromeos"], "extension_types": ["extension", "platform_app"] }, "networking.castPrivate": { @@ -460,21 +452,7 @@ }, { "channel": "stable", - "extension_types": ["platform_app"], - "whitelist": [ - "AE27D69DBE571F4B1694F05C89B710C646792231", // Published ADT - // TODO(grv): clean up once Apps developer tool is published. - "5107DE9024C329EEA9C9A72D94C16723790C6422", // Apps Developer Tool. - "8C0B1873FFFB65E4D0F4D772879F7304CEF125C2", // Apps Editor old. - "FA0501B579070BB9CBD4FCAEC8CB0EDF22BA2F04", // Apps Editor published. - "EE17C698905F7F2E6DDC87C9C30F11E164C829F4", // Watchdog (Activity Log) - "90113DA9516526D24DAF156C629CC41C049E8882", // Watchdog Test Version - "4A4EA121622FCA3D78ED2AB534197F43D7189EE0", // Spark nightly build. - "9FDE6E7F06FCFA11D9A05041C7FF6D8AE662F5D1", // Spark release. - "50B4A905D522C06E27CA6D099E3E54BDA1F152C5", // Spark Beta channel. - "BA0C8BB92084C9741312D90D3EA882526853455F", // Spark dev channel. - "5F57A9AE8DFF5D6BB09DF8606270402612E871E5" // http://crbug.com/422624 - ] + "extension_types": ["platform_app"] }, { "channel": "stable", @@ -681,6 +659,7 @@ "rtcPrivate": { "channel": "stable", "extension_types": ["extension", "legacy_packaged_app"], + "platforms": ["chromeos"], "whitelist": [ "53041A2FA309EECED01FFC751E7399186E860B2C", // Google Talk prod "A74A4D44C7CFCD8844830E6140C8D763E12DD8F3", // Google Talk beta @@ -778,7 +757,7 @@ ], "tabCapture": { "channel": "stable", - "extension_types": ["extension", "legacy_packaged_app"] + "extension_types": ["extension", "legacy_packaged_app", "platform_app"] }, "terminalPrivate": { "channel": "stable", @@ -804,6 +783,7 @@ "usersPrivate": { "channel": "trunk", "extension_types": ["extension", "platform_app"], + "platforms": ["chromeos"], "location": "component" }, "wallpaper": { diff --git a/chrome/common/extensions/api/webview_tag.json b/chrome/common/extensions/api/webview_tag.json index b425423d56b78..d1a3a232b3b3f 100644 --- a/chrome/common/extensions/api/webview_tag.json +++ b/chrome/common/extensions/api/webview_tag.json @@ -904,6 +904,13 @@ "description": "Returns Chrome's internal process ID for the guest web page's current process, allowing embedders to know how many guests would be affected by terminating the process. Two guests will share a process only if they belong to the same app and have the same
      storage partition ID. The call is synchronous and returns the embedder's cached notion of the current process ID. The process ID isn't the same as the operating system's process ID.", "parameters": [] }, + { + "name": "getGuestId", + "type": "function", + "returns": { "type": "integer" }, + "description": "", + "parameters": [] + }, { "name": "getUserAgent", "type": "function", @@ -1119,6 +1126,41 @@ } ] }, + { + "name": "showDevTools", + "type": "function", + "description": "Open or close devtools for this webview.", + "parameters": [ + { + "type": "boolean", + "name": "show", + "description" : "show or close." + }, + { + "type": "object", + "name": "container", + "description" : "where to show the devtools, should be a webview", + "optional": true + } + ] + }, + { + "name": "inspectElementAt", + "type": "function", + "description": "inpsect element in this webview in devtools opened previously.", + "parameters": [ + { + "type": "integer", + "name": "x", + "description" : "coordinate x of the element." + }, + { + "type": "integer", + "name": "y", + "description" : "coordinate y of the element" + } + ] + }, { "name": "terminate", "type": "function", diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc index 284a5324b06e5..f7d8cb1dfd574 100644 --- a/chrome/common/extensions/chrome_extensions_client.cc +++ b/chrome/common/extensions/chrome_extensions_client.cc @@ -51,6 +51,8 @@ #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#include "content/nw/src/api/generated_schemas.h" + namespace extensions { namespace { @@ -174,6 +176,7 @@ ChromeExtensionsClient::CreateAPIFeatureSource() const { new JSONFeatureProviderSource("api")); source->LoadJSON(IDR_EXTENSION_API_FEATURES); source->LoadJSON(IDR_CHROME_EXTENSION_API_FEATURES); + source->LoadJSON(IDR_NW_EXTENSION_API_FEATURES); return source; } @@ -252,6 +255,7 @@ bool ChromeExtensionsClient::IsAPISchemaGenerated( const std::string& name) const { // Test from most common to least common. return api::ChromeGeneratedSchemas::IsGenerated(name) || + nwapi::nwjsGeneratedSchemas::IsGenerated(name) || api::GeneratedSchemas::IsGenerated(name); } @@ -261,6 +265,9 @@ base::StringPiece ChromeExtensionsClient::GetAPISchema( base::StringPiece chrome_schema = api::ChromeGeneratedSchemas::Get(name); if (!chrome_schema.empty()) return chrome_schema; + base::StringPiece nwjs_schema = nwapi::nwjsGeneratedSchemas::Get(name); + if (!nwjs_schema.empty()) + return nwjs_schema; return api::GeneratedSchemas::Get(name); } diff --git a/chrome/common/extensions/sync_helper.cc b/chrome/common/extensions/sync_helper.cc index 2fad6ffd5d587..3196518bca2d8 100644 --- a/chrome/common/extensions/sync_helper.cc +++ b/chrome/common/extensions/sync_helper.cc @@ -48,6 +48,7 @@ bool IsSyncable(const Extension* extension) { case Manifest::TYPE_HOSTED_APP: case Manifest::TYPE_LEGACY_PACKAGED_APP: case Manifest::TYPE_PLATFORM_APP: + case Manifest::TYPE_NWJS_APP: case Manifest::TYPE_THEME: return true; diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc index f77d4a6b73633..8af456a2144e6 100644 --- a/chrome/common/logging_chrome.cc +++ b/chrome/common/logging_chrome.cc @@ -20,6 +20,7 @@ #define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \ content::RegisterIPCLogger(msg_id, logger) #include "chrome/common/all_messages.h" +#include "extensions/common/extension_messages.h" #endif #if defined(OS_WIN) diff --git a/chrome/common/mac/app_mode_chrome_locator.mm b/chrome/common/mac/app_mode_chrome_locator.mm index efd272e706ba5..c1b3b09b58128 100644 --- a/chrome/common/mac/app_mode_chrome_locator.mm +++ b/chrome/common/mac/app_mode_chrome_locator.mm @@ -79,6 +79,7 @@ bool GetChromeBundleInfo(const base::FilePath& chrome_bundle, // However, we want the shims to be agnostic to distribution and operate based // on the data in their plist, so encode the framework names here. NSDictionary* framework_for_exe = @{ + @"nwjs": @"nwjs", @"Chromium": @"Chromium", @"Google Chrome": @"Google Chrome", @"Google Chrome Canary": @"Google Chrome", diff --git a/chrome/common/pepper_flash.cc b/chrome/common/pepper_flash.cc index 9a16357d3e01a..64f6c8957435c 100644 --- a/chrome/common/pepper_flash.cc +++ b/chrome/common/pepper_flash.cc @@ -39,6 +39,7 @@ const char kPepperFlashOperatingSystem[] = "linux"; #endif +#if 0 // Name of the Pepper Flash architecture in the component manifest. const char kPepperFlashArch[] = #if defined(ARCH_CPU_X86) @@ -50,6 +51,7 @@ const char kPepperFlashArch[] = #else "???"; #endif +#endif // Returns true if the Pepper |interface_name| is implemented by this browser. // It does not check if the interface is proxied. @@ -118,6 +120,7 @@ bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, if (os != kPepperFlashOperatingSystem) return false; +#if 0 std::string arch; manifest.GetStringASCII("x-ppapi-arch", &arch); if (arch != kPepperFlashArch) { @@ -130,7 +133,7 @@ bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, return false; #endif } - +#endif *version_out = version; return true; } diff --git a/chrome/install_static/chromium_install_modes.cc b/chrome/install_static/chromium_install_modes.cc index ccb6021bf5ee9..5c424e8d74cc1 100644 --- a/chrome/install_static/chromium_install_modes.cc +++ b/chrome/install_static/chromium_install_modes.cc @@ -14,14 +14,14 @@ namespace install_static { const wchar_t kCompanyPathName[] = L""; -const wchar_t kProductPathName[] = L"Chromium"; +const wchar_t kProductPathName[] = L"nwjs"; const size_t kProductPathNameLength = _countof(kProductPathName) - 1; // No integration with Google Update, so no app GUID. const wchar_t kBinariesAppGuid[] = L""; -const wchar_t kBinariesPathName[] = L"Chromium Binaries"; +const wchar_t kBinariesPathName[] = L"NW Binaries"; const InstallConstants kInstallModes[] = { // The primary (and only) install mode for Chromium. @@ -32,8 +32,8 @@ const InstallConstants kInstallModes[] = { L"", // Empty install_suffix for the primary install mode. L"", // No logo suffix for the primary install mode. L"", // Empty app_guid since no integraion with Google Update. - L"Chromium", // A distinct base_app_name. - L"Chromium", // A distinct base_app_id. + L"nwjs", // A distinct base_app_name. + L"nwjs", // A distinct base_app_id. L"ChromiumHTM", // ProgID prefix. L"Chromium HTML Document", // ProgID description. L"{7D2B3E1D-D096-4594-9D8F-A6667F12E0AC}", // Active Setup GUID. diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc index fa3e47a248c87..f39150022e2d0 100644 --- a/chrome/install_static/install_util.cc +++ b/chrome/install_static/install_util.cc @@ -22,6 +22,8 @@ #include "components/nacl/common/buildflags.h" #include "components/version_info/channel.h" +std::wstring g_nwjs_prod_name, g_nwjs_prod_version; + namespace install_static { enum class ProcessType { @@ -94,6 +96,7 @@ void Trace(const wchar_t* format_string, ...) { va_end(args); } +#if 0 bool GetLanguageAndCodePageFromVersionResource(const char* version_resource, WORD* language, WORD* code_page) { @@ -171,6 +174,7 @@ bool GetValueFromVersionResource(const char* version_resource, } return false; } +#endif bool DirectoryExists(const std::wstring& path) { DWORD file_attributes = ::GetFileAttributes(path.c_str()); @@ -487,7 +491,10 @@ std::wstring& AppendChromeInstallSubDirectory(const InstallConstants& mode, path->append(kCompanyPathName); path->push_back(L'\\'); } - path->append(kProductPathName, kProductPathNameLength); + if (!g_nwjs_prod_name.empty()) + path->append(g_nwjs_prod_name); + else + path->append(kProductPathName, kProductPathNameLength); if (!include_suffix) return *path; return path->append(mode.install_suffix); @@ -595,10 +602,10 @@ void GetExecutableVersionDetails(const std::wstring& exe_path, assert(channel_name); // Default values in case we don't find a version resource. - *product_name = L"Chrome"; - *version = L"0.0.0.0-devel"; + *product_name = g_nwjs_prod_name; + *version = g_nwjs_prod_version; special_build->clear(); - +#if 0 DWORD dummy = 0; DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy); if (length) { @@ -617,6 +624,7 @@ void GetExecutableVersionDetails(const std::wstring& exe_path, } } *channel_name = GetChromeChannelName(); +#endif } version_info::Channel GetChromeChannel() { diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn index fbabd6c3414f5..e2722ae308840 100644 --- a/chrome/installer/linux/BUILD.gn +++ b/chrome/installer/linux/BUILD.gn @@ -25,7 +25,7 @@ declare_args() { assert(is_linux) packaging_files_executables = [ - "$root_out_dir/chrome", + "$root_out_dir/nw", "$root_out_dir/chrome_sandbox", ] packaging_files_shlibs = [] @@ -159,7 +159,7 @@ action("merge_rpm_dependencies") { } action("strip_chrome_binary") { - prog_name = "$root_out_dir/chrome" + prog_name = "$root_out_dir/nw" debug_file = prog_name + ".debug" stripped_file = prog_name + ".stripped" deps = [ @@ -357,6 +357,9 @@ group("installer_deps") { "//chrome/browser/resources/media/mei_preload:component", "//sandbox/linux:chrome_sandbox", ] + if (is_linux) { + public_deps += [ "//chrome:xdg_mime" ] + } if (enable_nacl) { public_deps += [ "//components/nacl/loader:nacl_helper", diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include index 58b80612445aa..9ad879d711f2f 100644 --- a/chrome/installer/linux/common/installer.include +++ b/chrome/installer/linux/common/installer.include @@ -146,9 +146,9 @@ stage_install_common() { # we should flag all installer files in FILES.cfg and get them from there, so # there's only one place people need to keep track of such things (and in # only the public repository). - if [ -r "${BUILDDIR}/chrome_100_percent.pak" ]; then - install -m 644 "${BUILDDIR}/chrome_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" - install -m 644 "${BUILDDIR}/chrome_200_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" + if [ -r "${BUILDDIR}/nw_100_percent.pak" ]; then + install -m 644 "${BUILDDIR}/nw_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" + install -m 644 "${BUILDDIR}/nw_200_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" else install -m 644 "${BUILDDIR}/theme_resources_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" install -m 644 "${BUILDDIR}/ui_resources_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/" diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn index 5c940dde6d9c7..5244c1e272110 100644 --- a/chrome/installer/mini_installer/BUILD.gn +++ b/chrome/installer/mini_installer/BUILD.gn @@ -132,7 +132,7 @@ template("generate_mini_installer") { inputs = [ "$chrome_dll_file", - "$root_out_dir/chrome.exe", + "$root_out_dir/nw.exe", "$root_out_dir/locales/en-US.pak", "$root_out_dir/setup.exe", "//chrome/tools/build/win/makecab.py", @@ -289,7 +289,7 @@ template("generate_mini_installer") { generate_mini_installer("mini_installer") { out_dir = root_out_dir - chrome_dll_file = "$root_out_dir/chrome.dll" + chrome_dll_file = "$root_out_dir/nw.dll" chrome_dll_target = "//chrome:main_dll" } diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release index 419d98ccc4a8d..f53e9e95a21bb 100644 --- a/chrome/installer/mini_installer/chrome.release +++ b/chrome/installer/mini_installer/chrome.release @@ -6,44 +6,46 @@ # # Chrome Application dir entries, sorted alphabetically. # -chrome.exe: %(ChromeDir)s\ +nw.exe: %(ChromeDir)s\ # # Chrome version dir assembly manifest. # The name of this file must match the name of the version dir, so we cannot # hard-code it. # // TODO(caitkp): Find a way to do this without wildcards. # -*.*.*.*.manifest: %(VersionDir)s\ +*.*.*.*.manifest: %(ChromeDir)s\ # # Chrome version dir entries, sorted alphabetically. # -chrome.dll: %(VersionDir)s\ -chrome_100_percent.pak: %(VersionDir)s\ -chrome_child.dll: %(VersionDir)s\ -chrome_elf.dll: %(VersionDir)s\ -chrome_watcher.dll: %(VersionDir)s\ -d3dcompiler_47.dll: %(VersionDir)s\ -eventlog_provider.dll: %(VersionDir)s\ +nw.dll: %(ChromeDir)s\ +nw_100_percent.pak: %(ChromeDir)s\ +nw_child.dll: %(ChromeDir)s\ +nw_elf.dll: %(ChromeDir)s\ +nw_watcher.dll: %(ChromeDir)s\ +d3dcompiler_47.dll: %(ChromeDir)s\ +eventlog_provider.dll: %(ChromeDir)s\ ffmpeg.dll: %(VersionDir)s\ -icudt.dll: %(VersionDir)s\ -icudtl.dat: %(VersionDir)s\ -libEGL.dll: %(VersionDir)s\ -libGLESv2.dll: %(VersionDir)s\ -nacl64.exe: %(VersionDir)s\ -nacl_irt_x86_32.nexe: %(VersionDir)s\ -nacl_irt_x86_64.nexe: %(VersionDir)s\ -natives_blob.bin: %(VersionDir)s\ -notification_helper.exe: %(VersionDir)s\ -resources.pak: %(VersionDir)s\ -v8_context_snapshot.bin: %(VersionDir)s\ +icudt.dll: %(ChromeDir)s\ +icudtl.dat: %(ChromeDir)s\ +libEGL.dll: %(ChromeDir)s\ +libGLESv2.dll: %(ChromeDir)s\ +nacl64.exe: %(ChromeDir)s\ +nacl_irt_x86_32.nexe: %(ChromeDir)s\ +nacl_irt_x86_64.nexe: %(ChromeDir)s\ +notification_helper.exe: %(ChromeDir)s\ +natives_blob.bin: %(ChromeDir)s\ +resources.pak: %(ChromeDir)s\ +notification_helper.exe: %(ChromeDir)s\ +node.dll: %(ChromeDir)s\ +v8_context_snapshot.bin: %(ChromeDir)s\ # # Sub directories living in the version dir # -default_apps\*.crx: %(VersionDir)s\default_apps\ -default_apps\external_extensions.json: %(VersionDir)s\default_apps\ -Extensions\*.*: %(VersionDir)s\Extensions\ -locales\*.dll: %(VersionDir)s\Locales -locales\*.pak: %(VersionDir)s\Locales +default_apps\*.crx: %(ChromeDir)s\default_apps\ +default_apps\external_extensions.json: %(ChromeDir)s\default_apps\ +Extensions\*.*: %(ChromeDir)s\Extensions\ +locales\*.dll: %(ChromeDir)s\Locales +locales\*.pak: %(ChromeDir)s\Locales # # VisualElements sub-dir. @@ -51,31 +53,31 @@ locales\*.pak: %(VersionDir)s\Locales # All or none of the following files need to be present as the creation of # VisualElementsManifest.xml is based on the existence of # %(VersionDir)\VisualElements. -Logo.png: %(VersionDir)s\VisualElements\ -LogoBeta.png: %(VersionDir)s\VisualElements\ -LogoBetaLight.png: %(VersionDir)s\VisualElements\ -LogoCanary.png: %(VersionDir)s\VisualElements\ -LogoCanaryLight.png: %(VersionDir)s\VisualElements\ -LogoDev.png: %(VersionDir)s\VisualElements\ -LogoDevLight.png: %(VersionDir)s\VisualElements\ -LogoLight.png: %(VersionDir)s\VisualElements\ -SmallLogo.png: %(VersionDir)s\VisualElements\ -SmallLogoBeta.png: %(VersionDir)s\VisualElements\ -SmallLogoBetaLight.png: %(VersionDir)s\VisualElements\ -SmallLogoCanary.png: %(VersionDir)s\VisualElements\ -SmallLogoCanaryLight.png: %(VersionDir)s\VisualElements\ -SmallLogoDev.png: %(VersionDir)s\VisualElements\ -SmallLogoDevLight.png: %(VersionDir)s\VisualElements\ -SmallLogoLight.png: %(VersionDir)s\VisualElements\ +Logo.png: %(ChromeDir)s\VisualElements\ +LogoBeta.png: %(ChromeDir)s\VisualElements\ +LogoBetaLight.png: %(ChromeDir)s\VisualElements\ +LogoCanary.png: %(ChromeDir)s\VisualElements\ +LogoCanaryLight.png: %(ChromeDir)s\VisualElements\ +LogoDev.png: %(ChromeDir)s\VisualElements\ +LogoDevLight.png: %(ChromeDir)s\VisualElements\ +LogoLight.png: %(ChromeDir)s\VisualElements\ +SmallLogo.png: %(ChromeDir)s\VisualElements\ +SmallLogoBeta.png: %(ChromeDir)s\VisualElements\ +SmallLogoBetaLight.png: %(ChromeDir)s\VisualElements\ +SmallLogoCanary.png: %(ChromeDir)s\VisualElements\ +SmallLogoCanaryLight.png: %(ChromeDir)s\VisualElements\ +SmallLogoDev.png: %(ChromeDir)s\VisualElements\ +SmallLogoDevLight.png: %(ChromeDir)s\VisualElements\ +SmallLogoLight.png: %(ChromeDir)s\VisualElements\ # # SwiftShader sub-dir # -swiftshader\libEGL.dll: %(VersionDir)s\swiftshader\ -swiftshader\libGLESv2.dll: %(VersionDir)s\swiftshader\ +swiftshader\libEGL.dll: %(ChromeDir)s\swiftshader\ +swiftshader\libGLESv2.dll: %(ChromeDir)s\swiftshader\ [HIDPI] -chrome_200_percent.pak: %(VersionDir)s\ +nw_200_percent.pak: %(ChromeDir)s\ [TOUCH] @@ -83,14 +85,14 @@ chrome_200_percent.pak: %(VersionDir)s\ # # Widevine CDM sub-dir # -WidevineCdm\manifest.json: %(VersionDir)s\WidevineCdm\ -WidevineCdm\_platform_specific\win_x86\widevinecdm.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x86\ -WidevineCdm\_platform_specific\win_x86\widevinecdm.dll.sig: %(VersionDir)s\WidevineCdm\_platform_specific\win_x86\ -WidevineCdm\_platform_specific\win_x64\widevinecdm.dll: %(VersionDir)s\WidevineCdm\_platform_specific\win_x64\ -WidevineCdm\_platform_specific\win_x64\widevinecdm.dll.sig: %(VersionDir)s\WidevineCdm\_platform_specific\win_x64\ +WidevineCdm\manifest.json: %(ChromeDir)s\WidevineCdm\ +WidevineCdm\_platform_specific\win_x86\widevinecdm.dll: %(ChromeDir)s\WidevineCdm\_platform_specific\win_x86\ +WidevineCdm\_platform_specific\win_x86\widevinecdm.dll.sig: %(ChromeDir)s\WidevineCdm\_platform_specific\win_x86\ +WidevineCdm\_platform_specific\win_x64\widevinecdm.dll: %(ChromeDir)s\WidevineCdm\_platform_specific\win_x64\ +WidevineCdm\_platform_specific\win_x64\widevinecdm.dll.sig: %(ChromeDir)s\WidevineCdm\_platform_specific\win_x64\ # # MEI Preload sub dir # -MEIPreload\manifest.json: %(VersionDir)s\MEIPreload\ -MEIPreload\preloaded_data.pb: %(VersionDir)s\MEIPreload\ +MEIPreload\manifest.json: %(ChromeDir)s\MEIPreload\ +MEIPreload\preloaded_data.pb: %(ChromeDir)s\MEIPreload\ diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc index 33c105c968dc4..b0ac508ab5370 100644 --- a/chrome/installer/util/browser_distribution.cc +++ b/chrome/installer/util/browser_distribution.cc @@ -108,7 +108,7 @@ base::string16 BrowserDistribution::GetStartMenuShortcutSubfolder( } base::string16 BrowserDistribution::GetPublisherName() { - return L"Chromium"; + return L"nwjs"; } base::string16 BrowserDistribution::GetAppDescription() { @@ -122,7 +122,7 @@ base::string16 BrowserDistribution::GetLongAppDescription() { } std::string BrowserDistribution::GetSafeBrowsingName() { - return "chromium"; + return "nwjs"; } base::string16 BrowserDistribution::GetDistributionData(HKEY root_key) { diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc index 42a2c0cc1b957..af9029a6c3cbb 100644 --- a/chrome/installer/util/google_update_settings.cc +++ b/chrome/installer/util/google_update_settings.cc @@ -209,7 +209,7 @@ GoogleUpdateSettings::CollectStatsConsentTaskRunner() { } bool GoogleUpdateSettings::GetCollectStatsConsent() { - return GetCollectStatsConsentAtLevel(IsSystemInstall()); + return false; //GetCollectStatsConsentAtLevel(IsSystemInstall()); } bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) { diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index 4ed3469f1dae8..79a62e23d421b 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc @@ -185,9 +185,9 @@ const char kGoogleUpdateIsMachineEnvVar[] = "GoogleUpdateIsMachine"; // TODO(gab): Rename setup.exe itself altogether and use the same binary for // Active Setup. const wchar_t kActiveSetupExe[] = L"chrmstp.exe"; -const wchar_t kChromeDll[] = L"chrome.dll"; -const wchar_t kChromeChildDll[] = L"chrome_child.dll"; -const wchar_t kChromeExe[] = L"chrome.exe"; +const wchar_t kChromeDll[] = L"nw.dll"; +const wchar_t kChromeChildDll[] = L"nw_child.dll"; +const wchar_t kChromeExe[] = L"nw.exe"; const wchar_t kChromeNewExe[] = L"new_chrome.exe"; const wchar_t kChromeOldExe[] = L"old_chrome.exe"; const wchar_t kCmdOnOsUpgrade[] = L"on-os-upgrade"; diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 0b312fc03b93e..a86bc8366ab26 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn @@ -113,6 +113,7 @@ static_library("renderer") { defines = [] deps = [ + "//content/nw:nw_renderer", "//chrome:resources", "//chrome:strings", "//chrome/common", @@ -138,9 +139,9 @@ static_library("renderer") { "//components/startup_metric_utils/common:interfaces", "//components/subresource_filter/content/renderer", "//components/task_scheduler_util", - "//components/translate/content/renderer", + #"//components/translate/content/renderer", "//components/translate/core/common", - "//components/translate/core/language_detection", + #"//components/translate/core/language_detection", "//components/visitedlink/renderer", "//components/web_cache/renderer", "//content/app/resources", diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 64a3c7982c9f2..3fc8f138102f6 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -192,6 +192,9 @@ #endif // BUILDFLAG(HAS_SPELLCHECK_PANEL) #endif // BUILDFLAG(ENABLE_SPELLCHECK) +#include "content/nw/src/nw_content.h" +#include "content/nw/src/common/shell_switches.h" + using autofill::AutofillAgent; using autofill::PasswordAutofillAgent; using autofill::PasswordGenerationAgent; @@ -373,6 +376,15 @@ ChromeContentRendererClient::ChromeContentRendererClient() ChromeContentRendererClient::~ChromeContentRendererClient() = default; +void ChromeContentRendererClient::willHandleNavigationPolicy(content::RenderView* rv, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy* policy, + blink::WebString* manifest, + bool new_win) { + nw::willHandleNavigationPolicy(rv, frame, request, policy, manifest, new_win); +} + void ChromeContentRendererClient::RenderThreadStarted() { RenderThread* thread = RenderThread::Get(); @@ -419,9 +431,11 @@ void ChromeContentRendererClient::RenderThreadStarted() { prescient_networking_dispatcher_.reset( new network_hints::PrescientNetworkingDispatcher()); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); #if BUILDFLAG(ENABLE_SPELLCHECK) - if (!spellcheck_) + if (!spellcheck_ && command_line->HasSwitch(switches::kEnableSpellChecking)) { InitSpellCheck(); + } #endif #if defined(FULL_SAFE_BROWSING) registry_.AddInterface( @@ -444,7 +458,6 @@ void ChromeContentRendererClient::RenderThreadStarted() { thread->AddFilter(webrtc_logging_message_filter_.get()); thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(variations::switches::kEnableBenchmarking)) thread->RegisterExtension(extensions_v8::BenchmarkingExtension::Get()); if (command_line->HasSwitch(switches::kEnableNetBenchmarking)) @@ -600,6 +613,7 @@ void ChromeContentRendererClient::RenderFrameCreated( #endif // !defined(OS_ANDROID) #if BUILDFLAG(ENABLE_SPELLCHECK) + if (command_line->HasSwitch(switches::kEnableSpellChecking)) new SpellCheckProvider(render_frame, spellcheck_.get(), this); #if BUILDFLAG(HAS_SPELLCHECK_PANEL) @@ -1390,11 +1404,14 @@ void ChromeContentRendererClient::InitSpellCheck() { // default (https://crbug.com/825740). std::unique_ptr ChromeContentRendererClient::CreateWebSocketHandshakeThrottle() { +#if 0 InitSafeBrowsingIfNecessary(); // This is called only for Shared Worker and Service Worker that don't have a // real frame, so we specify MSG_ROUTING_NONE here. return std::make_unique( safe_browsing_.get(), MSG_ROUTING_NONE); +#endif + return nullptr; } std::unique_ptr @@ -1422,7 +1439,7 @@ bool ChromeContentRendererClient::AllowPepperMediaStreamAPI( // Allow only the Hangouts app to use the MediaStream APIs. It's OK to check // the whitelist in the renderer, since we're only preventing access until // these APIs are public and stable. - return (AppCategorizer::IsHangoutsUrl(url)); + return true; #endif // !defined(OS_ANDROID) } @@ -1512,22 +1529,30 @@ ChromeContentRendererClient::CreateBrowserPluginDelegate( #endif } +base::FilePath ChromeContentRendererClient::GetRootPath() { + return nw::GetRootPathRenderer(); +} + void ChromeContentRendererClient::RecordRappor(const std::string& metric, const std::string& sample) { +#if 0 if (!rappor_recorder_) { RenderThread::Get()->GetConnector()->BindInterface( content::mojom::kBrowserServiceName, &rappor_recorder_); } rappor_recorder_->RecordRappor(metric, sample); +#endif } void ChromeContentRendererClient::RecordRapporURL(const std::string& metric, const GURL& url) { +#if 0 if (!rappor_recorder_) { RenderThread::Get()->GetConnector()->BindInterface( content::mojom::kBrowserServiceName, &rappor_recorder_); } rappor_recorder_->RecordRapporURL(metric, url); +#endif } void ChromeContentRendererClient::AddImageContextMenuProperties( diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 8427fc4c5669c..62dd8bd68511e 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -109,6 +109,13 @@ class ChromeContentRendererClient ChromeContentRendererClient(); ~ChromeContentRendererClient() override; + base::FilePath GetRootPath() override; + void willHandleNavigationPolicy(content::RenderView* rv, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy* policy, + blink::WebString* manifest, + bool new_win) override; void RenderThreadStarted() override; void RenderFrameCreated(content::RenderFrame* render_frame) override; void RenderViewCreated(content::RenderView* render_view) override; @@ -307,7 +314,9 @@ class ChromeContentRendererClient // Used to profile main thread. std::unique_ptr main_thread_profiler_; +#if 0 rappor::mojom::RapporRecorderPtr rappor_recorder_; +#endif std::unique_ptr chrome_observer_; std::unique_ptr web_cache_impl_; diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc index 42c21996ab524..9f93deb77d991 100644 --- a/chrome/renderer/chrome_render_frame_observer.cc +++ b/chrome/renderer/chrome_render_frame_observer.cc @@ -152,8 +152,10 @@ ChromeRenderFrameObserver::ChromeRenderFrameObserver( if (!command_line.HasSwitch(switches::kDisableClientSidePhishingDetection)) SetClientSidePhishingDetection(true); #endif +#if 0 translate_helper_ = new translate::TranslateHelper( render_frame, ISOLATED_WORLD_ID_TRANSLATE, extensions::kExtensionScheme); +#endif } ChromeRenderFrameObserver::~ChromeRenderFrameObserver() { @@ -371,12 +373,14 @@ void ChromeRenderFrameObserver::DidCreateNewDocument() { void ChromeRenderFrameObserver::DidStartProvisionalLoad( WebDocumentLoader* document_loader) { +#if 0 // Let translate_helper do any preparatory work for loading a URL. if (!translate_helper_) return; translate_helper_->PrepareForUrl( render_frame()->GetWebFrame()->GetDocument().Url()); +#endif } void ChromeRenderFrameObserver::DidCommitProvisionalLoad( @@ -447,11 +451,13 @@ void ChromeRenderFrameObserver::CapturePageText(TextCaptureType capture_type) { UMA_HISTOGRAM_TIMES(kTranslateCaptureText, base::TimeTicks::Now() - capture_begin_time); +#if 0 // We should run language detection only once. Parsing finishes before // the page loads, so let's pick that timing. if (translate_helper_ && capture_type == PRELIMINARY_CAPTURE) { translate_helper_->PageCaptured(contents); } +#endif TRACE_EVENT0("renderer", "ChromeRenderFrameObserver::CapturePageText"); diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index 4af2422cf5981..d9d27f9270edc 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc @@ -424,7 +424,7 @@ bool ContentSettingsObserver::AllowWriteToClipboard(bool default_value) { } bool ContentSettingsObserver::AllowMutationEvents(bool default_value) { - return IsPlatformApp() ? false : default_value; + return default_value; } bool ContentSettingsObserver::AllowRunningInsecureContent( diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc index 4c7e07ba3fc6f..345f8a7f7a055 100644 --- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc +++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc @@ -7,6 +7,8 @@ #include #include +#include "content/nw/src/nw_content.h" + #include "base/command_line.h" #include "base/lazy_instance.h" #include "chrome/common/chrome_isolated_world_ids.h" @@ -155,6 +157,7 @@ void ChromeExtensionsRendererClient::RenderThreadStarted() { if (!extension_dispatcher_) { extension_dispatcher_ = std::make_unique( std::make_unique()); + nw::ExtensionDispatcherCreated(extension_dispatcher_.get()); } permissions_policy_delegate_.reset( new extensions::RendererPermissionsPolicyDelegate( diff --git a/chrome/renderer/extensions/extension_process_policy.cc b/chrome/renderer/extensions/extension_process_policy.cc index 0f6417c1dabfb..697bbb80b3dd9 100644 --- a/chrome/renderer/extensions/extension_process_policy.cc +++ b/chrome/renderer/extensions/extension_process_policy.cc @@ -34,6 +34,9 @@ bool CrossesExtensionProcessBoundary(const ExtensionSet& extensions, const extensions::Extension* new_url_extension = GetNonBookmarkAppExtension(extensions, new_url); + if (old_url_extension && old_url_extension->is_nwjs_app()) + return false; + // TODO(creis): Temporary workaround for crbug.com/59285: Do not swap process // to navigate from a hosted app to a normal page or another hosted app // (unless either is the web store). This is because some OAuth providers diff --git a/chrome/renderer/extensions/resource_request_policy.cc b/chrome/renderer/extensions/resource_request_policy.cc index 6f4b963b1400d..a746cf2648d48 100644 --- a/chrome/renderer/extensions/resource_request_policy.cc +++ b/chrome/renderer/extensions/resource_request_policy.cc @@ -73,7 +73,10 @@ bool ResourceRequestPolicy::CanRequestResource( // resources: // Empty urls (needed for some edge cases when we have empty urls). - if (frame_url.is_empty()) + // NWJS: about:blank here when load iframe in document-start-end + // case starting from cr53 + bool is_empty_origin = frame_url.is_empty() || frame_url == GURL(url::kAboutBlankURL); + if (is_empty_origin) return true; // Extensions requesting their own resources (frame_url check is for images, diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc index ad75e9b9c8c59..40ff8824c67cb 100644 --- a/chrome/renderer/url_loader_throttle_provider_impl.cc +++ b/chrome/renderer/url_loader_throttle_provider_impl.cc @@ -96,8 +96,10 @@ URLLoaderThrottleProviderImpl::CreateThrottles( std::vector> throttles; +#if 1 bool network_service_enabled = base::FeatureList::IsEnabled(network::features::kNetworkService); +#endif // Some throttles have already been added in the browser for frame resources. // Don't add them for frame requests. bool is_frame_resource = content::IsResourceTypeFrame(resource_type); @@ -105,6 +107,7 @@ URLLoaderThrottleProviderImpl::CreateThrottles( DCHECK(!is_frame_resource || type_ == content::URLLoaderThrottleProviderType::kFrame); +#if 0 if ((network_service_enabled || base::FeatureList::IsEnabled( safe_browsing::kCheckByURLLoaderThrottle)) && @@ -115,7 +118,7 @@ URLLoaderThrottleProviderImpl::CreateThrottles( std::make_unique( safe_browsing_.get(), render_frame_id)); } - +#endif if (type_ == content::URLLoaderThrottleProviderType::kFrame && !is_frame_resource) { content::RenderFrame* render_frame = diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 0ba10d54a17a7..e58b74e498724 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -32,7 +32,7 @@ if (is_android) { import("//build/config/android/rules.gni") import("//tools/v8_context_snapshot/v8_context_snapshot.gni") } else { - include_js_tests = !(is_asan || is_msan || is_tsan) + include_js_tests = false #!(is_asan || is_msan || is_tsan) } # This target exists to reference other test executables to bring these files @@ -1372,7 +1372,7 @@ test("browser_tests") { # TODO(rockot) bug 505926: The chrome_extensions_browsertests target # should be deleted and this line removed. See the # chrome_extensions_browsertests target for more. - "//extensions:chrome_extensions_browsertests", + #"//extensions:chrome_extensions_browsertests", "//extensions/common/api", ] @@ -2109,6 +2109,20 @@ test("browser_tests") { sources += [ "../browser/ui/screen_capture_notification_ui_browsertest.cc" ] } + sources = [] + sources = [ + "../../content/nw/src/nwjs_browsertest.cc", + "../browser/extensions/extension_apitest.cc", + "../browser/extensions/extension_browsertest.cc", + "../browser/apps/app_browsertest_util.cc", + "../browser/apps/app_browsertest_util.h", + "../browser/pdf/pdf_extension_test_util.cc", + "../browser/pdf/pdf_extension_test_util.h", + "../browser/extensions/updater/extension_cache_fake.cc", + "../browser/extensions/updater/extension_cache_fake.h", + "../browser/extensions/browsertest_util.cc", + "../browser/extensions/browsertest_util.h", + ] } } diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index 53dec57917249..09e6f2c96a26d 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc @@ -380,11 +380,13 @@ component_updater::ComponentUpdateService* TestingBrowserProcess::component_updater() { return nullptr; } +#if 0 component_updater::SupervisedUserWhitelistInstaller* TestingBrowserProcess::supervised_user_whitelist_installer() { return nullptr; } +#endif MediaFileSystemRegistry* TestingBrowserProcess::media_file_system_registry() { #if defined(OS_ANDROID) diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h index 92bdeb2ad606b..9e6e9a31bbeaa 100644 --- a/chrome/test/base/testing_browser_process.h +++ b/chrome/test/base/testing_browser_process.h @@ -116,9 +116,12 @@ class TestingBrowserProcess : public BrowserProcess { #endif net_log::ChromeNetLog* net_log() override; + component_updater::ComponentUpdateService* component_updater() override; +#if 0 component_updater::SupervisedUserWhitelistInstaller* supervised_user_whitelist_installer() override; +#endif MediaFileSystemRegistry* media_file_system_registry() override; WebRtcLogUploader* webrtc_log_uploader() override; diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc index 7c292405628f6..c2af47352284e 100644 --- a/chrome/test/chromedriver/capabilities.cc +++ b/chrome/test/chromedriver/capabilities.cc @@ -229,6 +229,20 @@ Status ParseSwitches(const base::Value& option, return Status(kOk); } +Status ParseArguments(const base::Value& option, + Capabilities* capabilities) { + const base::ListValue* arg_list = NULL; + if (!option.GetAsList(&arg_list)) + return Status(kUnknownError, "must be a list"); + for (size_t i = 0; i < arg_list->GetSize(); ++i) { + std::string arg_string; + if (!arg_list->GetString(i, &arg_string)) + return Status(kUnknownError, "each argument must be a string"); + capabilities->arguments.push_back(arg_string); + } + return Status(kOk); +} + Status ParseExtensions(const base::Value& option, Capabilities* capabilities) { const base::ListValue* extensions = NULL; if (!option.GetAsList(&extensions)) @@ -488,6 +502,7 @@ Status ParseChromeOptions( parser_map["debuggerAddress"] = base::Bind(&ParseUseRemoteBrowser); } else { parser_map["args"] = base::Bind(&ParseSwitches); + parser_map["nwargs"] = base::Bind(&ParseArguments); parser_map["binary"] = base::Bind(&ParseFilePath, &capabilities->binary); parser_map["detach"] = base::Bind(&ParseBoolean, &capabilities->detach); parser_map["excludeSwitches"] = base::Bind(&ParseExcludeSwitches); diff --git a/chrome/test/chromedriver/capabilities.h b/chrome/test/chromedriver/capabilities.h index 4ffbc38489f61..09c255e9b8a61 100644 --- a/chrome/test/chromedriver/capabilities.h +++ b/chrome/test/chromedriver/capabilities.h @@ -134,6 +134,8 @@ struct Capabilities { // Time to wait for extension background page to appear. If 0, no waiting. base::TimeDelta extension_load_timeout; + std::vector arguments; + // True if should always use DevTools for taking screenshots. // This is experimental and may be removed at a later point. bool force_devtools_screenshot; diff --git a/chrome/test/chromedriver/chrome/chrome_finder.cc b/chrome/test/chromedriver/chrome/chrome_finder.cc index 91155793154f9..5105949d0b0ce 100644 --- a/chrome/test/chromedriver/chrome/chrome_finder.cc +++ b/chrome/test/chromedriver/chrome/chrome_finder.cc @@ -25,7 +25,7 @@ namespace { -#if defined(OS_WIN) +#if 0 void GetApplicationDirs(std::vector* locations) { std::vector installation_locations; base::FilePath local_app_data, program_files, program_files_x86; @@ -45,7 +45,7 @@ void GetApplicationDirs(std::vector* locations) { installation_locations[i].Append(L"Chromium\\Application")); } } -#elif defined(OS_LINUX) +#elif 0 void GetApplicationDirs(std::vector* locations) { // TODO: Respect users' PATH variables. // Until then, we use an approximation of the most common defaults. @@ -87,22 +87,18 @@ bool FindExe( } // namespace internal -#if defined(OS_MACOSX) +#if 0 void GetApplicationDirs(std::vector* locations); #endif bool FindChrome(base::FilePath* browser_exe) { base::FilePath browser_exes_array[] = { #if defined(OS_WIN) - base::FilePath(L"chrome.exe") + base::FilePath(L"nw.exe") #elif defined(OS_MACOSX) - base::FilePath("Google Chrome.app/Contents/MacOS/Google Chrome"), - base::FilePath("Chromium.app/Contents/MacOS/Chromium") + base::FilePath("nwjs.app/Contents/MacOS/nwjs") #elif defined(OS_LINUX) - base::FilePath("google-chrome"), - base::FilePath("chrome"), - base::FilePath("chromium"), - base::FilePath("chromium-browser") + base::FilePath("nw"), #else // it will compile but won't work on other OSes base::FilePath() @@ -123,7 +119,10 @@ bool FindChrome(base::FilePath* browser_exe) { } std::vector locations; - GetApplicationDirs(&locations); + base::FilePath exe_path; + base::PathService::Get(base::DIR_EXE, &exe_path); + locations.push_back(exe_path); + return internal::FindExe( base::Bind(&base::PathExists), browser_exes, diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index b710d1a28a174..a766120c84b6f 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc @@ -8,6 +8,7 @@ #include #include "base/values.h" +#include "base/strings/string_util.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/chrome/devtools_http_client.h" @@ -42,13 +43,25 @@ Status ChromeImpl::GetWebViewIdForFirstTab(std::string* web_view_id, if (status.IsError()) return status; UpdateWebViews(views_info, w3c_compliant); + std::string ret; for (size_t i = 0; i < views_info.GetSize(); ++i) { const WebViewInfo& view = views_info.Get(i); - if (view.type == WebViewInfo::kPage) { - *web_view_id = view.id; - return Status(kOk); + if (view.type == WebViewInfo::kPage || + view.type == WebViewInfo::kApp || + (view.type == WebViewInfo::kOther && + !base::StartsWith(view.url, "chrome-extension://", base::CompareCase::SENSITIVE) && + !base::StartsWith(view.url, "about:blank", base::CompareCase::SENSITIVE))) { + ret = view.id; + if (view.type != WebViewInfo::kOther) { + *web_view_id = view.id; + return Status(kOk); + } } } + if (!ret.empty()) { + *web_view_id = ret; + return Status(kOk); + } return Status(kUnknownError, "unable to discover open window in chrome"); } diff --git a/chrome/test/chromedriver/chrome/devtools_http_client.cc b/chrome/test/chromedriver/chrome/devtools_http_client.cc index 760da07a9e5a6..e31111ca516a9 100644 --- a/chrome/test/chromedriver/chrome/devtools_http_client.cc +++ b/chrome/test/chromedriver/chrome/devtools_http_client.cc @@ -162,6 +162,15 @@ bool DevToolsHttpClient::IsBrowserWindow(const WebViewInfo& view) const { return base::ContainsKey(*window_types_, view.type) || (view.type == WebViewInfo::kOther && (view.url == "chrome://print/" || + view.url == "" || view.url == "about:blank" || + // base::StartsWith(view.url, "chrome-extension://", + // base::CompareCase::SENSITIVE) || + base::StartsWith(view.url, "file://", + base::CompareCase::SENSITIVE) || + base::StartsWith(view.url, "http://", + base::CompareCase::SENSITIVE) || + base::StartsWith(view.url, "https://", + base::CompareCase::SENSITIVE) || view.url == "chrome://media-router/")); } diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index 74787b846e142..1259d3565d142 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc @@ -63,6 +63,8 @@ #include "chrome/test/chromedriver/keycode_text_conversion.h" #endif +#include "base/strings/string_number_conversions.h" + namespace { // TODO(eseckler): Remove --ignore-certificate-errors for newer Chrome versions @@ -72,6 +74,7 @@ const char* const kCommonSwitches[] = { "metrics-recording-only", }; +#if 0 const char* const kDesktopSwitches[] = { "disable-hang-monitor", "disable-prompt-on-repost", @@ -88,6 +91,7 @@ const char* const kDesktopSwitches[] = { "test-type=webdriver", "force-fieldtrials=SiteIsolationExtensions/Control", }; +#endif const char* const kAndroidSwitches[] = { "disable-fre", "enable-remote-debugging", @@ -140,8 +144,10 @@ Status PrepareDesktopCommandLine(const Capabilities& capabilities, for (auto* common_switch : kCommonSwitches) switches.SetUnparsedSwitch(common_switch); +#if 0 //FIXME if enabled, chromedriver cannot find chrome on windows for (auto* desktop_switch : kDesktopSwitches) switches.SetUnparsedSwitch(desktop_switch); +#endif for (const auto& excluded_switch : capabilities.exclude_switches) { switches.RemoveSwitch(excluded_switch); } @@ -159,7 +165,7 @@ Status PrepareDesktopCommandLine(const Capabilities& capabilities, *user_data_dir = base::FilePath(switches.GetSwitchValueNative("user-data-dir")); } else { - command.AppendArg("data:,"); + //command.AppendArg("data:,"); if (!user_data_dir_temp_dir->CreateUniqueTempDir()) return Status(kUnknownError, "cannot create temp dir for user data dir"); switches.SetSwitch("user-data-dir", @@ -189,6 +195,10 @@ Status PrepareDesktopCommandLine(const Capabilities& capabilities, return status; } switches.AppendToCommandLine(&command); + + for (size_t i = 0; i < capabilities.arguments.size(); i++) + command.AppendArg(capabilities.arguments[i]); + *prepared_command = command; return Status(kOk); } @@ -212,6 +222,11 @@ Status WaitForDevToolsAndCheckVersion( window_types.reset(new std::set()); } + base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch("launch-timeout")) { + std::string s_timeout = cmd_line->GetSwitchValueASCII("launch-timeout"); + base::StringToInt(s_timeout, &wait_time); + } std::unique_ptr client(new DevToolsHttpClient( address, context_getter, socket_factory, std::move(device_metrics), std::move(window_types), capabilities->page_load_strategy)); @@ -238,7 +253,6 @@ Status WaitForDevToolsAndCheckVersion( } } - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); if (cmd_line->HasSwitch("disable-build-check")) { LOG(WARNING) << "You are using an unsupported command-line switch: " "--disable-build-check. Please don't report bugs that " @@ -253,7 +267,9 @@ Status WaitForDevToolsAndCheckVersion( WebViewsInfo views_info; client->GetWebViewsInfo(&views_info); for (size_t i = 0; i < views_info.GetSize(); ++i) { - if (views_info.Get(i).type == WebViewInfo::kPage) { + if (views_info.Get(i).type == WebViewInfo::kApp + || (views_info.Get(i).type == WebViewInfo::kOther && + !base::StartsWith(views_info.Get(i).url, "chrome-extension://", base::CompareCase::SENSITIVE))) { //node-remote page *user_client = std::move(client); return Status(kOk); } diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg index dba5cd354b17c..3f24aad718067 100644 --- a/chrome/tools/build/linux/FILES.cfg +++ b/chrome/tools/build/linux/FILES.cfg @@ -36,11 +36,11 @@ FILES = [ 'buildtype': ['dev', 'official'], }, { - 'filename': 'chrome_100_percent.pak', + 'filename': 'nw_100_percent.pak', 'buildtype': ['dev', 'official'], }, { - 'filename': 'chrome_200_percent.pak', + 'filename': 'nw_200_percent.pak', 'buildtype': ['dev', 'official'], }, { diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg index 1b6622526457a..f1f448adbf07f 100644 --- a/chrome/tools/build/win/FILES.cfg +++ b/chrome/tools/build/win/FILES.cfg @@ -85,11 +85,11 @@ FILES = [ 'filegroup': ['default'], }, { - 'filename': 'chrome_100_percent.pak', + 'filename': 'nw_100_percent.pak', 'buildtype': ['dev', 'official'], }, { - 'filename': 'chrome_200_percent.pak', + 'filename': 'nw_200_percent.pak', 'buildtype': ['dev', 'official'], 'optional': ['dev', 'official'], }, diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index 2d46f2507cf5d..a073c52d659f8 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc @@ -86,6 +86,10 @@ #include "chrome/services/file_util/public/mojom/constants.mojom.h" // nogncheck #endif +#if defined(OS_WIN) +#pragma warning(disable:4065) +#endif + namespace { base::LazyInstance:: diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn index 6cdabcb46a364..bab21c5c7e834 100644 --- a/chrome_elf/BUILD.gn +++ b/chrome_elf/BUILD.gn @@ -39,6 +39,7 @@ source_set("chrome_elf_main_include") { # We should move chrome_result_codes.h to another target which does not bring # in the world. shared_library("chrome_elf") { + output_name = "nw_elf" sources = [ "chrome_elf_main.cc", "chrome_elf_main.h", diff --git a/chrome_elf/chrome_elf.ver b/chrome_elf/chrome_elf.ver index 78f890e7ece7d..92d53efaa487f 100644 --- a/chrome_elf/chrome_elf.ver +++ b/chrome_elf/chrome_elf.ver @@ -1,2 +1,2 @@ -INTERNAL_NAME=chrome_elf_dll -ORIGINAL_FILENAME=chrome_elf.dll +INTERNAL_NAME=nw_elf_dll +ORIGINAL_FILENAME=nw_elf.dll diff --git a/chrome_elf/chrome_elf_main.cc b/chrome_elf/chrome_elf_main.cc index 50912fe157e88..c48448bc1e979 100644 --- a/chrome_elf/chrome_elf_main.cc +++ b/chrome_elf/chrome_elf_main.cc @@ -4,6 +4,7 @@ #include "chrome_elf/chrome_elf_main.h" +#include "components/crash/content/app/crash_reporter_client.h" #include #include @@ -14,10 +15,24 @@ #include "chrome_elf/blacklist/blacklist.h" #include "chrome_elf/crash/crash_helper.h" +extern std::wstring g_nwjs_prod_name, g_nwjs_prod_version; // This function is a temporary workaround for https://crbug.com/655788. We // need to come up with a better way to initialize crash reporting that can // happen inside DllMain(). -void SignalInitializeCrashReporting() { +void SignalInitializeCrashReporting(void* prod_name, void* prod_version) { + if (prod_name) g_nwjs_prod_name = *(std::wstring*)prod_name; + if (prod_version) g_nwjs_prod_version = *(std::wstring*)prod_version; + if (prod_name || prod_version) { + //install_static::InitializeProductDetailsForPrimaryModule(); +#if 0 + std::wstring user_data_dir, invalid_user_data_dir; + install_static::PrimaryInstallDetails* details = (install_static::PrimaryInstallDetails*)&install_static::InstallDetails::Get(); + const install_static::InstallDetails::Payload* payload = details->GetPayload(); + install_static::DeriveUserDataDirectory(*payload->mode, &user_data_dir, &invalid_user_data_dir); + details->set_user_data_dir(user_data_dir); + details->set_invalid_user_data_dir(invalid_user_data_dir); +#endif + } if (!elf_crash::InitializeCrashReporting()) { #ifdef _DEBUG assert(false); @@ -46,13 +61,19 @@ bool GetUserDataDirectoryThunk(wchar_t* user_data_dir, return true; } +void* ElfGetReporterClient() { + return crash_reporter::GetCrashReporterClient(); +} + BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { install_static::InitializeProductDetailsForPrimaryModule(); // CRT on initialization installs an exception filter which calls // TerminateProcess. We need to hook CRT's attempt to set an exception. +#if 0 ////disable this or NW will fail with Enigma VB elf_crash::DisableSetUnhandledExceptionFilter(); +#endif install_static::InitializeProcessType(); diff --git a/chrome_elf/chrome_elf_main.h b/chrome_elf/chrome_elf_main.h index c313294fe6fa5..1f6a7df3df69e 100644 --- a/chrome_elf/chrome_elf_main.h +++ b/chrome_elf/chrome_elf_main.h @@ -22,12 +22,13 @@ bool GetUserDataDirectoryThunk(wchar_t* user_data_dir, // This function is a temporary workaround for https://crbug.com/655788. We // need to come up with a better way to initialize crash reporting that can // happen inside DllMain(). -void SignalInitializeCrashReporting(); +void SignalInitializeCrashReporting(void*, void*); void SignalChromeElf(); // Sets the metrics client ID in crash keys. void SetMetricsClientId(const char* client_id); } // extern "C" +extern "C" void* ElfGetReporterClient(); #endif // CHROME_ELF_CHROME_ELF_MAIN_H_ diff --git a/chrome_elf/chrome_elf_x64.def b/chrome_elf/chrome_elf_x64.def index f4b3dfba8e119..201d758e5b23f 100644 --- a/chrome_elf/chrome_elf_x64.def +++ b/chrome_elf/chrome_elf_x64.def @@ -1,9 +1,10 @@ ; 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. -LIBRARY "chrome_elf.dll" +LIBRARY "nw_elf.dll" EXPORTS + ElfGetReporterClient ; When functions are added to this file, they must also be added to ; chrome_elf_x86.def diff --git a/chrome_elf/chrome_elf_x86.def b/chrome_elf/chrome_elf_x86.def index 258af5bf8ffbe..d9f51f8351d13 100644 --- a/chrome_elf/chrome_elf_x86.def +++ b/chrome_elf/chrome_elf_x86.def @@ -1,7 +1,8 @@ ; 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. -LIBRARY "chrome_elf.dll" + +LIBRARY "nw_elf.dll" EXPORTS ; When functions are added to this file, they must also be added to @@ -36,3 +37,4 @@ EXPORTS ; From chrome_elf/third_party_dlls/logs DrainLog RegisterLogNotification + ElfGetReporterClient diff --git a/components/about_ui/resources/about_credits.tmpl b/components/about_ui/resources/about_credits.tmpl index 9cf3f9aad0138..5d824d05bc4e5 100644 --- a/components/about_ui/resources/about_credits.tmpl +++ b/components/about_ui/resources/about_credits.tmpl @@ -48,7 +48,6 @@ body { background-color: #e8eef7; border-radius: 3px; clear: both; - display: none; padding: 16px; } .licence h3 { diff --git a/components/app_modal/javascript_dialog_manager.cc b/components/app_modal/javascript_dialog_manager.cc index 6e7dc9fdfbcd8..e6994c6b2e520 100644 --- a/components/app_modal/javascript_dialog_manager.cc +++ b/components/app_modal/javascript_dialog_manager.cc @@ -30,7 +30,7 @@ namespace { #if !defined(OS_ANDROID) // Keep in sync with kDefaultMessageWidth, but allow some space for the rest of // the text. -const int kUrlElideWidth = 350; +//const int kUrlElideWidth = 350; #endif class DefaultExtensionsClient : public JavaScriptDialogExtensionsClient { @@ -94,6 +94,8 @@ JavaScriptDialogManager::~JavaScriptDialogManager() { base::string16 JavaScriptDialogManager::GetTitle( content::WebContents* web_contents, const GURL& alerting_frame_url) { + return base::string16(); +#if 0 // For extensions, show the extension name, but only if the origin of // the alert matches the top-level WebContents. std::string name; @@ -158,6 +160,7 @@ base::string16 JavaScriptDialogManager::GetTitleImpl( is_same_origin_as_main_frame ? IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL : IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME); +#endif } void JavaScriptDialogManager::RunJavaScriptDialog( @@ -221,7 +224,7 @@ void JavaScriptDialogManager::RunJavaScriptDialog( AppModalDialogQueue::GetInstance()->AddDialog(new JavaScriptAppModalDialog( web_contents, &javascript_dialog_extra_data_, dialog_title, dialog_type, message_text, default_prompt_text, - ShouldDisplaySuppressCheckbox(extra_data), + false, //ShouldDisplaySuppressCheckbox(extra_data), false, // is_before_unload_dialog false, // is_reload base::BindOnce(&JavaScriptDialogManager::OnDialogClosed, diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 478ecb4cd5b5a..5e5397a2a4171 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc @@ -72,7 +72,7 @@ const net::BackoffEntry::Policy kAutofillBackoffPolicy = { #if defined(GOOGLE_CHROME_BUILD) const char kClientName[] = "Google+Chrome"; #else -const char kClientName[] = "Chromium"; +const char kClientName[] = "nwjs"; #endif // defined(GOOGLE_CHROME_BUILD) const char kDefaultAutofillServerURL[] = diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index 6a0478a2e2dad..2537e0d52dc63 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc @@ -146,7 +146,7 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::INHERIT_IN_INCOGNITO); Register(CONTENT_SETTINGS_TYPE_PLUGINS, "plugins", - CONTENT_SETTING_DETECT_IMPORTANT_CONTENT, + CONTENT_SETTING_ALLOW, WebsiteSettingsInfo::SYNCABLE, WhitelistedSchemes(kChromeUIScheme, kChromeDevToolsScheme), ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, @@ -176,7 +176,7 @@ void ContentSettingsRegistry::Init() { ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE); Register(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications", - CONTENT_SETTING_ASK, WebsiteSettingsInfo::UNSYNCABLE, + CONTENT_SETTING_ALLOW, WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(), ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK), diff --git a/components/cookie_config/cookie_store_util.cc b/components/cookie_config/cookie_store_util.cc index c1aa494335c04..15f106b019aa4 100644 --- a/components/cookie_config/cookie_store_util.cc +++ b/components/cookie_config/cookie_store_util.cc @@ -14,6 +14,8 @@ namespace cookie_config { #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) namespace { +bool g_should_encrypt = true; + // Use the operating system's mechanisms to encrypt cookies before writing // them to persistent store. Currently this only is done with desktop OS's // because ChromeOS and Android already protect the entire profile contents. @@ -39,7 +41,7 @@ bool CookieOSCryptoDelegate::ShouldEncrypt() { // rewritten. return false; #else - return true; + return g_should_encrypt; #endif } @@ -63,6 +65,11 @@ base::LazyInstance::DestructorAtExit net::CookieCryptoDelegate* GetCookieCryptoDelegate() { return g_cookie_crypto_delegate.Pointer(); } + +void SetEnableCookieCrypto(bool enable) { + g_should_encrypt = enable; +} + #else // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) net::CookieCryptoDelegate* GetCookieCryptoDelegate() { return NULL; diff --git a/components/cookie_config/cookie_store_util.h b/components/cookie_config/cookie_store_util.h index 893e6a07db7c8..ea782212ec4ad 100644 --- a/components/cookie_config/cookie_store_util.h +++ b/components/cookie_config/cookie_store_util.h @@ -15,7 +15,7 @@ namespace cookie_config { // this platform. The object returned is a LazyInstance. Ownership is not // transferred. net::CookieCryptoDelegate* GetCookieCryptoDelegate(); - +void SetEnableCookieCrypto(bool enable); } // namespace cookie_config #endif // COMPONENTS_COOKIE_CONFIG_COOKIE_STORE_UTIL_H_ diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc index 76f15cb5b5118..f885861fd7793 100644 --- a/components/crash/content/app/breakpad_linux.cc +++ b/components/crash/content/app/breakpad_linux.cc @@ -86,7 +86,7 @@ namespace breakpad { namespace { -#if !defined(OS_CHROMEOS) +#if 0 const char kUploadURL[] = "https://clients2.google.com/cr/report"; #endif @@ -796,7 +796,6 @@ void EnableCrashDumping(bool unattended) { minidump_descriptor.set_size_limit(kMaxMinidumpFileSize); } #if defined(OS_ANDROID) - unattended = true; // Android never uploads directly. SetMinidumpSanitizationFields(&minidump_descriptor, sanitization_info); #endif if (unattended) { @@ -1336,12 +1335,28 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info, StringFromPrefixAndUint("/dev/fd/", upload_status_fd, allocator); static const char kWgetBinary[] = "/usr/bin/wget"; + char* const upload_url = reinterpret_cast(allocator->Alloc(1024)); + *upload_url='\0'; + int i = 1; + do { + char key_name[17]; + my_strlcpy(key_name, "url-nwjs__", sizeof(key_name)); + my_uitos(key_name + 10, i, my_uint_len(i)); + key_name[10 + my_uint_len(i)] = '\0'; + const char* chunk = crash_reporter::internal::GetCrashKeyStorage()->GetValueForKey(key_name); + if (!chunk) + break; + my_strlcat(upload_url, chunk, 1024); + i++; + } while(true); + //WriteLog("UPLOAD_URL", 10); + //WriteLog(upload_url, my_strlen(upload_url)); const char* args[] = { kWgetBinary, header_content_encoding, header_content_type, post_file, - kUploadURL, + upload_url, "--timeout=10", // Set a timeout so we don't hang forever. "--tries=1", // Don't retry if the upload fails. "-O", // Output reply to the file descriptor path. diff --git a/components/crash/content/app/crash_reporter_client.cc b/components/crash/content/app/crash_reporter_client.cc index 464fe2efc0db1..c662c47d0d4fc 100644 --- a/components/crash/content/app/crash_reporter_client.cc +++ b/components/crash/content/app/crash_reporter_client.cc @@ -41,6 +41,10 @@ void CrashReporterClient::SetCrashReporterClientIdFromGUID( const std::string& client_guid) {} #endif +void CrashReporterClient::SetUploadDump(bool upload) { + enable_upload_ = upload; +} + #if defined(OS_WIN) bool CrashReporterClient::ShouldCreatePipeName( const base::string16& process_type) { @@ -88,7 +92,7 @@ int CrashReporterClient::GetResultCodeRespawnFailed() { } #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) +#if defined(OS_POSIX) && !defined(OS_IOS) void CrashReporterClient::GetProductNameAndVersion(const char** product_name, const char** version) { } diff --git a/components/crash/content/app/crash_reporter_client.h b/components/crash/content/app/crash_reporter_client.h index e6a09126bdb98..dc5fd99c3ef10 100644 --- a/components/crash/content/app/crash_reporter_client.h +++ b/components/crash/content/app/crash_reporter_client.h @@ -25,7 +25,7 @@ class CrashReporterClient; // runtime. void SetCrashReporterClient(CrashReporterClient* client); -#if defined(CRASH_IMPLEMENTATION) +#if 1 // The components's embedder API should only be used by the component. CrashReporterClient* GetCrashReporterClient(); #endif @@ -46,7 +46,7 @@ class CrashReporterClient { // not be set directly by the client. virtual void SetCrashReporterClientIdFromGUID(const std::string& client_guid); #endif - + virtual void SetUploadDump(bool); #if defined(OS_WIN) // Returns true if the pipe name to connect to breakpad should be computed and // stored in the process's environment block. By default, returns true for the @@ -91,7 +91,7 @@ class CrashReporterClient { virtual int GetResultCodeRespawnFailed(); #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) +#if defined(OS_POSIX) && !defined(OS_IOS) // Returns a textual description of the product type and version to include // in the crash report. Neither out parameter should be set to NULL. // TODO(jperaza): Remove the 2-parameter overload of this method once all @@ -181,6 +181,10 @@ class CrashReporterClient { // Returns true if breakpad should run in the given process type. virtual bool EnableBreakpadForProcess(const std::string& process_type); + + bool enable_upload_; + std::string product_name_; + std::string product_version_; }; } // namespace crash_reporter diff --git a/components/crash/content/app/crashpad_mac.mm b/components/crash/content/app/crashpad_mac.mm index f06d903c2f41b..d61d53a86f9ee 100644 --- a/components/crash/content/app/crashpad_mac.mm +++ b/components/crash/content/app/crashpad_mac.mm @@ -125,6 +125,10 @@ void DumpProcessWithoutCrashing(task_t task_port) { // Is there a way to recover if this fails? CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); + const char* product_name = ""; + const char* version = ""; + + crash_reporter_client->GetProductNameAndVersion(&product_name, &version); crash_reporter_client->GetCrashDumpLocation(&database_path); crash_reporter_client->GetCrashMetricsLocation(&metrics_path); @@ -136,6 +140,11 @@ void DumpProcessWithoutCrashing(task_t task_port) { std::string url; #endif + std::map process_annotations; + process_annotations["prod"] = product_name; + process_annotations["ver"] = version; + process_annotations["plat"] = std::string("OS X"); + std::vector arguments; if (crash_reporter_client->ShouldMonitorCrashHandlerExpensively()) { @@ -156,9 +165,10 @@ void DumpProcessWithoutCrashing(task_t task_port) { "--reset-own-crash-exception-port-to-system-default"); } + bool result = GetCrashpadClient().StartHandler( handler_path, database_path, metrics_path, url, - GetProcessSimpleAnnotations(), arguments, true, false); + process_annotations, arguments, true, false); // If this is an initial client that's not the browser process, it's // important to sever the connection to any existing handler. If diff --git a/components/crx_file/id_util.cc b/components/crx_file/id_util.cc index d896ab491b648..6818e9406d589 100644 --- a/components/crx_file/id_util.cc +++ b/components/crx_file/id_util.cc @@ -88,6 +88,7 @@ base::FilePath MaybeNormalizePath(const base::FilePath& path) { } bool IdIsValid(const std::string& id) { +#if 0 // Verify that the id is legal. if (id.size() != (crx_file::id_util::kIdSize * 2)) return false; @@ -98,6 +99,7 @@ bool IdIsValid(const std::string& id) { return false; } +#endif return true; } diff --git a/components/gcm_driver/gcm_channel_status_syncer.cc b/components/gcm_driver/gcm_channel_status_syncer.cc index 6ef1f13c2834c..18400d0270283 100644 --- a/components/gcm_driver/gcm_channel_status_syncer.cc +++ b/components/gcm_driver/gcm_channel_status_syncer.cc @@ -20,6 +20,8 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "content/nw/src/nw_base.h" + namespace gcm { namespace { @@ -61,7 +63,7 @@ const char kCustomPollIntervalMinutes[] = "gcm-channel-poll-interval"; // static void GCMChannelStatusSyncer::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterBooleanPref(prefs::kGCMChannelStatus, true); + registry->RegisterBooleanPref(prefs::kGCMChannelStatus, nw::gcm_enabled()); registry->RegisterIntegerPref( prefs::kGCMChannelPollIntervalSeconds, GCMChannelStatusRequest::default_poll_interval_seconds()); @@ -71,7 +73,7 @@ void GCMChannelStatusSyncer::RegisterPrefs(PrefRegistrySimple* registry) { // static void GCMChannelStatusSyncer::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref(prefs::kGCMChannelStatus, true); + registry->RegisterBooleanPref(prefs::kGCMChannelStatus, nw::gcm_enabled()); registry->RegisterIntegerPref( prefs::kGCMChannelPollIntervalSeconds, GCMChannelStatusRequest::default_poll_interval_seconds()); @@ -95,7 +97,7 @@ GCMChannelStatusSyncer::GCMChannelStatusSyncer( user_agent_(user_agent), request_context_(request_context), started_(false), - gcm_enabled_(true), + gcm_enabled_(nw::gcm_enabled()), poll_interval_seconds_( GCMChannelStatusRequest::default_poll_interval_seconds()), custom_poll_interval_use_count_(0), diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc index dbae814977cec..58f8b3f5aa6d9 100644 --- a/components/gcm_driver/gcm_driver_desktop.cc +++ b/components/gcm_driver/gcm_driver_desktop.cc @@ -32,6 +32,8 @@ #include "components/timers/alarm_timer_chromeos.h" #endif +#include "content/nw/src/nw_base.h" + namespace gcm { class GCMDriverDesktop::IOWorker : public GCMClient::Delegate { @@ -1271,7 +1273,8 @@ GCMClient::Result GCMDriverDesktop::EnsureStarted( // Polling for channel status should be invoked when GCM is being requested, // no matter whether GCM is enabled or nor. - gcm_channel_status_syncer_->EnsureStarted(); + if (nw::gcm_enabled()) + gcm_channel_status_syncer_->EnsureStarted(); if (!gcm_enabled_) return GCMClient::GCM_DISABLED; diff --git a/components/guest_view/browser/guest_view_manager.cc b/components/guest_view/browser/guest_view_manager.cc index a18eacb3b74c7..c41742b086b3a 100644 --- a/components/guest_view/browser/guest_view_manager.cc +++ b/components/guest_view/browser/guest_view_manager.cc @@ -486,10 +486,11 @@ bool GuestViewManager::CanEmbedderAccessInstanceID( // Other than MimeHandlerViewGuest, all other guest types are only permitted // to run in the main frame. - return embedder_render_process_id == guest_view->owner_web_contents() - ->GetMainFrame() - ->GetProcess() - ->GetID(); + // return embedder_render_process_id == guest_view->owner_web_contents() + // ->GetMainFrame() + // ->GetProcess() + // ->GetID(); + return true; } GuestViewManager::ElementInstanceKey::ElementInstanceKey() diff --git a/components/guest_view/browser/guest_view_manager.h b/components/guest_view/browser/guest_view_manager.h index 9045a219f5b48..7231098686aad 100644 --- a/components/guest_view/browser/guest_view_manager.h +++ b/components/guest_view/browser/guest_view_manager.h @@ -202,9 +202,12 @@ class GuestViewManager : public content::BrowserPluginGuestManager, content::WebContents* guest_web_contents); // Contains guests' WebContents, mapping from their instance ids. + public: using GuestInstanceMap = std::map; + const GuestInstanceMap& guest_web_contents_by_instance_id() { return guest_web_contents_by_instance_id_; } + protected: GuestInstanceMap guest_web_contents_by_instance_id_; - + struct ElementInstanceKey { int embedder_process_id; int element_instance_id; diff --git a/components/infobars/core/simple_alert_infobar_delegate.cc b/components/infobars/core/simple_alert_infobar_delegate.cc index a74326d69de8d..65c2594fbeb8b 100644 --- a/components/infobars/core/simple_alert_infobar_delegate.cc +++ b/components/infobars/core/simple_alert_infobar_delegate.cc @@ -17,6 +17,9 @@ void SimpleAlertInfoBarDelegate::Create( const gfx::VectorIcon* vector_icon, const base::string16& message, bool auto_expire) { + //NWJS#6340: Crash on select file dialog when policy deny it + if (!infobar_manager) + return; infobar_manager->AddInfoBar(infobar_manager->CreateConfirmInfoBar( std::unique_ptr(new SimpleAlertInfoBarDelegate( infobar_identifier, vector_icon, message, auto_expire)))); diff --git a/components/keep_alive_registry/keep_alive_registry.h b/components/keep_alive_registry/keep_alive_registry.h index 40d4ed0c05920..4eb4632df138b 100644 --- a/components/keep_alive_registry/keep_alive_registry.h +++ b/components/keep_alive_registry/keep_alive_registry.h @@ -65,10 +65,12 @@ class KeepAliveRegistry { KeepAliveRegistry(); ~KeepAliveRegistry(); + public: // Add/Remove entries. Do not use directly, use ScopedKeepAlive instead. void Register(KeepAliveOrigin origin, KeepAliveRestartOption restart); void Unregister(KeepAliveOrigin origin, KeepAliveRestartOption restart); + private: // Methods called when a specific aspect of the state of the registry changes. void OnKeepAliveStateChanged(bool new_keeping_alive); void OnRestartAllowedChanged(bool new_restart_allowed); diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index b800b64ccc149..955d36bb4cc82 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc @@ -218,7 +218,7 @@ MetricsService::MetricsService(MetricsStateManager* state_manager, client_(client), local_state_(local_state), recording_state_(UNSET), - test_mode_active_(false), + test_mode_active_(true), state_(INITIALIZED), idle_since_last_transmission_(false), session_id_(-1), @@ -261,9 +261,9 @@ void MetricsService::InitializeMetricsRecordingState() { } void MetricsService::Start() { - HandleIdleSinceLastTransmission(false); + test_mode_active_ = true; EnableRecording(); - EnableReporting(); + DisableReporting(); } void MetricsService::StartRecordingForTests() { diff --git a/components/metrics_services_manager/metrics_services_manager.cc b/components/metrics_services_manager/metrics_services_manager.cc index 49526315ac1c9..60481cc4a2356 100644 --- a/components/metrics_services_manager/metrics_services_manager.cc +++ b/components/metrics_services_manager/metrics_services_manager.cc @@ -42,11 +42,13 @@ metrics::MetricsService* MetricsServicesManager::GetMetricsService() { } rappor::RapporServiceImpl* MetricsServicesManager::GetRapporServiceImpl() { +#if 0 DCHECK(thread_checker_.CalledOnValidThread()); if (!rappor_service_) { rappor_service_ = client_->CreateRapporServiceImpl(); rappor_service_->Initialize(client_->GetURLLoaderFactory()); } +#endif return rappor_service_.get(); } @@ -110,10 +112,10 @@ void MetricsServicesManager::UpdateRunningServices() { DCHECK(thread_checker_.CalledOnValidThread()); metrics::MetricsService* metrics = GetMetricsService(); - const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - if (cmdline->HasSwitch(metrics::switches::kMetricsRecordingOnly)) { + //const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + if (true /*cmdline->HasSwitch(metrics::switches::kMetricsRecordingOnly)*/) { metrics->StartRecordingForTests(); - GetRapporServiceImpl()->Update(true, false); + //GetRapporServiceImpl()->Update(true, false); return; } @@ -130,9 +132,11 @@ void MetricsServicesManager::UpdateRunningServices() { metrics->Stop(); } +#if defined(GOOGLE_CHROME_BUILD) UpdateUkmService(); - GetRapporServiceImpl()->Update(may_record_, may_upload_); + //GetRapporServiceImpl()->Update(may_record_, may_upload_); +#endif // defined(GOOGLE_CHROME_BUILD) } void MetricsServicesManager::UpdateUkmService() { diff --git a/components/nacl/features.gni b/components/nacl/features.gni index 1a09aafc97daf..c3f90601e37a8 100644 --- a/components/nacl/features.gni +++ b/components/nacl/features.gni @@ -9,10 +9,7 @@ declare_args() { # Enables Native Client support. # Temporarily disable nacl on arm64 linux to get rid of compilation errors. # TODO: When mipsel-nacl-clang is available, drop the exclusion. - enable_nacl = - checkout_nacl && !is_ios && !is_android && !is_fuchsia && - !is_chromecast && current_cpu != "mipsel" && current_cpu != "mips64el" && - !(is_linux && target_cpu == "arm64") && !(is_win && host_os != "win") + enable_nacl = false # Non-SFI is not yet supported on mipsel enable_nacl_nonsfi = current_cpu != "mipsel" && current_cpu != "mips64el" diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn index c468773ce224d..1bcef26c1590c 100644 --- a/components/nacl/loader/BUILD.gn +++ b/components/nacl/loader/BUILD.gn @@ -159,6 +159,13 @@ if (is_linux) { } } + if (is_linux) { + if (!is_component_build) { + # Set rpath to find our own libfreetype even in a non-component build. + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } + } + data_deps = [ "//native_client/src/trusted/service_runtime/linux:bootstrap", ] diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc index 50230ec6a8e3c..a0918cd53a5aa 100644 --- a/components/nacl/loader/nacl_helper_linux.cc +++ b/components/nacl/loader/nacl_helper_linux.cc @@ -286,7 +286,7 @@ bool HonorRequestAndReply(int reply_fd, } if (!have_to_reply) return false; - const std::vector empty; // We never send file descriptors back. + const std::vector empty = std::vector(); // We never send file descriptors back. if (!base::UnixDomainSocket::SendMsg(reply_fd, write_pickle.data(), write_pickle.size(), empty)) { LOG(ERROR) << "*** send() to zygote failed"; @@ -306,11 +306,13 @@ bool HandleZygoteRequest(int zygote_ipc_fd, &buf, sizeof(buf), &fds); // If the Zygote has started handling requests, we should be sandboxed via // the setuid sandbox. +#if 0 if (!nacl_sandbox->layer_one_enabled()) { LOG(ERROR) << "NaCl helper process running without a sandbox!\n" << "Most likely you need to configure your SUID sandbox " << "correctly"; } +#endif if (msglen == 0 || (msglen == -1 && errno == ECONNRESET)) { // EOF from the browser. Goodbye! _exit(0); @@ -442,7 +444,7 @@ int main(int argc, char* argv[]) { nacl_sandbox->InitializeLayerOneSandbox(); CHECK_EQ(is_init_process, nacl_sandbox->layer_one_enabled()); - const std::vector empty; + const std::vector empty = std::vector(); // Send the zygote a message to let it know we are ready to help if (!base::UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, kNaClHelperStartupAck, diff --git a/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc b/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc index 9babfaa076b97..8c56f6ba23866 100644 --- a/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc +++ b/components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc @@ -181,7 +181,7 @@ void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) { // have a single thread running here. DCHECK(!layer_one_sealed_); CHECK(IsSingleThreaded()); - CheckForExpectedNumberOfOpenFds(); + //CheckForExpectedNumberOfOpenFds(); RestrictAddressSpaceUsage(); diff --git a/components/nacl/zygote/nacl_fork_delegate_linux.cc b/components/nacl/zygote/nacl_fork_delegate_linux.cc index c5c5f29c8a1d7..3d679206f788e 100644 --- a/components/nacl/zygote/nacl_fork_delegate_linux.cc +++ b/components/nacl/zygote/nacl_fork_delegate_linux.cc @@ -408,7 +408,7 @@ bool NaClForkDelegate::GetTerminationStatus(pid_t pid, bool known_dead, write_pickle.WriteInt(pid); write_pickle.WriteBool(known_dead); - const std::vector empty_fds; + const std::vector empty_fds = std::vector(); char reply_buf[kNaClMaxIPCMessageLength]; ssize_t reply_size = 0; bool got_reply = diff --git a/components/network_time/network_time_tracker.cc b/components/network_time/network_time_tracker.cc index b9581ce9d78cd..587053e9e5a3f 100644 --- a/components/network_time/network_time_tracker.cc +++ b/components/network_time/network_time_tracker.cc @@ -43,7 +43,7 @@ const base::Feature kNetworkTimeServiceQuerying{ "NetworkTimeServiceQuerying", base::FEATURE_DISABLED_BY_DEFAULT}; #else const base::Feature kNetworkTimeServiceQuerying{ - "NetworkTimeServiceQuerying", base::FEATURE_ENABLED_BY_DEFAULT}; + "NetworkTimeServiceQuerying", base::FEATURE_DISABLED_BY_DEFAULT}; #endif namespace { diff --git a/components/os_crypt/keychain_password_mac.mm b/components/os_crypt/keychain_password_mac.mm index 2b38db266f9aa..ae90f4a69c1fe 100644 --- a/components/os_crypt/keychain_password_mac.mm +++ b/components/os_crypt/keychain_password_mac.mm @@ -54,8 +54,8 @@ const char KeychainPassword::service_name[] = "Chrome Safe Storage"; const char KeychainPassword::account_name[] = "Chrome"; #else -const char KeychainPassword::service_name[] = "Chromium Safe Storage"; -const char KeychainPassword::account_name[] = "Chromium"; +const char KeychainPassword::service_name[] = "NWJS Safe Storage"; +const char KeychainPassword::account_name[] = "nwjs"; #endif std::string KeychainPassword::GetPassword() const { diff --git a/components/os_crypt/os_crypt_mac.mm b/components/os_crypt/os_crypt_mac.mm index 592d1b007980a..74de02e732b02 100644 --- a/components/os_crypt/os_crypt_mac.mm +++ b/components/os_crypt/os_crypt_mac.mm @@ -34,7 +34,7 @@ const size_t kEncryptionIterations = 1003; // TODO(dhollowa): Refactor to allow dependency injection of Keychain. -static bool use_mock_keychain = false; +static bool use_mock_keychain = true; // Prefix for cypher text returned by current encryption version. We prefix // the cypher text with this string so that future data migration can detect diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index b5383eb386e17..8f7a9055bc490 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc @@ -765,6 +765,8 @@ bool PasswordManager::ShouldBlockPasswordForSameOriginButDifferentScheme( } bool PasswordManager::ShouldPromptUserToSavePassword() const { + return false; +#if 0 return (provisional_save_manager_->IsNewLogin() || provisional_save_manager_ ->is_possible_change_password_form_without_username() || @@ -773,6 +775,7 @@ bool PasswordManager::ShouldPromptUserToSavePassword() const { !(provisional_save_manager_->has_generated_password() && provisional_save_manager_->IsNewLogin()) && !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); +#endif } void PasswordManager::OnPasswordFormsRendered( diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index a791237f311e2..2f721247aec4b 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc @@ -77,7 +77,7 @@ void PaymentRequest::Init(mojom::PaymentRequestClientPtr client, return; } - bool allowed_origin = + bool allowed_origin = last_committed_url.SchemeIs("chrome-extension") || OriginSecurityChecker::IsSchemeCryptographic(last_committed_url) || OriginSecurityChecker::IsOriginLocalhostOrFile(last_committed_url); if (!allowed_origin) { @@ -169,6 +169,7 @@ void PaymentRequest::Show(bool is_user_gesture) { return; } +#if 0 if (!delegate_->IsBrowserWindowActive()) { LOG(ERROR) << "Cannot show PaymentRequest UI in a background tab"; journey_logger_.SetNotShown(JourneyLogger::NOT_SHOWN_REASON_OTHER); @@ -177,6 +178,7 @@ void PaymentRequest::Show(bool is_user_gesture) { return; } +#endif is_show_user_gesture_ = is_user_gesture; // TODO(crbug.com/783811): Display a spinner when checking whether diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index b240ad23334cb..4ea9a13a3cb22 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn @@ -82,3 +82,9 @@ action("about_credits") { rebase_path(about_credits_file, root_build_dir), ] } + +copy("about_credits_nw") { + sources = [ about_credits_file ] + outputs = [ "$root_build_dir/credits.html" ] + deps = [ ":about_credits" ] +} \ No newline at end of file diff --git a/components/storage_monitor/portable_device_watcher_win.cc b/components/storage_monitor/portable_device_watcher_win.cc index 6fea011ba4fe9..4df0c81d8aa85 100644 --- a/components/storage_monitor/portable_device_watcher_win.cc +++ b/components/storage_monitor/portable_device_watcher_win.cc @@ -31,7 +31,7 @@ namespace storage_monitor { namespace { // Name of the client application that communicates with the MTP device. -const base::char16 kClientName[] = L"Chromium"; +const base::char16 kClientName[] = L"nwjs"; // Returns true if |data| represents a class of portable devices. bool IsPortableDeviceStructure(LPARAM data) { diff --git a/components/translate/core/language_detection/BUILD.gn b/components/translate/core/language_detection/BUILD.gn index 5653eb1404ff6..aba9d96b4a5b4 100644 --- a/components/translate/core/language_detection/BUILD.gn +++ b/components/translate/core/language_detection/BUILD.gn @@ -26,7 +26,7 @@ static_library("language_detection") { ":chinese_script_classifier", "//base", "//components/translate/core/common", - "//third_party/cld_3/src/src:cld_3", + #"//third_party/cld_3/src/src:cld_3", "//third_party/icu", "//url", ] diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc index ba84cac14b3a2..742a895cf59c9 100644 --- a/components/viz/service/display_embedder/software_output_device_win.cc +++ b/components/viz/service/display_embedder/software_output_device_win.cc @@ -14,6 +14,7 @@ #include "skia/ext/platform_canvas.h" #include "skia/ext/skia_utils_win.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "ui/display/display.h" #include "ui/gfx/gdi_util.h" #include "ui/gfx/skia_util.h" @@ -209,6 +210,10 @@ void SoftwareOutputDeviceWinLayered::EndPaintDelegated( RECT wr; GetWindowRect(hwnd(), &wr); SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; + if (content::g_force_cpu_draw) { + size.cx = canvas_->getDeviceClipBounds().width(); + size.cy = canvas_->getDeviceClipBounds().height(); + } POINT position = {wr.left, wr.top}; POINT zero = {0, 0}; BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA}; diff --git a/components/webdata_services/web_data_service_wrapper.cc b/components/webdata_services/web_data_service_wrapper.cc index 6f6d495a4ccd8..e8687cb2139ae 100644 --- a/components/webdata_services/web_data_service_wrapper.cc +++ b/components/webdata_services/web_data_service_wrapper.cc @@ -49,6 +49,7 @@ void InitSyncableServicesOnDBSequence( autofill::AutofillWebDataBackend* autofill_backend) { DCHECK(db_task_runner->RunsTasksInCurrentSequence()); +#if 0 // Currently only Autocomplete and Autofill profiles use the new Sync API, but // all the database data should migrate to this API over time. autofill::AutocompleteSyncBridge::CreateForWebDataServiceAndBackend( @@ -68,6 +69,7 @@ void InitSyncableServicesOnDBSequence( autofill::AutofillWalletSyncableService::FromWebDataService( autofill_web_data.get()) ->InjectStartSyncFlare(sync_flare); +#endif } } // namespace diff --git a/content/BUILD.gn b/content/BUILD.gn index 09962146a2426..2b143809cc58d 100644 --- a/content/BUILD.gn +++ b/content/BUILD.gn @@ -62,6 +62,7 @@ config("content_implementation") { if (!is_nacl_nonsfi) { content_shared_components = [ + "//content/nw:nw_base", "//content/gpu:gpu_sources", "//content/public/browser:browser_sources", "//content/public/child:child_sources", @@ -83,6 +84,7 @@ if (is_component_build) { content_shared_components + [ "//content/public/app:both_sources" ] deps = [ "//build/config:exe_and_shlib_deps", + "//content/nw:nw_content", ] } } else if (is_nacl_nonsfi) { diff --git a/content/app/content_main.cc b/content/app/content_main.cc index 657761cb5dc58..dbf83ac1751c0 100644 --- a/content/app/content_main.cc +++ b/content/app/content_main.cc @@ -16,7 +16,7 @@ int ContentMain(const ContentMainParams& params) { main_params.argc = params.argc; main_params.argv = params.argv; #endif - return service_manager::Main(main_params); + return service_manager::Main(main_params); } } // namespace content diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc index 83e8990edf17e..73f797f585d26 100644 --- a/content/app/content_main_runner_impl.cc +++ b/content/app/content_main_runner_impl.cc @@ -934,7 +934,7 @@ int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) { int ContentMainRunnerImpl::Run() { DCHECK(is_initialized_); DCHECK(!is_shutdown_); - const base::CommandLine& command_line = + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); std::string process_type = command_line.GetSwitchValueASCII(switches::kProcessType); @@ -946,6 +946,10 @@ int ContentMainRunnerImpl::Run() { process_type != service_manager::switches::kZygoteProcess) InitializeFieldTrialAndFeatureList(&field_trial_list); + if (process_type.empty()) { + command_line.AppendSwitch(service_manager::switches::kNoSandbox); + command_line.AppendSwitch(switches::kNoZygote); + } MainFunctionParams main_params(command_line); main_params.ui_task = ui_task_; main_params.created_main_parts_closure = created_main_parts_closure_; diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 10de251accf85..3d9ea06dc7b84 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -492,7 +492,7 @@ class HDRProxy { // The currently-running BrowserMainLoop. There can be one or zero. BrowserMainLoop* g_current_browser_main_loop = nullptr; -#if defined(OS_ANDROID) +#if 1 //defined(OS_ANDROID) bool g_browser_main_loop_shutting_down = false; #endif @@ -998,13 +998,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { base::BindOnce( base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true)); -#if defined(OS_ANDROID) +#if 1 //defined(OS_ANDROID) g_browser_main_loop_shutting_down = true; #endif - if (RenderProcessHost::run_renderer_in_process()) - RenderProcessHostImpl::ShutDownInProcessRenderer(); - #if BUILDFLAG(ENABLE_MUS) // NOTE: because of dependencies this has to happen before // PostMainMessageLoopRun(). @@ -1017,6 +1014,9 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { parts_->PostMainMessageLoopRun(); } + if (RenderProcessHost::run_renderer_in_process()) + RenderProcessHostImpl::ShutDownInProcessRenderer(); + system_stats_monitor_.reset(); // Cancel pending requests and prevent new requests. diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index a0bc9305e62dc..359b9fe368352 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc @@ -4,6 +4,10 @@ #include "content/browser/browser_plugin/browser_plugin_guest.h" +#include "content/nw/src/nw_base.h" +#include "content/nw/src/common/shell_switches.h" +#include "base/files/file_util.h" + #include #include @@ -341,6 +345,20 @@ void BrowserPluginGuest::InitInternal( // Disable "client blocked" error page for browser plugin. renderer_prefs->disable_client_blocked_error_page = true; + base::ThreadRestrictions::ScopedAllowIO allow_io; + nw::Package* package = nw::package(); + std::string js_doc_start, js_doc_end; + package->root()->GetString(::switches::kmInjectJSDocStart, &js_doc_start); + if (!js_doc_start.empty()) { + std::string fpath = base::MakeAbsoluteFilePath(package->path()).AppendASCII(js_doc_start).AsUTF8Unsafe(); + renderer_prefs->nw_inject_js_doc_start = fpath; + } + package->root()->GetString(::switches::kmInjectJSDocEnd, &js_doc_end); + if (!js_doc_end.empty()) { + std::string fpath = base::MakeAbsoluteFilePath(package->path()).AppendASCII(js_doc_end).AsUTF8Unsafe(); + renderer_prefs->nw_inject_js_doc_end = fpath; + } + embedder_visibility_observer_.reset(new EmbedderVisibilityObserver(this)); DCHECK(GetWebContents()->GetRenderViewHost()); diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 4bf51fd3352ee..7c9efa366fb7b 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc @@ -101,7 +101,8 @@ bool IsMalformedBlobUrl(const GURL& url) { class ChildProcessSecurityPolicyImpl::SecurityState { public: SecurityState() - : enabled_bindings_(0), + : grant_all_(false), + enabled_bindings_(0), can_read_raw_cookies_(false), can_send_midi_sysex_(false) { } @@ -117,6 +118,9 @@ class ChildProcessSecurityPolicyImpl::SecurityState { file_permissions_.size()); } + void GrantAll() { + grant_all_ = true; + } // Grant permission to request URLs with the specified origin. void GrantOrigin(const url::Origin& origin) { origin_set_.insert(origin); @@ -202,6 +206,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState { bool CanCommitURL(const GURL& url) { DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem()) << "inner_url extraction should be done already."; + if (grant_all_) + return true; // Having permission to a scheme implies permission to all of its URLs. SchemeSet::const_iterator scheme_judgment( scheme_policy_.find(url.scheme())); @@ -229,6 +235,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState { if (file.IsContentUri()) return HasPermissionsForContentUri(file, permissions); #endif + if (grant_all_) + return true; if (!permissions || file.empty() || !file.IsAbsolute()) return false; base::FilePath current_path = file.StripTrailingSeparators(); @@ -300,6 +308,7 @@ class ChildProcessSecurityPolicyImpl::SecurityState { typedef std::map FileSystemMap; typedef std::set FileSet; + bool grant_all_; // Maps URL schemes to whether permission has been granted, containment means // that the scheme has been granted, otherwise, it has never been granted. // There is no provision for revoking. @@ -342,7 +351,7 @@ ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { // IsWebSafeScheme(), and then eliminate the next two lines. RegisterWebSafeScheme(url::kBlobScheme); RegisterWebSafeScheme(url::kFileSystemScheme); - + //RegisterWebSafeScheme("chrome-devtools"); // We know about the following pseudo schemes and treat them specially. RegisterPseudoScheme(url::kAboutScheme); RegisterPseudoScheme(url::kJavaScriptScheme); @@ -482,6 +491,15 @@ void ChildProcessSecurityPolicyImpl::GrantRequestSpecificFileURL( } } +void ChildProcessSecurityPolicyImpl::GrantAll(int child_id) { + base::AutoLock lock(lock_); + SecurityStateMap::iterator state = security_state_.find(child_id); + if (state == security_state_.end()) + return; + + state->second->GrantAll(); +} + void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id, const base::FilePath& file) { GrantPermissionsForFile(child_id, file, READ_FILE_GRANT); diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h index 47eb33219766a..52e41f345de3b 100644 --- a/content/browser/child_process_security_policy_impl.h +++ b/content/browser/child_process_security_policy_impl.h @@ -52,6 +52,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl static ChildProcessSecurityPolicyImpl* GetInstance(); // ChildProcessSecurityPolicy implementation. + void GrantAll(int child_id) override; void RegisterWebSafeScheme(const std::string& scheme) override; void RegisterWebSafeIsolatedScheme( const std::string& scheme, diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc index c9187e7749536..4bba0163097fd 100644 --- a/content/browser/devtools/devtools_http_handler.cc +++ b/content/browser/devtools/devtools_http_handler.cc @@ -34,6 +34,8 @@ #include "content/public/browser/devtools_frontend_host.h" #include "content/public/browser/devtools_manager_delegate.h" #include "content/public/browser/devtools_socket_factory.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" @@ -61,10 +63,14 @@ namespace { const base::FilePath::CharType kDevToolsActivePortFileName[] = FILE_PATH_LITERAL("DevToolsActivePort"); +#if defined(NWJS_SDK) const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread"; +#endif const char kPageUrlPrefix[] = "/devtools/page/"; +#if defined(NWJS_SDK) const char kBrowserUrlPrefix[] = "/devtools/browser"; +#endif const char kTargetIdField[] = "id"; const char kTargetParentIdField[] = "parentId"; @@ -696,8 +702,13 @@ void DevToolsHttpHandler::RespondToJsonList( DevToolsAgentHost::List agent_hosts = std::move(hosts); std::sort(agent_hosts.begin(), agent_hosts.end(), TimeComparator); base::ListValue list_value; - for (auto& agent_host : agent_hosts) + for (auto& agent_host : agent_hosts) { + WebContents* web_contents = agent_host->GetWebContents(); + if (web_contents && web_contents->GetMainFrame()) + if (!web_contents->GetMainFrame()->context_created()) + continue; list_value.Append(SerializeDescriptor(agent_host, host)); + } SendJson(connection_id, net::HTTP_OK, &list_value, std::string()); } @@ -776,6 +787,7 @@ DevToolsHttpHandler::DevToolsHttpHandler( const base::FilePath& output_directory, const base::FilePath& debug_frontend_dir) : delegate_(delegate), weak_factory_(this) { +#if defined(NWJS_SDK) browser_guid_ = delegate_->IsBrowserTargetDiscoverable() ? kBrowserUrlPrefix : base::StringPrintf("%s/%s", kBrowserUrlPrefix, @@ -793,6 +805,7 @@ DevToolsHttpHandler::DevToolsHttpHandler( output_directory, debug_frontend_dir, browser_guid_, delegate_->HasBundledFrontendResources())); } +#endif } void DevToolsHttpHandler::ServerStarted( diff --git a/content/browser/dom_storage/dom_storage_area.cc b/content/browser/dom_storage/dom_storage_area.cc index 593fa6d693b33..dd46a3162088e 100644 --- a/content/browser/dom_storage/dom_storage_area.cc +++ b/content/browser/dom_storage/dom_storage_area.cc @@ -41,7 +41,7 @@ namespace { // To avoid excessive IO we apply limits to the amount of data being written // and the frequency of writes. The specific values used are somewhat arbitrary. constexpr int kMaxBytesPerHour = kPerStorageAreaQuota; -constexpr int kMaxCommitsPerHour = 60; +constexpr int kMaxCommitsPerHour = 60 * 3600; } // namespace diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc index 369046443da4d..1f164113a4a9b 100644 --- a/content/browser/dom_storage/local_storage_context_mojo.cc +++ b/content/browser/dom_storage/local_storage_context_mojo.cc @@ -189,7 +189,7 @@ class LocalStorageContextMojo::LevelDBWrapperHolder final // To avoid excessive IO we apply limits to the amount of data being written // and the frequency of writes. static constexpr int kMaxBytesPerHour = kPerStorageAreaQuota; - static constexpr int kMaxCommitsPerHour = 60; + static constexpr int kMaxCommitsPerHour = std::numeric_limits::max(); LevelDBWrapperImpl::Options options; options.max_size = kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance; diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc index 3b2045e18eeea..4ebf99932b725 100644 --- a/content/browser/download/download_request_core.cc +++ b/content/browser/download/download_request_core.cc @@ -305,6 +305,7 @@ bool DownloadRequestCore::OnResponseStarted( if (request()->initiator().has_value() && !create_info->url_chain.back().SchemeIsBlob() && !create_info->url_chain.back().SchemeIs(url::kAboutScheme) && + !request()->initiator()->GetURL().SchemeIs("chrome-extension") && !create_info->url_chain.back().SchemeIs(url::kDataScheme) && request()->initiator()->GetURL() != create_info->url_chain.back().GetOrigin()) { diff --git a/content/browser/frame_host/ancestor_throttle.cc b/content/browser/frame_host/ancestor_throttle.cc index 129c37770203f..86fb53a2e3dcb 100644 --- a/content/browser/frame_host/ancestor_throttle.cc +++ b/content/browser/frame_host/ancestor_throttle.cc @@ -145,6 +145,9 @@ NavigationThrottle::ThrottleCheckResult AncestorThrottle::ProcessResponseImpl( HeaderDisposition disposition = ParseHeader(handle->GetResponseHeaders(), &header_value); + if (handle->frame_tree_node()->frame_owner_properties().nwfaketop) + return NavigationThrottle::PROCEED; + switch (disposition) { case HeaderDisposition::CONFLICT: if (logging == LoggingDisposition::LOG_TO_CONSOLE) diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index ad9de41d1e3e1..f8299a810f6a6 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc @@ -374,6 +374,9 @@ bool InterstitialPageImpl::OnMessageReceived( IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() + if (!handled) { + handled = static_cast(web_contents_)->OnMessageReceived(render_frame_host, message); + } return handled; } diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 74ff6b4286c2a..b14ccaa941d33 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc @@ -304,7 +304,7 @@ base::Time NavigationControllerImpl::TimeSmoother::GetSmoothedTime( NavigationControllerImpl::NavigationControllerImpl( NavigationControllerDelegate* delegate, BrowserContext* browser_context) - : browser_context_(browser_context), + : history_initiator_(nullptr), browser_context_(browser_context), pending_entry_(nullptr), failed_pending_entry_id_(0), last_committed_entry_index_(-1), @@ -2296,18 +2296,27 @@ bool NavigationControllerImpl::NavigateToPendingEntryInternal( std::make_pair(root, pending_entry_->GetFrameEntry(root))); } + FrameTreeNode* nwfaketop_node = nullptr; + if (history_initiator_) { + if (history_initiator_->frame_tree_node()->frame_owner_properties().nwfaketop) + nwfaketop_node = history_initiator_->frame_tree_node(); + } // If all the frame loads fail, we will discard the pending entry. bool success = false; // Send all the same document frame loads before the different document loads. for (const auto& item : same_document_loads) { FrameTreeNode* frame = item.first; + if (nwfaketop_node && nwfaketop_node->IsDescendantOf(frame)) + continue; success |= frame->navigator()->NavigateToPendingEntry( frame, *item.second, reload_type, true, nullptr /* navigation_ui_data */); } for (const auto& item : different_document_loads) { FrameTreeNode* frame = item.first; + if (nwfaketop_node && nwfaketop_node->IsDescendantOf(frame)) + continue; success |= frame->navigator()->NavigateToPendingEntry( frame, *item.second, reload_type, false, // The NavigationUIData has only been initialized for main frames. Do diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index 3f1f1ceff6d5f..3e37b70f81c8b 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h @@ -34,6 +34,7 @@ struct LoadCommittedDetails; class CONTENT_EXPORT NavigationControllerImpl : public NavigationController { public: + void set_history_initiator(RenderFrameHostImpl* frame_host) { history_initiator_ = frame_host; } NavigationControllerImpl( NavigationControllerDelegate* delegate, BrowserContext* browser_context); @@ -233,7 +234,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController { private: friend class RestoreHelper; - + RenderFrameHostImpl* history_initiator_; FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, PurgeScreenshot); FRIEND_TEST_ALL_PREFIXES(TimeSmoother, Basic); diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index ecc9736c95c60..51e372ef93b37 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc @@ -68,6 +68,11 @@ #include "third_party/blink/public/common/frame/sandbox_flags.h" #include "third_party/blink/public/platform/web_mixed_content_context_type.h" +namespace nw { + typedef bool(*RphGuestFilterURLHookFn)(content::RenderProcessHost* rph, const GURL* url); + extern RphGuestFilterURLHookFn gRphGuestFilterURLHook; +} + namespace content { namespace { @@ -462,6 +467,15 @@ NavigationRequest::NavigationRequest( frame_tree_node_->navigator()->GetDelegate()->GetUserAgentOverride(); } + FrameTreeNode* node = frame_tree_node; + while (node) { + const std::string& nwuseragent = node->frame_owner_properties().nwuseragent; + if (!nwuseragent.empty()) { + user_agent_override = nwuseragent; + break; + } + node = node->parent(); + } std::unique_ptr embedder_additional_headers; int additional_load_flags = 0; GetContentClient()->browser()->NavigationRequestStarted( @@ -1309,6 +1323,13 @@ void NavigationRequest::OnStartChecksComplete( navigation_handle_->GetStartingSiteInstance()->GetSiteURL(). SchemeIs(kGuestScheme); + bool nw_trusted = false; + if (is_for_guests_only) { + GURL dummy; + RenderProcessHost* render_process_host = navigating_frame_host->GetProcess(); + if (nw::gRphGuestFilterURLHook && nw::gRphGuestFilterURLHook(render_process_host, &dummy)) + nw_trusted = true; + } // Give DevTools a chance to override begin params (headers, skip SW) // before actually loading resource. bool report_raw_headers = false; @@ -1328,7 +1349,7 @@ void NavigationRequest::OnStartChecksComplete( blink::mojom::PageVisibilityState::kPrerender, blob_url_loader_factory_ ? blob_url_loader_factory_->Clone() : nullptr, - devtools_navigation_token()), + devtools_navigation_token(), nw_trusted), std::move(navigation_ui_data), navigation_handle_->service_worker_handle(), navigation_handle_->appcache_handle(), this); diff --git a/content/browser/frame_host/navigation_request_info.cc b/content/browser/frame_host/navigation_request_info.cc index 51d8563db098b..14ac08f0213f6 100644 --- a/content/browser/frame_host/navigation_request_info.cc +++ b/content/browser/frame_host/navigation_request_info.cc @@ -20,7 +20,7 @@ NavigationRequestInfo::NavigationRequestInfo( bool is_prerendering, std::unique_ptr blob_url_loader_factory, - const base::UnguessableToken& devtools_navigation_token) + const base::UnguessableToken& devtools_navigation_token, bool nw_trusted) : common_params(common_params), begin_params(std::move(begin_params)), site_for_cookies(site_for_cookies), @@ -32,7 +32,7 @@ NavigationRequestInfo::NavigationRequestInfo( report_raw_headers(report_raw_headers), is_prerendering(is_prerendering), blob_url_loader_factory(std::move(blob_url_loader_factory)), - devtools_navigation_token(devtools_navigation_token) {} + devtools_navigation_token(devtools_navigation_token), nw_trusted(nw_trusted) {} NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other) : common_params(other.common_params), @@ -45,7 +45,7 @@ NavigationRequestInfo::NavigationRequestInfo(const NavigationRequestInfo& other) is_for_guests_only(other.is_for_guests_only), report_raw_headers(other.report_raw_headers), is_prerendering(other.is_prerendering), - devtools_navigation_token(other.devtools_navigation_token) {} + devtools_navigation_token(other.devtools_navigation_token), nw_trusted(other.nw_trusted) {} NavigationRequestInfo::~NavigationRequestInfo() {} diff --git a/content/browser/frame_host/navigation_request_info.h b/content/browser/frame_host/navigation_request_info.h index 304502f0a25d5..bf71e9f1997ca 100644 --- a/content/browser/frame_host/navigation_request_info.h +++ b/content/browser/frame_host/navigation_request_info.h @@ -36,7 +36,7 @@ struct CONTENT_EXPORT NavigationRequestInfo { bool is_prerendering, std::unique_ptr blob_url_loader_factory, - const base::UnguessableToken& devtools_navigation_token); + const base::UnguessableToken& devtools_navigation_token, bool nw_trust = false); NavigationRequestInfo(const NavigationRequestInfo& other); ~NavigationRequestInfo(); @@ -66,6 +66,7 @@ struct CONTENT_EXPORT NavigationRequestInfo { std::unique_ptr blob_url_loader_factory; const base::UnguessableToken devtools_navigation_token; + bool nw_trusted; }; } // namespace content diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index e098e1bc69eda..18d5c80f03aad 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc @@ -48,6 +48,11 @@ #include "url/gurl.h" #include "url/url_util.h" +namespace nw { + typedef bool(*RphGuestFilterURLHookFn)(content::RenderProcessHost* rph, const GURL* url); + extern RphGuestFilterURLHookFn gRphGuestFilterURLHook; +} + namespace content { namespace { @@ -184,9 +189,9 @@ void NavigatorImpl::DidStartProvisionalLoad( ChildProcessSecurityPolicyImpl::GetInstance(); if (render_process_host->IsForGuestsOnly() && !policy->IsWebSafeScheme(validated_url.scheme())) { + if (!(nw::gRphGuestFilterURLHook && nw::gRphGuestFilterURLHook(render_process_host, &validated_url))) //NWJS#5682 validated_url = GURL(url::kAboutBlankURL); } - if (is_main_frame && !is_error_page) { DidStartMainFrameNavigation(validated_url, render_frame_host->GetSiteInstance(), diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index daff8c65a981c..a348cf62a287b 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc @@ -495,6 +495,14 @@ void RenderFrameHostImpl::SetNetworkFactoryForTesting( create_network_factory_callback; } +void RenderFrameHostImpl::SetNodeJS(bool node) { + nodejs_ = node; +} + +void RenderFrameHostImpl::SetContextCreated(bool created) { + context_created_ = created; +} + RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, RenderViewHostImpl* render_view_host, RenderFrameHostDelegate* delegate, @@ -505,7 +513,9 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, int32_t widget_routing_id, bool hidden, bool renderer_initiated_creation) - : render_view_host_(render_view_host), + : + in_window_creation_(false), + render_view_host_(render_view_host), delegate_(delegate), site_instance_(static_cast(site_instance)), process_(site_instance->GetProcess()), @@ -516,6 +526,8 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, routing_id_(routing_id), is_waiting_for_swapout_ack_(false), render_frame_created_(false), + nodejs_(false), + context_created_(false), is_waiting_for_beforeunload_ack_(false), unload_ack_is_for_navigation_(false), was_discarded_(false), @@ -713,6 +725,14 @@ ui::AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::GetAXTreeID() { return ax_tree_id_; } +bool RenderFrameHostImpl::nodejs() { + return nodejs_; +} + +bool RenderFrameHostImpl::context_created() { + return context_created_; +} + const base::UnguessableToken& RenderFrameHostImpl::GetOverlayRoutingToken() { if (!overlay_routing_token_) { overlay_routing_token_ = base::UnguessableToken::Create(); diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 39f9624f1733e..6d1b6ffb3df22 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h @@ -162,6 +162,7 @@ class CONTENT_EXPORT RenderFrameHostImpl using AXTreeSnapshotCallback = base::OnceCallback; + bool in_window_creation_; // An accessibility reset is only allowed to prevent very rare corner cases // or race conditions where the browser and renderer get out of sync. If // this happens more than this many times, kill the renderer. @@ -189,6 +190,8 @@ class CONTENT_EXPORT RenderFrameHostImpl // RenderFrameHost int GetRoutingID() override; ui::AXTreeIDRegistry::AXTreeID GetAXTreeID() override; + bool nodejs() override; + bool context_created() override; SiteInstanceImpl* GetSiteInstance() override; RenderProcessHost* GetProcess() override; RenderWidgetHostView* GetView() override; @@ -950,6 +953,9 @@ class CONTENT_EXPORT RenderFrameHostImpl void UpdateEncoding(const std::string& encoding) override; void FrameSizeChanged(const gfx::Size& frame_size) override; + void SetNodeJS(bool node) override; + void SetContextCreated(bool created) override; + // Registers Mojo interfaces that this frame host makes available. void RegisterMojoInterfaces(); @@ -1284,6 +1290,8 @@ class CONTENT_EXPORT RenderFrameHostImpl // TODO(creis): Use this for main frames as well when RVH goes away. bool render_frame_created_; + bool nodejs_; + bool context_created_; // When the last BeforeUnload message was sent. base::TimeTicks send_before_unload_start_time_; diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index b682235b0f872..a22e8a08bdee7 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc @@ -4,6 +4,7 @@ #include "content/browser/frame_host/render_frame_host_manager.h" +#include "content/public/common/browser_side_navigation_policy.h" #include #include @@ -56,6 +57,11 @@ #include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h" #endif // defined(OS_MACOSX) +namespace nw { +typedef bool(*GuestSwapProcessHookFn)(content::BrowserContext*, const GURL& url); +CONTENT_EXPORT GuestSwapProcessHookFn gGuestSwapProcessHook = nullptr; +} + namespace content { RenderFrameHostManager::RenderFrameHostManager( @@ -979,9 +985,11 @@ RenderFrameHostManager::GetSiteInstanceForNavigation( DCHECK(!source_instance || !dest_instance); SiteInstance* current_instance = render_frame_host_->GetSiteInstance(); + BrowserContext* browser_context = + delegate_->GetControllerForRenderManager().GetBrowserContext(); // We do not currently swap processes for navigations in webview tag guests. - if (current_instance->GetSiteURL().SchemeIs(kGuestScheme)) + if (current_instance->GetSiteURL().SchemeIs(kGuestScheme) && !(nw::gGuestSwapProcessHook && nw::gGuestSwapProcessHook(browser_context, dest_url))) return current_instance; // Determine if we need a new BrowsingInstance for this entry. If true, this @@ -998,8 +1006,6 @@ RenderFrameHostManager::GetSiteInstanceForNavigation( // whether to use a new SiteInstance. This happens when navigating a subframe, // or when a new RenderFrameHost has been swapped in at the beginning of a // navigation to replace a crashed RenderFrameHost. - BrowserContext* browser_context = - delegate_->GetControllerForRenderManager().GetBrowserContext(); const GURL& current_effective_url = !render_frame_host_->last_successful_url().is_empty() ? SiteInstanceImpl::GetEffectiveURL( @@ -1415,11 +1421,11 @@ bool RenderFrameHostManager::IsRendererTransferNeededForNavigation( if (!rfh->GetSiteInstance()->HasSite()) return rfh->GetSiteInstance()->HasWrongProcessForURL(dest_url); + BrowserContext* context = rfh->GetSiteInstance()->GetBrowserContext(); // We do not currently swap processes for navigations in webview tag guests. - if (rfh->GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme)) + if (rfh->GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme) && !(nw::gGuestSwapProcessHook && nw::gGuestSwapProcessHook(context, dest_url))) return false; - BrowserContext* context = rfh->GetSiteInstance()->GetBrowserContext(); // TODO(nasko, nick): These following --site-per-process checks are // overly simplistic. Update them to match all the cases // considered by DetermineSiteInstanceForURL. @@ -1939,7 +1945,7 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest( request.dest_site_instance(), was_server_redirect); } - if (no_renderer_swap_allowed) + if (no_renderer_swap_allowed || (was_server_redirect && render_frame_host_->in_window_creation_)) return scoped_refptr(current_site_instance); // If the navigation can swap SiteInstances, compute the SiteInstance it diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 72708d0f0c741..6dc0a6d1b016d 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -636,6 +636,7 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind) in_process_(false), kind_(kind), process_launched_(false), + closing_(false), status_(UNKNOWN), gpu_host_binding_(this), weak_ptr_factory_(this) { @@ -661,6 +662,7 @@ GpuProcessHost::~GpuProcessHost() { if (in_process_gpu_thread_) DCHECK(process_); + closing_ = true; SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID); if (status_ == UNKNOWN) { @@ -906,7 +908,8 @@ void GpuProcessHost::EstablishGpuChannel( const EstablishChannelCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel"); - + if (in_process_ && closing_) + return; // If GPU features are already blacklisted, no need to establish the channel. if (!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr)) { DVLOG(1) << "GPU blacklisted, refusing to open a GPU channel."; diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index e08bcf72fc16d..579e089c99d06 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -281,6 +281,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, // Whether we actually launched a GPU process. bool process_launched_; + bool closing_; GpuInitializationStatus status_; diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 1c1fb59e02c81..e5cc2c4d0ddf5 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -1597,7 +1597,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest( !policy->IsWebSafeScheme(info.common_params.url.scheme()) && !is_external_protocol; - if (is_shutdown_ || non_web_url_in_guest) { + if (is_shutdown_ || (non_web_url_in_guest && !info.nw_trusted)) { url_loader_client->OnComplete( network::URLLoaderCompletionStatus(net::ERR_ABORTED)); return; diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 5ccfa4398c718..8c57cc72f5343 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -269,6 +269,14 @@ #include "content/browser/net/reporting_service_proxy.h" #endif // BUILDFLAG(ENABLE_REPORTING) +#include "content/nw/src/common/shell_switches.h" +#include "content/nw/src/nw_content.h" + +namespace nw { +typedef bool (*RphGuestFilterURLHookFn)(content::RenderProcessHost* rph, const GURL* url); +CONTENT_EXPORT RphGuestFilterURLHookFn gRphGuestFilterURLHook = nullptr; +} + namespace content { using CheckOriginLockResult = @@ -277,6 +285,8 @@ using CheckOriginLockResult = namespace { const RenderProcessHostFactory* g_render_process_host_factory_ = nullptr; +RenderProcessHostImpl* g_main_host = nullptr; + const char kSiteProcessMapKeyName[] = "content_site_process_map"; RenderProcessHost::AnalyzeHungRendererFunction g_analyze_hung_renderer = @@ -1602,6 +1612,8 @@ bool RenderProcessHostImpl::Init() { RegisterMojoInterfaces(); if (run_renderer_in_process()) { + base::ThreadRestrictions::ScopedAllowIO allow_io; + nw::LoadNodeSymbols(); DCHECK(g_renderer_main_thread_factory); // Crank up a thread and run the initialization there. With the way that // messages flow between the browser and renderer, this thread is required @@ -1624,6 +1636,8 @@ bool RenderProcessHostImpl::Init() { // in-process plugins. options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; #endif + options.message_loop_type = base::MessageLoop::TYPE_NODE; + // As for execution sequence, this callback should have no any dependency // on starting in-process-render-thread. // So put it here to trigger ChannelMojo initialization earlier to enable @@ -2647,6 +2661,14 @@ void RenderProcessHostImpl::AppendRendererCommandLine( command_line->AppendSwitch(switches::kNoZygote); } + bool allow_nw = false; + if (IsForGuestsOnly()) { + if (nw::GetInWebViewApplyAttr(&allow_nw) && allow_nw) + command_line->AppendSwitch("nwjs-guest-nw"); + else + command_line->AppendSwitch("nwjs-guest"); + } + GetContentClient()->browser()->AppendExtraCommandLineSwitches(command_line, GetID()); @@ -2679,6 +2701,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( // Allow this to be set when invoking the browser and relayed along. service_manager::switches::kEnableSandboxLogging, #endif + switches::kDisableRAFThrottling, + switches::kEnableNodeWorker, + switches::kEnableSpellChecking, switches::kAgcStartupMinVolume, switches::kAecRefinedAdaptiveFilter, switches::kAllowLoopbackInPeerConnection, @@ -3372,6 +3397,16 @@ void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { g_all_hosts.Get().AddWithID(host, host_id); } +void RenderProcessHostImpl::set_main_host() { + g_main_host = this; +} + +RenderProcessHostImpl* RenderProcessHostImpl::main_host() { + return g_main_host; +} + +extern bool g_browser_main_loop_shutting_down; + // static void RenderProcessHostImpl::UnregisterHost(int host_id) { RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); @@ -3380,6 +3415,12 @@ void RenderProcessHostImpl::UnregisterHost(int host_id) { g_all_hosts.Get().Remove(host_id); + if (g_main_host == host) + g_main_host = nullptr; + + if (run_renderer_in_process() && g_browser_main_loop_shutting_down) + return; //or the following line will crash because browser context + //has been destroyed // Look up the map of site to process for the given browser_context, // in case we need to remove this process from it. It will be registered // under any sites it rendered that use process-per-site mode. @@ -3411,6 +3452,8 @@ void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph, // If this renderer is not permitted to request this URL, we invalidate the // URL. This prevents us from storing the blocked URL and becoming confused // later. + if (nw::gRphGuestFilterURLHook && nw::gRphGuestFilterURLHook(rph, url)) + return; VLOG(1) << "Blocked URL " << url->spec(); *url = GURL(url::kAboutBlankURL); } @@ -3577,6 +3620,8 @@ RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost( g_spare_render_process_host_manager.Get() .spare_render_process_host()); + if (iter.GetCurrentValue() == g_main_host) + return g_main_host; suitable_renderers.push_back(iter.GetCurrentValue()); } iter.Advance(); @@ -3584,9 +3629,12 @@ RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost( // Now pick a random suitable renderer, if we have any. if (!suitable_renderers.empty()) { - int suitable_count = static_cast(suitable_renderers.size()); - int random_index = base::RandInt(0, suitable_count - 1); - return suitable_renderers[random_index]; + //int suitable_count = static_cast(suitable_renderers.size()); + //int random_index = base::RandInt(0, suitable_count - 1); + //return suitable_renderers[random_index]; + //NWJS: reuse first renderer, the main process for valid nw.Window.open + //callback value. see also app_window_api.cc:416 + return suitable_renderers[0]; } return nullptr; @@ -3661,7 +3709,10 @@ void RenderProcessHostImpl::RegisterProcessHostForSite( // appropriate bindings here, because the bindings have not yet been granted. std::string site = SiteInstance::GetSiteForURL(browser_context, url).possibly_invalid_spec(); - if (!site.empty()) + // don't register process when we're opening new_instance window, or + // the map slot will be took over and following same-instance window + // opening will return null; NWJS#4691 + if (!site.empty() && nw::PinningRenderer()) map->RegisterProcess(site, process); } diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index b418b4c8a0ad3..3537945039555 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h @@ -138,6 +138,8 @@ class CONTENT_EXPORT RenderProcessHostImpl ~RenderProcessHostImpl() override; + void set_main_host(); + static RenderProcessHostImpl* main_host(); // RenderProcessHost implementation (public portion). bool Init() override; void EnableSendQueue() override; diff --git a/content/browser/renderer_host/render_view_host_delegate.cc b/content/browser/renderer_host/render_view_host_delegate.cc index 6ceb1543e018b..e0dbc54a47fd2 100644 --- a/content/browser/renderer_host/render_view_host_delegate.cc +++ b/content/browser/renderer_host/render_view_host_delegate.cc @@ -9,6 +9,10 @@ namespace content { +RenderViewHostDelegate::RenderViewHostDelegate() + :skip_blocking_parser_(true) { +} + RenderViewHostDelegateView* RenderViewHostDelegate::GetDelegateView() { return nullptr; } @@ -69,4 +73,11 @@ RenderFrameHost* RenderViewHostDelegate::GetPendingMainFrame() { return nullptr; } +bool RenderViewHostDelegate::GetSkipBlockingParser() { + return skip_blocking_parser_; +} + +void RenderViewHostDelegate::SetSkipBlockingParser(bool value) { + skip_blocking_parser_ = value; +} } // namespace content diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index cec0257475741..8674564c2d019 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -55,6 +55,7 @@ struct RendererPreferences; // listener here to serve that need. class CONTENT_EXPORT RenderViewHostDelegate { public: + RenderViewHostDelegate(); // Returns the current delegate associated with a feature. May return NULL if // there is no corresponding delegate. virtual RenderViewHostDelegateView* GetDelegateView(); @@ -150,6 +151,8 @@ class CONTENT_EXPORT RenderViewHostDelegate { // create the SessionStorageNamespace on the fly. virtual SessionStorageNamespace* GetSessionStorageNamespace( SiteInstance* instance); + virtual bool GetSkipBlockingParser(); + virtual void SetSkipBlockingParser(bool); // Returns a copy of the map of all session storage namespaces related // to this view. @@ -192,6 +195,8 @@ class CONTENT_EXPORT RenderViewHostDelegate { protected: virtual ~RenderViewHostDelegate() {} + private: + bool skip_blocking_parser_; }; } // namespace content diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index e8aa2e41e8add..8730585eafad1 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc @@ -322,6 +322,7 @@ bool RenderViewHostImpl::CreateRenderView( } params->session_storage_namespace_id = delegate_->GetSessionStorageNamespace(instance_.get())->id(); + params->skip_blocking_parser = delegate_->GetSkipBlockingParser(); // Ensure the RenderView sets its opener correctly. params->opener_frame_route_id = opener_frame_route_id; params->swapped_out = !is_active_; diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge.h b/content/browser/renderer_host/render_widget_host_ns_view_bridge.h index 3761be5f730dd..94b3b833f1426 100644 --- a/content/browser/renderer_host/render_widget_host_ns_view_bridge.h +++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge.h @@ -29,6 +29,8 @@ namespace ui { enum class DomCode; } // namespace ui +@class CALayer; + namespace content { class RenderWidgetHostNSViewClient; @@ -80,6 +82,9 @@ class RenderWidgetHostNSViewBridge { // Forward changes in ui::TextInputType. virtual void SetTextInputType(ui::TextInputType text_input_type) = 0; + // Used by g_force_cpu_draw + virtual CALayer* GetBackgroundLayer() = 0; + // Forward the TextInputManager::TextSelection from the renderer. virtual void SetTextSelection(const base::string16& text, size_t offset, diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm b/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm index 54b1c71bb4c6d..c82672efabc86 100644 --- a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm +++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm @@ -22,6 +22,9 @@ namespace content { +extern bool g_support_transparency; +extern bool g_force_cpu_draw; + namespace { // Bridge to a locally-hosted NSView -- this is always instantiated in the same @@ -61,6 +64,8 @@ void ShowDictionaryOverlay( void LockKeyboard(base::Optional> codes) override; void UnlockKeyboard() override; + CALayer* GetBackgroundLayer() override; + private: bool IsPopup() const { // TODO(ccameron): If this is not equivalent to |popup_window_| then @@ -101,10 +106,18 @@ void OnDisplayMetricsChanged(const display::Display& display, cocoa_view_.reset([[RenderWidgetHostViewCocoa alloc] initWithClient:client]); background_layer_.reset([[CALayer alloc] init]); + display_ca_layer_tree_ = std::make_unique(background_layer_.get()); + + bool isOpaque = [cocoa_view_ isOpaque]; + if (content::g_support_transparency) { + [background_layer_ setBackgroundColor: (isOpaque || !content::g_support_transparency) ? + CGColorGetConstantColor(kCGColorWhite) : CGColorGetConstantColor(kCGColorClear)]; + } + [cocoa_view_ setLayer:background_layer_]; - [cocoa_view_ setWantsLayer:YES]; + [cocoa_view_ setWantsLayer:!g_force_cpu_draw]; } RenderWidgetHostViewNSViewBridgeLocal:: @@ -193,6 +206,10 @@ void OnDisplayMetricsChanged(const display::Display& display, if (display_disabled_) return; display_ca_layer_tree_->UpdateCALayerTree(ca_layer_params); + if (content::g_force_cpu_draw) { + // this is to tell parent window, that the window content has been updated + [[cocoa_view_ superview] setNeedsDisplay:YES]; + } } void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) { @@ -275,6 +292,11 @@ void OnDisplayMetricsChanged(const display::Display& display, [cocoa_view_ updateScreenProperties]; } +CALayer* RenderWidgetHostViewNSViewBridgeLocal::GetBackgroundLayer() { + assert(content::g_force_cpu_draw); + return background_layer_; +} + void RenderWidgetHostViewNSViewBridgeLocal::DisplayCursor( const WebCursor& cursor) { WebCursor non_const_cursor = cursor; diff --git a/content/browser/renderer_host/render_widget_host_ns_view_client.h b/content/browser/renderer_host/render_widget_host_ns_view_client.h index bc2365191c657..69164dfc5aa2b 100644 --- a/content/browser/renderer_host/render_widget_host_ns_view_client.h +++ b/content/browser/renderer_host/render_widget_host_ns_view_client.h @@ -44,6 +44,8 @@ class RenderWidgetHostNSViewClient { RenderWidgetHostNSViewClient() {} virtual ~RenderWidgetHostNSViewClient() {} + virtual RenderWidgetHostViewMac* GetRenderWidgetHostViewMac() = 0; + // Return the RenderWidget's BrowserAccessibilityManager. // TODO(ccameron): This returns nullptr for non-local NSViews. A scheme for // non-local accessibility needs to be developed. diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/content/browser/renderer_host/render_widget_host_view_cocoa.mm index d86576cc36ac0..118e138071779 100644 --- a/content/browser/renderer_host/render_widget_host_view_cocoa.mm +++ b/content/browser/renderer_host/render_widget_host_view_cocoa.mm @@ -43,6 +43,10 @@ using blink::WebMouseWheelEvent; using blink::WebGestureEvent; +namespace content { + extern bool g_force_cpu_draw; +} + namespace { // No-op client used to avoid scattering of nullptr checks (see comments in @@ -53,6 +57,9 @@ ~NoopClient() override{}; // RenderWidgetHostNSViewClient implementation: + content::RenderWidgetHostViewMac* GetRenderWidgetHostViewMac() override { + return nullptr; + } BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override { return nullptr; } @@ -351,6 +358,19 @@ - (id)forwardingTargetForSelector:(SEL)selector { return [super forwardingTargetForSelector:selector]; } +- (void)drawRect:(NSRect)dirty { + if (content::g_force_cpu_draw) { + CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextClipToRect(ctx, NSRectToCGRect(dirty)); + //High Sierra 10.13 fix, previously we use [self layer], + //since we have set the layer to nil in AcceleratedWidgetMac::GotSoftwareFrame, + //we access the layer "directly" which is the "background_layer()" (see RenderWidgetHostViewMac constructor) + [client_->GetRenderWidgetHostViewMac()->background_layer() renderInContext:ctx]; + } else { + [super drawRect:dirty]; + } +} + - (void)setCanBeKeyView:(BOOL)can { canBeKeyView_ = can; } @@ -1187,8 +1207,17 @@ - (void)setFrameOrigin:(NSPoint)newOrigin { } - (void)setFrameSize:(NSSize)newSize { + //High Sierra 10.13 fix, RenderWidgetHostViewCocoa CALayer must be nil + //so we can do drawRect "manually" + //here, we temporarily assign back the layer during resize, so the background_layer() can be resized properly + if (content::g_force_cpu_draw) + [self setLayer:client_->GetRenderWidgetHostViewMac()->background_layer()]; + [super setFrameSize:newSize]; [self sendViewBoundsInWindowToClient]; + + if (content::g_force_cpu_draw) + [self setLayer:nil]; } - (BOOL)canBecomeKeyView { diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 656807e405af3..c534461cb4ac8 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -84,6 +84,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac RenderWidgetHostViewCocoa* cocoa_view() const; + // Used by g_force_cpu_draw + CALayer* background_layer() const; + // |delegate| is used to separate out the logic from the NSResponder delegate. // |delegate| is retained by this class. // |delegate| should be set at most once. @@ -295,6 +298,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac void PauseForPendingResizeOrRepaintsAndDraw(); // RenderWidgetHostNSViewClient implementation. + RenderWidgetHostViewMac* GetRenderWidgetHostViewMac() override; BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override; void OnNSViewSyncIsRenderViewHost(bool* is_render_view) override; void OnNSViewRequestShutdown() override; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index c8bfdb794cd39..4ed2cb26f3592 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "content/browser/renderer_host/render_widget_host_view_mac.h" +#include "content/public/common/content_switches.h" #import @@ -59,6 +60,10 @@ using blink::WebGestureEvent; using blink::WebTouchEvent; +namespace content { + extern bool g_force_cpu_draw; +} + namespace content { //////////////////////////////////////////////////////////////////////////////// @@ -217,6 +222,13 @@ new BrowserCompositorMac(this, this, host()->is_hidden(), return ns_view_bridge_->GetRenderWidgetHostViewCocoa(); } +CALayer* RenderWidgetHostViewMac::background_layer() const { + assert(content::g_force_cpu_draw); + if (ns_view_bridge_) + return ns_view_bridge_->GetBackgroundLayer(); + return nil; +} + void RenderWidgetHostViewMac::SetDelegate( NSObject* delegate) { [cocoa_view() setResponderDelegate:delegate]; @@ -373,6 +385,7 @@ new BrowserCompositorMac(this, this, host()->is_hidden(), is_visible_ = false; ns_view_bridge_->SetVisible(is_visible_); host()->WasHidden(); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableRAFThrottling)) browser_compositor_->SetRenderWidgetHostIsHidden(true); } @@ -383,6 +396,7 @@ new BrowserCompositorMac(this, this, host()->is_hidden(), void RenderWidgetHostViewMac::WasOccluded() { host()->WasHidden(); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableRAFThrottling)) browser_compositor_->SetRenderWidgetHostIsHidden(true); } @@ -1313,6 +1327,10 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback, /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostNSViewClient implementation: +RenderWidgetHostViewMac* RenderWidgetHostViewMac::GetRenderWidgetHostViewMac() { + return this; +} + BrowserAccessibilityManager* RenderWidgetHostViewMac::GetRootBrowserAccessibilityManager() { return host()->GetRootBrowserAccessibilityManager(); diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc index 107d46564b9ca..28f40289f4234 100644 --- a/content/browser/shared_worker/shared_worker_host.cc +++ b/content/browser/shared_worker/shared_worker_host.cc @@ -125,7 +125,7 @@ void SharedWorkerHost::Start( DCHECK_CURRENTLY_ON(BrowserThread::UI); AdvanceTo(Phase::kStarted); - mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New( + mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New(instance_->nodejs(), instance_->root_path(), instance_->url(), instance_->name(), instance_->content_security_policy(), instance_->content_security_policy_type(), instance_->creation_address_space())); diff --git a/content/browser/shared_worker/shared_worker_instance.cc b/content/browser/shared_worker/shared_worker_instance.cc index 67e1d88f76a58..369281fdcc0f7 100644 --- a/content/browser/shared_worker/shared_worker_instance.cc +++ b/content/browser/shared_worker/shared_worker_instance.cc @@ -8,7 +8,7 @@ namespace content { -SharedWorkerInstance::SharedWorkerInstance( +SharedWorkerInstance::SharedWorkerInstance(bool is_node_js, const base::FilePath& root_path, const GURL& url, const std::string& name, const url::Origin& constructor_origin, @@ -16,7 +16,8 @@ SharedWorkerInstance::SharedWorkerInstance( blink::WebContentSecurityPolicyType security_policy_type, blink::mojom::IPAddressSpace creation_address_space, blink::mojom::SharedWorkerCreationContextType creation_context_type) - : url_(url), + : is_node_js_(is_node_js), root_path_(root_path), + url_(url), name_(name), constructor_origin_(constructor_origin), content_security_policy_(content_security_policy), diff --git a/content/browser/shared_worker/shared_worker_instance.h b/content/browser/shared_worker/shared_worker_instance.h index eb909daa38d62..da9dda2ebea5b 100644 --- a/content/browser/shared_worker/shared_worker_instance.h +++ b/content/browser/shared_worker/shared_worker_instance.h @@ -7,6 +7,8 @@ #include +#include "base/files/file_path.h" + #include "content/common/content_export.h" #include "third_party/blink/public/mojom/net/ip_address_space.mojom.h" #include "third_party/blink/public/mojom/shared_worker/shared_worker_creation_context_type.mojom.h" @@ -20,7 +22,7 @@ namespace content { // the UI thread and be used for comparison in SharedWorkerDevToolsManager. class CONTENT_EXPORT SharedWorkerInstance { public: - SharedWorkerInstance( + SharedWorkerInstance(bool is_node_js, const base::FilePath& root_path, const GURL& url, const std::string& name, const url::Origin& constructor_origin, @@ -41,6 +43,8 @@ class CONTENT_EXPORT SharedWorkerInstance { bool Matches(const SharedWorkerInstance& other) const; // Accessors. + bool nodejs() const { return is_node_js_; } + const base::FilePath& root_path() const { return root_path_; } const GURL& url() const { return url_; } const std::string name() const { return name_; } const url::Origin& constructor_origin() const { return constructor_origin_; } @@ -58,6 +62,8 @@ class CONTENT_EXPORT SharedWorkerInstance { } private: + bool is_node_js_; + const base::FilePath root_path_; const GURL url_; const std::string name_; diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc index 8140ae678d37c..90dccd0535f29 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.cc +++ b/content/browser/shared_worker/shared_worker_service_impl.cc @@ -159,7 +159,7 @@ void SharedWorkerServiceImpl::ConnectToWorker( return; } - auto instance = std::make_unique( + auto instance = std::make_unique(info->is_node_js, info->root_path, info->url, info->name, render_frame_host->GetLastCommittedOrigin(), info->content_security_policy, info->content_security_policy_type, info->creation_address_space, creation_context_type); diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index b34db8034e1f0..758b528cc7e85 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc @@ -9,6 +9,8 @@ #include "base/command_line.h" #include "base/debug/crash_logging.h" #include "base/macros.h" +#include "content/nw/src/nw_content.h" +#include "extensions/common/constants.h" #include "content/browser/browsing_instance.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/frame_host/debug_urls.h" @@ -122,7 +124,7 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() { bool should_use_process_per_site = has_site_ && RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_); - if (should_use_process_per_site) { + if (should_use_process_per_site && nw::PinningRenderer()) { process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE; } else if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE) { process_reuse_policy_ = ProcessReusePolicy::DEFAULT; @@ -434,6 +436,10 @@ GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context, std::string domain = net::registry_controlled_domains::GetDomainAndRegistry( origin.host(), net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + //NWJS: chrome-extension://test.foo.com was changed to foo.com + //without this + if (real_url.SchemeIs("chrome-extension")) + domain = origin.host(); std::string site = origin.scheme(); site += url::kStandardSchemeSeparator; site += domain.empty() ? origin.host() : domain; diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 6ae9bf2f9c6ae..3c0f27837f543 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -10,6 +10,8 @@ #include #include +#include "content/nw/src/nw_base.h" + #include "base/command_line.h" #include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" @@ -2508,10 +2510,11 @@ void WebContentsImpl::CreateNewWindow( AddDestructionObserver(raw_new_contents); } + nw::SetCurrentNewWinManifest(params.nw_window_manifest); if (delegate_) { delegate_->WebContentsCreated(this, render_process_id, opener->GetRoutingID(), params.frame_name, - params.target_url, raw_new_contents); + params.target_url, raw_new_contents, params.nw_window_manifest); } if (opener) { @@ -4288,10 +4291,16 @@ void WebContentsImpl::OnDidFinishLoad(RenderFrameHostImpl* source, } void WebContentsImpl::OnGoToEntryAtOffset(RenderViewHostImpl* source, - int offset) { + int offset, int frame_routing_id) { // All frames are allowed to navigate the global history. - if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) + if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) { + RenderFrameHostImpl* frame_host = nullptr; + if (frame_routing_id > -1) + frame_host = RenderFrameHostImpl::FromID(source->GetProcess()->GetID(), frame_routing_id); + controller_.set_history_initiator(frame_host); controller_.GoToOffset(offset); + controller_.set_history_initiator(nullptr); + } } void WebContentsImpl::OnUpdateZoomLimits(RenderViewHostImpl* source, diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index cd1c992c7738e..19b9777eebfad 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -1137,7 +1137,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void OnDidRunContentWithCertificateErrors(RenderFrameHostImpl* source); void OnDocumentLoadedInFrame(RenderFrameHostImpl* source); void OnDidFinishLoad(RenderFrameHostImpl* source, const GURL& url); - void OnGoToEntryAtOffset(RenderViewHostImpl* source, int offset); + void OnGoToEntryAtOffset(RenderViewHostImpl* source, int offset, int); void OnUpdateZoomLimits(RenderViewHostImpl* source, int minimum_percent, int maximum_percent); diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc index 96d9134051092..b1d629f9cbe79 100644 --- a/content/browser/webui/url_data_manager_backend.cc +++ b/content/browser/webui/url_data_manager_backend.cc @@ -7,6 +7,8 @@ #include #include +#include "content/nw/src/nw_content.h" + #include "base/bind.h" #include "base/command_line.h" #include "base/compiler_specific.h" @@ -51,6 +53,11 @@ #include "ui/base/webui/i18n_source_stream.h" #include "url/url_util.h" +namespace nw { +typedef bool (*CheckStoragePartitionMatchesFn)(int render_process_id, const GURL& url); +CONTENT_EXPORT CheckStoragePartitionMatchesFn gCheckStoragePartitionMatches = nullptr; +} + namespace content { namespace { diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index d6898e941c81b..f9e705b6b4f5b 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc @@ -539,7 +539,7 @@ void ChildThreadImpl::Init(const Options& options) { source_ptr->Init(GetConnector()); } -#if defined(OS_POSIX) +#if 0 // for supporting 'exit' event of process // Check that --process-type is specified so we don't do this in unit tests // and single-process mode. if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc index 27c25d3d25e18..2cd5cd75a3e24 100644 --- a/content/common/content_switches_internal.cc +++ b/content/common/content_switches_internal.cc @@ -115,7 +115,7 @@ void WaitForDebugger(const std::string& label) { #if defined(GOOGLE_CHROME_BUILD) std::string title = "Google Chrome"; #else // CHROMIUM_BUILD - std::string title = "Chromium"; + std::string title = "NW.js"; #endif // CHROMIUM_BUILD title += " "; title += label; // makes attaching to process easier diff --git a/content/common/dom_storage/dom_storage_map.cc b/content/common/dom_storage/dom_storage_map.cc index 0a6b0176a9827..a1fe9ca7642ad 100644 --- a/content/common/dom_storage/dom_storage_map.cc +++ b/content/common/dom_storage/dom_storage_map.cc @@ -31,6 +31,7 @@ size_t size_in_storage(const base::string16& key, } // namespace +size_t DOMStorageMap::quota_override_ = 0; DOMStorageMap::DOMStorageMap(size_t quota) : DOMStorageMap(quota, false) {} DOMStorageMap::DOMStorageMap(size_t quota, bool has_only_keys) @@ -39,6 +40,8 @@ DOMStorageMap::DOMStorageMap(size_t quota, bool has_only_keys) quota_(quota), has_only_keys_(has_only_keys) { ResetKeyIterator(); + if (quota_override_) + quota_ = quota_override_; } DOMStorageMap::~DOMStorageMap() {} diff --git a/content/common/dom_storage/dom_storage_map.h b/content/common/dom_storage/dom_storage_map.h index 7c154bc155153..1df98c37fc8a7 100644 --- a/content/common/dom_storage/dom_storage_map.h +++ b/content/common/dom_storage/dom_storage_map.h @@ -26,6 +26,7 @@ class CONTENT_EXPORT DOMStorageMap public: DOMStorageMap(size_t quota, bool only_keys); explicit DOMStorageMap(size_t quota); + static void SetQuotaOverride(size_t quota) {quota_override_ = quota; } unsigned Length() const; base::NullableString16 Key(unsigned index); @@ -62,8 +63,8 @@ class CONTENT_EXPORT DOMStorageMap size_t storage_used() const { return storage_used_; } size_t memory_used() const { return memory_used_; } size_t quota() const { return quota_; } - void set_quota(size_t quota) { quota_ = quota; } bool has_only_keys() const { return has_only_keys_; } + void set_quota(size_t quota) { quota_ = quota > quota_override_ ? quota : quota_override_; } static size_t CountBytes(const DOMStorageValuesMap& values); @@ -99,6 +100,7 @@ class CONTENT_EXPORT DOMStorageMap size_t memory_used_; size_t quota_; const bool has_only_keys_; + static size_t quota_override_; }; } // namespace content diff --git a/content/common/dom_storage/dom_storage_types.h b/content/common/dom_storage/dom_storage_types.h index e87afe5b8ee07..d7d1c66dcd5d7 100644 --- a/content/common/dom_storage/dom_storage_types.h +++ b/content/common/dom_storage/dom_storage_types.h @@ -21,13 +21,13 @@ typedef std::map DOMStorageValuesMap; // The quota for each storage area. // This value is enforced in renderer processes and the browser process. -const size_t kPerStorageAreaQuota = 10 * 1024 * 1024; +const size_t kPerStorageAreaQuota = std::numeric_limits::max(); // In the browser process we allow some overage to // accomodate concurrent writes from different renderers // that were allowed because the limit imposed in the renderer // wasn't exceeded. -const size_t kPerStorageAreaOverQuotaAllowance = 100 * 1024; +const size_t kPerStorageAreaOverQuotaAllowance = 0; } // namespace content diff --git a/content/common/frame.mojom b/content/common/frame.mojom index 09b5766c0794c..22d4f3aa28733 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom @@ -33,6 +33,7 @@ const string kNavigation_FrameSpec = "navigation:frame"; interface Frame { GetInterfaceProvider(service_manager.mojom.InterfaceProvider& interfaces); GetCanonicalUrlForSharing() => (url.mojom.Url? canonical_url); + SetSkipBlockingParser(bool skip); // Samsung Galaxy Note-specific "smart clip" stylus text getter. // Extracts the data at the given rect. @@ -184,6 +185,8 @@ struct CreateNewWindowParams { // The window features to use for the new window. blink.mojom.WindowFeatures features; + + mojo_base.mojom.String16 nw_window_manifest; }; // Operation result when the renderer asks the browser to create a new window. @@ -234,6 +237,8 @@ struct DidCommitProvisionalLoadParams; // Implemented by the frame server (i.e. the browser process). For messages that // must be associated with the IPC channel. interface FrameHost { + SetNodeJS(bool node); + SetContextCreated(bool created); // Sent by the renderer to request the browser to create a new window. |reply| // is only non-null on when status == CreateNewWindowStatus::kSuccess. [Sync] CreateNewWindow(CreateNewWindowParams params) diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 98bc62f6c9372..c17c7906fd427 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h @@ -239,7 +239,9 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameOwnerProperties) IPC_STRUCT_TRAITS_MEMBER(margin_width) IPC_STRUCT_TRAITS_MEMBER(margin_height) IPC_STRUCT_TRAITS_MEMBER(allow_fullscreen) + IPC_STRUCT_TRAITS_MEMBER(nwfaketop) IPC_STRUCT_TRAITS_MEMBER(allow_payment_request) + IPC_STRUCT_TRAITS_MEMBER(nwuseragent) IPC_STRUCT_TRAITS_MEMBER(is_display_none) IPC_STRUCT_TRAITS_MEMBER(required_csp) IPC_STRUCT_TRAITS_END() @@ -738,6 +740,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::FileChooserParams) IPC_STRUCT_TRAITS_MEMBER(capture) #endif IPC_STRUCT_TRAITS_MEMBER(requestor) + IPC_STRUCT_TRAITS_MEMBER(initial_path) + IPC_STRUCT_TRAITS_MEMBER(extract_directory) IPC_STRUCT_TRAITS_END() IPC_STRUCT_BEGIN(FrameMsg_MixedContentFound_Params) diff --git a/content/common/frame_owner_properties.cc b/content/common/frame_owner_properties.cc index 0a135b4d02f78..8df0d29fb8230 100644 --- a/content/common/frame_owner_properties.cc +++ b/content/common/frame_owner_properties.cc @@ -8,6 +8,7 @@ namespace content { FrameOwnerProperties::FrameOwnerProperties() : scrolling_mode(blink::WebFrameOwnerProperties::ScrollingMode::kAuto), + nwfaketop(false), margin_width(-1), margin_height(-1), allow_fullscreen(false), @@ -21,6 +22,8 @@ FrameOwnerProperties::~FrameOwnerProperties() {} bool FrameOwnerProperties::operator==(const FrameOwnerProperties& other) const { return name == other.name && scrolling_mode == other.scrolling_mode && + nwfaketop == other.nwfaketop && + nwuseragent == other.nwuseragent && margin_width == other.margin_width && margin_height == other.margin_height && allow_fullscreen == other.allow_fullscreen && diff --git a/content/common/frame_owner_properties.h b/content/common/frame_owner_properties.h index 74ed5d594288b..56cb38d98ca02 100644 --- a/content/common/frame_owner_properties.h +++ b/content/common/frame_owner_properties.h @@ -26,8 +26,10 @@ struct CONTENT_EXPORT FrameOwnerProperties { return !(*this == other); } + std::string nwuseragent; std::string name; // browsing context container's name blink::WebFrameOwnerProperties::ScrollingMode scrolling_mode; + bool nwfaketop; int margin_width; int margin_height; bool allow_fullscreen; diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 2405622dde31a..3b7ca5dfd4d65 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom @@ -89,6 +89,7 @@ struct CreateViewParams { // window.open or via ) should be renderer-wide (i.e. going // beyond the usual opener-relationship-based BrowsingInstance boundaries). bool renderer_wide_named_frame_lookup; + bool skip_blocking_parser; }; struct CreateFrameWidgetParams { diff --git a/content/common/shared_worker/shared_worker_info.mojom b/content/common/shared_worker/shared_worker_info.mojom index 38782d71ee1c4..173832b3fb477 100644 --- a/content/common/shared_worker/shared_worker_info.mojom +++ b/content/common/shared_worker/shared_worker_info.mojom @@ -7,12 +7,15 @@ module content.mojom; import "third_party/blink/public/mojom/net/ip_address_space.mojom"; import "third_party/blink/public/platform/content_security_policy.mojom"; import "url/mojom/url.mojom"; +import "mojo/public/mojom/base/file_path.mojom"; // Meta data that is necessary to create a new shared worker context. This // structure gets populated when a new SharedWorker object is created in the // parent context (e.g. Document), and passed onto the destination child // process where the shared worker runs. struct SharedWorkerInfo { + bool is_node_js; + mojo_base.mojom.FilePath root_path; url.mojom.Url url; string name; string content_security_policy; diff --git a/content/common/user_agent.cc b/content/common/user_agent.cc index e4565757f8869..28fd16bbf05d0 100644 --- a/content/common/user_agent.cc +++ b/content/common/user_agent.cc @@ -153,6 +153,16 @@ std::string BuildUserAgentFromProduct(const std::string& product) { return BuildUserAgentFromOSAndProduct(os_info, product); } +std::string BuildOSInfo() { + std::string os_info; + base::StringAppendF( + &os_info, + "%s%s", + getUserAgentPlatform().c_str(), + BuildOSCpuInfo().c_str()); + return os_info; +} + std::string BuildUserAgentFromProductAndExtraOSInfo( const std::string& product, const std::string& extra_os_info) { diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 7411a755dd7b1..9419058432fa0 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -247,6 +247,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences) IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_height_vertical_scroll_bar_in_dips) IPC_STRUCT_TRAITS_MEMBER(arrow_bitmap_width_horizontal_scroll_bar_in_dips) #endif + IPC_STRUCT_TRAITS_MEMBER(nw_inject_js_doc_start) + IPC_STRUCT_TRAITS_MEMBER(nw_inject_js_doc_end) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(content::TextInputState) @@ -578,8 +580,9 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_AppCacheAccessed, // Used to go to the session history entry at the given offset (ie, -1 will // return the "back" item). -IPC_MESSAGE_ROUTED1(ViewHostMsg_GoToEntryAtOffset, - int /* offset (from current) of history item to get */) +IPC_MESSAGE_ROUTED2(ViewHostMsg_GoToEntryAtOffset, + int /* offset (from current) of history item to get */, + int /* frame id*/) // Sent from an inactive renderer for the browser to route to the active // renderer, instructing it to close. diff --git a/content/ppapi_plugin/ppapi_plugin_main.cc b/content/ppapi_plugin/ppapi_plugin_main.cc index c2cf95a216ae0..4d7f2cba7107b 100644 --- a/content/ppapi_plugin/ppapi_plugin_main.cc +++ b/content/ppapi_plugin/ppapi_plugin_main.cc @@ -121,7 +121,7 @@ int PpapiPluginMain(const MainFunctionParams& parameters) { gin::V8Initializer::LoadV8Natives(); #endif -#if defined(OS_LINUX) +#if 0//defined(OS_LINUX) service_manager::SandboxLinux::GetInstance()->InitializeSandbox( service_manager::SandboxTypeFromCommandLine(command_line), service_manager::SandboxLinux::PreSandboxHook(), diff --git a/content/public/browser/child_process_security_policy.h b/content/public/browser/child_process_security_policy.h index 9ebdbd08c7c1f..63bda6e7c8f43 100644 --- a/content/public/browser/child_process_security_policy.h +++ b/content/public/browser/child_process_security_policy.h @@ -65,6 +65,7 @@ class ChildProcessSecurityPolicy { // change it to accept an URL instead. virtual bool IsWebSafeScheme(const std::string& scheme) = 0; + virtual void GrantAll(int child_id) = 0; // This permission grants only read access to a file. // Whenever the user picks a file from a element, the // browser should call this function to grant the child process the capability diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index a8927d0ba8da7..763b00358d0c8 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc @@ -285,6 +285,10 @@ void ContentBrowserClient::AllowWorkerFileSystem( std::move(callback).Run(true); } +base::FilePath ContentBrowserClient::GetRootPath() { + return base::FilePath(); +} + bool ContentBrowserClient::AllowWorkerIndexedDB( const GURL& url, const base::string16& name, diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index e9c6b810e050f..76e092729d757 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -493,6 +493,7 @@ class CONTENT_EXPORT ContentBrowserClient { const std::vector >& render_frames, base::Callback callback); + virtual base::FilePath GetRootPath(); // Allow the embedder to control if access to IndexedDB by a shared worker // is allowed. // This is called on the IO thread. diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index f5dced5b83470..2ed866a83f767 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h @@ -96,6 +96,8 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener, // Returns the accessibility tree ID for this RenderFrameHost. virtual int GetAXTreeID() = 0; + virtual bool nodejs() = 0; + virtual bool context_created() = 0; // Returns the SiteInstance grouping all RenderFrameHosts that have script // access to this RenderFrameHost, and must therefore live in the same // process. diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 4fc457c9e4131..de4e352141717 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h @@ -320,7 +320,8 @@ class CONTENT_EXPORT WebContentsDelegate { int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - WebContents* new_contents) {} + WebContents* new_contents, + const base::string16& nw_window_manifest) {} // Notification that one of the frames in the WebContents is hung. |source| is // the WebContents that is hung, and |render_widget_host| is the diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h index 528fd6abf6a62..5265efac25337 100644 --- a/content/public/common/content_client.h +++ b/content/public/common/content_client.h @@ -91,6 +91,7 @@ class CONTENT_EXPORT ContentClient { // WebSecurityOrigin or a full URL (if called from the browser process) and a // string is the lowest-common-denominator. virtual void SetActiveURL(const GURL& url, std::string top_origin) {} + virtual void SetNWReportURL(const GURL& url) {} // Sets the data on the current gpu. virtual void SetGpuInfo(const gpu::GPUInfo& gpu_info) {} diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 10d9366af3365..42b63d4028858 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc @@ -7,6 +7,9 @@ namespace features { +const base::Feature kNWNewWin{ + "NWNewWin", base::FEATURE_DISABLED_BY_DEFAULT}; + // All features in alphabetical order. // Enables the allowActivationDelegation attribute on iframes. @@ -376,7 +379,7 @@ const base::Feature kSlimmingPaintV175{"SlimmingPaintV175", // spare renderer process around for the most recently requested BrowserContext. // This feature is only consulted in site-per-process mode. const base::Feature kSpareRendererForSitePerProcess{ - "SpareRendererForSitePerProcess", base::FEATURE_ENABLED_BY_DEFAULT}; + "SpareRendererForSitePerProcess", base::FEATURE_DISABLED_BY_DEFAULT}; // Stop scheduler task queues in background after allowed grace time. const base::Feature kStopInBackground { diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index d972131225d80..06b3456fe8f35 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h @@ -14,6 +14,7 @@ namespace features { +CONTENT_EXPORT extern const base::Feature kNWNewWin; // All features in alphabetical order. The features should be documented // alongside the definition of their values in the .cc file. CONTENT_EXPORT extern const base::Feature kAllowActivationDelegationAttr; diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index aac63339ab228..aa5338db7fcf7 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -146,9 +146,17 @@ const char kDisableGestureRequirementForPresentation[] = // then the GPU process won't launch. const char kDisableGpu[] = "disable-gpu"; +// Disable apps transparency support +const char kDisableTransparency[] = "disable-transparency"; + +// Force CPU drawing, needed to enable click through on transparent window +const char kForceCpuDraw[] = "force-cpu-draw"; + // Prevent the compositor from using its GPU implementation. const char kDisableGpuCompositing[] = "disable-gpu-compositing"; - +const char kDisableRAFThrottling[] = "disable-raf-throttling"; +const char kEnableNodeWorker[] = "enable-node-worker"; +const char kNWAppPath[] = "nwapp-path"; // Disable proactive early init of GPU process. const char kDisableGpuEarlyInit[] = "disable-gpu-early-init"; diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 990f172ac8cba..abf0631d3e001 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -53,7 +53,12 @@ CONTENT_EXPORT extern const char kDisableFlash3d[]; CONTENT_EXPORT extern const char kDisableFlashStage3d[]; CONTENT_EXPORT extern const char kDisableGestureRequirementForPresentation[]; CONTENT_EXPORT extern const char kDisableGpu[]; +CONTENT_EXPORT extern const char kDisableTransparency[]; +CONTENT_EXPORT extern const char kForceCpuDraw[]; CONTENT_EXPORT extern const char kDisableGpuCompositing[]; +CONTENT_EXPORT extern const char kDisableRAFThrottling[]; +CONTENT_EXPORT extern const char kEnableNodeWorker[]; +CONTENT_EXPORT extern const char kNWAppPath[]; CONTENT_EXPORT extern const char kDisableGpuEarlyInit[]; CONTENT_EXPORT extern const char kDisableGpuMemoryBufferCompositorResources[]; CONTENT_EXPORT extern const char kDisableGpuMemoryBufferVideoFrames[]; diff --git a/content/public/common/file_chooser_params.h b/content/public/common/file_chooser_params.h index c189785370bdc..9c466e3b1c387 100644 --- a/content/public/common/file_chooser_params.h +++ b/content/public/common/file_chooser_params.h @@ -62,6 +62,9 @@ struct CONTENT_EXPORT FileChooserParams { // initiated by a document. Note that this value should be considered // untrustworthy since it is specified by the sandbox and not validated. GURL requestor; + + base::FilePath initial_path; + bool extract_directory; }; } // namespace content diff --git a/content/public/common/renderer_preferences.h b/content/public/common/renderer_preferences.h index 688fc6b020766..6ac4559b034f8 100644 --- a/content/public/common/renderer_preferences.h +++ b/content/public/common/renderer_preferences.h @@ -166,6 +166,9 @@ struct CONTENT_EXPORT RendererPreferences { // The width of the arrow bitmap on a horizontal scroll bar in dips. int32_t arrow_bitmap_width_horizontal_scroll_bar_in_dips; #endif + + std::string nw_inject_js_doc_start; + std::string nw_inject_js_doc_end; }; } // namespace content diff --git a/content/public/common/user_agent.h b/content/public/common/user_agent.h index 8a095a81c92ea..fc5d94b9933ea 100644 --- a/content/public/common/user_agent.h +++ b/content/public/common/user_agent.h @@ -19,6 +19,8 @@ CONTENT_EXPORT std::string GetWebKitRevision(); // Builds a User-agent compatible string that describes the OS and CPU type. CONTENT_EXPORT std::string BuildOSCpuInfo(); +CONTENT_EXPORT std::string BuildOSInfo(); + // Helper function to generate a full user agent string from a short // product name. CONTENT_EXPORT std::string BuildUserAgentFromProduct( diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc index c5f6d0b03ba63..4fac2b5ee0b29 100644 --- a/content/public/common/web_preferences.cc +++ b/content/public/common/web_preferences.cc @@ -187,13 +187,13 @@ WebPreferences::WebPreferences() user_gesture_required_for_presentation(true), text_track_margin_percentage(0.0f), immersive_mode_enabled(false), + double_tap_to_zoom_enabled(false), #if defined(OS_ANDROID) text_autosizing_enabled(true), font_scale_factor(1.0f), device_scale_adjustment(1.0f), force_enable_zoom(false), fullscreen_supported(true), - double_tap_to_zoom_enabled(true), support_deprecated_target_density_dpi(false), use_legacy_background_size_shorthand_behavior(false), wide_viewport_quirk(false), diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h index a1e9fba06a665..1324bf0514581 100644 --- a/content/public/common/web_preferences.h +++ b/content/public/common/web_preferences.h @@ -224,13 +224,13 @@ struct CONTENT_EXPORT WebPreferences { bool immersive_mode_enabled; + bool double_tap_to_zoom_enabled; #if defined(OS_ANDROID) bool text_autosizing_enabled; float font_scale_factor; float device_scale_adjustment; bool force_enable_zoom; bool fullscreen_supported; - bool double_tap_to_zoom_enabled; std::string media_playback_gesture_whitelist_scope; GURL default_video_poster_url; bool support_deprecated_target_density_dpi; diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 5134616afa5d6..459927bed4878 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc @@ -17,6 +17,10 @@ namespace content { +base::FilePath ContentRendererClient::GetRootPath() { + return base::FilePath(); +} + SkBitmap* ContentRendererClient::GetSadPluginBitmap() { return nullptr; } diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 6dd2589d653a8..ff4a3a9a3dc98 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h @@ -12,6 +12,8 @@ #include #include +#include "base/files/file_path.h" + #include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" @@ -39,6 +41,7 @@ class SingleThreadTaskRunner; } namespace blink { +class WebString; class WebFrame; class WebLocalFrame; class WebMIDIAccessor; @@ -69,6 +72,13 @@ struct WebPluginInfo; // Embedder API for participating in renderer logic. class CONTENT_EXPORT ContentRendererClient { public: + virtual base::FilePath GetRootPath(); + virtual void willHandleNavigationPolicy(RenderView* rv, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy* policy, + blink::WebString* manifest, + bool new_win) {} virtual ~ContentRendererClient() {} // Notifies us that the RenderThread has been created. diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index aae1e6cbc6aee..e4ec53ecba06b 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc @@ -182,6 +182,7 @@ void BrowserTestBase::SetUp() { if (AllowFileAccessFromFiles()) command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); + command_line->AppendSwitch("nwjs-test-mode"); command_line->AppendSwitch(switches::kDomAutomationController); // It is sometimes useful when looking at browser test failures to know which diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 4f9c35e697bbf..cfdaa45f81956 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -33,6 +33,8 @@ target(link_target_type, "renderer") { sources = [ "accessibility/aom_content_ax_tree.cc", "accessibility/aom_content_ax_tree.h", + "//base/message_loop/message_pumpuv_mac.mm", + "//base/message_loop/message_pumpuv_mac.h", "accessibility/blink_ax_enum_conversion.cc", "accessibility/blink_ax_enum_conversion.h", "accessibility/blink_ax_tree_source.cc", diff --git a/content/renderer/frame_owner_properties.cc b/content/renderer/frame_owner_properties.cc index 66df968b837c8..d7443a45a4519 100644 --- a/content/renderer/frame_owner_properties.cc +++ b/content/renderer/frame_owner_properties.cc @@ -16,11 +16,13 @@ FrameOwnerProperties ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( const blink::WebFrameOwnerProperties& web_frame_owner_properties) { FrameOwnerProperties result; + result.nwuseragent = web_frame_owner_properties.nwuseragent.Utf8(); result.name = web_frame_owner_properties.name.Utf8(); result.scrolling_mode = web_frame_owner_properties.scrolling_mode; result.margin_width = web_frame_owner_properties.margin_width; result.margin_height = web_frame_owner_properties.margin_height; result.allow_fullscreen = web_frame_owner_properties.allow_fullscreen; + result.nwfaketop = web_frame_owner_properties.nwFakeTop; result.allow_payment_request = web_frame_owner_properties.allow_payment_request; result.required_csp = web_frame_owner_properties.required_csp.Utf8(); @@ -38,6 +40,7 @@ ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( result.margin_width = frame_owner_properties.margin_width; result.margin_height = frame_owner_properties.margin_height; result.allow_fullscreen = frame_owner_properties.allow_fullscreen; + result.nwFakeTop = frame_owner_properties.nwfaketop; result.allow_payment_request = frame_owner_properties.allow_payment_request; result.required_csp = blink::WebString::FromUTF8(frame_owner_properties.required_csp); diff --git a/content/renderer/in_process_renderer_thread.cc b/content/renderer/in_process_renderer_thread.cc index e6a3a5d9e2219..5d3556b44d4d8 100644 --- a/content/renderer/in_process_renderer_thread.cc +++ b/content/renderer/in_process_renderer_thread.cc @@ -9,6 +9,8 @@ #include "content/renderer/render_process_impl.h" #include "content/renderer/render_thread_impl.h" +#include "content/nw/src/nw_content.h" + #if defined(OS_ANDROID) #include "base/android/jni_android.h" #endif diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index c027c4df34238..9501c9b20b4be 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -240,6 +240,9 @@ using base::Time; using base::TimeDelta; + +#include "content/nw/src/nw_content.h" + using blink::WebContentDecryptionModule; using blink::WebContextMenuData; using blink::WebData; @@ -1051,6 +1054,16 @@ blink::WebLocalFrame* RenderFrameImpl::UniqueNameFrameAdapter::GetWebFrame() return render_frame_->frame_; } +void RenderFrameImpl::willHandleNavigationPolicy( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy* policy, + blink::WebString* manifest, + bool new_win) { + GetContentClient()->renderer() + ->willHandleNavigationPolicy(render_view_, frame, request, policy, manifest, new_win); +} + // static RenderFrameImpl* RenderFrameImpl::Create( RenderViewImpl* render_view, @@ -1298,7 +1311,7 @@ RenderFrameImpl::CreateParams& RenderFrameImpl::CreateParams::operator=( // RenderFrameImpl ---------------------------------------------------------- RenderFrameImpl::RenderFrameImpl(CreateParams params) - : frame_(nullptr), + : skip_blocking_parser_(true), frame_(nullptr), is_main_frame_(true), unique_name_frame_adapter_(this), unique_name_helper_(&unique_name_frame_adapter_), @@ -2835,6 +2848,11 @@ void RenderFrameImpl::GetInterfaceProvider( browser_info_.identity, std::move(request), std::move(provider)); } + +void RenderFrameImpl::SetSkipBlockingParser(bool value) { + skip_blocking_parser_ = value; +} + void RenderFrameImpl::GetCanonicalUrlForSharing( GetCanonicalUrlForSharingCallback callback) { WebURL canonical_url = GetWebFrame()->GetDocument().CanonicalUrlForSharing(); @@ -4517,7 +4535,9 @@ bool RenderFrameImpl::RunFileChooser( ipc_params.capture = params.use_media_capture; #endif ipc_params.requestor = params.requestor; - + ipc_params.initial_path = blink::WebStringToFilePath(params.initial_path); + ipc_params.extract_directory = params.extract_directory; + ipc_params.default_file_name = blink::WebStringToFilePath(params.initial_value).BaseName(); return ScheduleFileChooser(ipc_params, chooser_completion); } @@ -4927,6 +4947,7 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local context, blink::WebContextFeatures::EnableMojoJS(context, true); } + GetFrameHost()->SetContextCreated(true); for (auto& observer : observers_) observer.DidCreateScriptContext(context, world_id); } @@ -4935,6 +4956,7 @@ void RenderFrameImpl::WillReleaseScriptContext(v8::Local context, int world_id) { for (auto& observer : observers_) observer.WillReleaseScriptContext(context, world_id); + GetFrameHost()->SetContextCreated(false); } void RenderFrameImpl::DidChangeScrollOffset() { @@ -4996,6 +5018,10 @@ blink::WebEncryptedMediaClient* RenderFrameImpl::EncryptedMediaClient() { } blink::WebString RenderFrameImpl::UserAgentOverride() { + std::string user_agent; + if (nw::GetUserAgentFromManifest(&user_agent)) + return WebString::FromUTF8(user_agent); + if (!render_view_->webview() || !render_view_->webview()->MainFrame() || render_view_->renderer_preferences_.user_agent_override.empty()) { return blink::WebString(); diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index d841189173ce8..9a6dc27507dd1 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h @@ -194,6 +194,7 @@ class CONTENT_EXPORT RenderFrameImpl public blink::WebFrameSerializerClient, service_manager::mojom::InterfaceProvider { public: + bool skip_blocking_parser_; // Creates a new RenderFrame as the main frame of |render_view|. static RenderFrameImpl* CreateMainFrame( RenderViewImpl* render_view, @@ -506,6 +507,7 @@ class CONTENT_EXPORT RenderFrameImpl service_manager::mojom::InterfaceProviderRequest request) override; void GetCanonicalUrlForSharing( GetCanonicalUrlForSharingCallback callback) override; + void SetSkipBlockingParser(bool) override; #if defined(OS_ANDROID) void ExtractSmartClipData( const gfx::Rect& rect, @@ -762,6 +764,12 @@ class CONTENT_EXPORT RenderFrameImpl const blink::WebVector& data, blink::WebFrameSerializerClient::FrameSerializationStatus status) override; + void willHandleNavigationPolicy( + blink::WebFrame*, + const blink::WebURLRequest&, + blink::WebNavigationPolicy*, + blink::WebString* manifest = NULL, + bool new_win = true) override; // Binds to the site engagement service in the browser. void BindEngagement(blink::mojom::EngagementClientAssociatedRequest request); diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index f839d5610a1b6..b64a5fd03d4c9 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc @@ -178,6 +178,12 @@ RenderProcessImpl::RenderProcessImpl( const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch("nwjs-guest")) { + VLOG(1) << "Enabling --no-untrusted-code-mitigations for trusted process."; + std::string flags("--no-untrusted-code-mitigations --allow_natives_syntax"); + v8::V8::SetFlagsFromString(flags.c_str(), static_cast(flags.size())); + } + if (command_line.HasSwitch(switches::kJavaScriptFlags)) { std::string flags( command_line.GetSwitchValueASCII(switches::kJavaScriptFlags)); diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 4aba7a9e290e7..15dd95f4f95aa 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -574,6 +574,7 @@ void RenderViewImpl::Initialize( GetWebScreenInfo(), compositor_deps_, opener_frame, params->devtools_main_frame_token, params->replicated_frame_state, params->has_committed_real_load); + main_render_frame_->SetSkipBlockingParser(params->skip_blocking_parser); } // TODO(dcheng): Shouldn't these be mutually exclusive at this point? See @@ -845,6 +846,7 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, static_cast( prefs.save_previous_document_resources)); + settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); #if defined(OS_ANDROID) settings->SetAllowCustomScrollbarInMainFrame(false); settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled); @@ -853,7 +855,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, settings->SetFullscreenSupported(prefs.fullscreen_supported); web_view->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom); settings->SetAutoZoomFocusedNodeToLegibleScale(true); - settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); settings->SetMediaPlaybackGestureWhitelistScope( blink::WebString::FromUTF8(prefs.media_playback_gesture_whitelist_scope)); settings->SetDefaultVideoPosterURL( @@ -969,7 +970,7 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, prefs.data_saver_holdback_media_api_enabled); #if defined(OS_MACOSX) - settings->SetDoubleTapToZoomEnabled(true); + //settings->SetDoubleTapToZoomEnabled(true); web_view->SetMaximumLegibleScale(prefs.default_maximum_page_scale_factor); #endif @@ -1214,7 +1215,8 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, const WebString& frame_name, WebNavigationPolicy policy, bool suppress_opener, - WebSandboxFlags sandbox_flags) { + WebSandboxFlags sandbox_flags, + WebString* manifest) { RenderFrameImpl* creator_frame = RenderFrameImpl::FromWebFrame(creator); mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New(); params->user_gesture = @@ -1242,6 +1244,7 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, params->referrer = GetReferrerFromRequest(creator, request); } params->features = ConvertWebWindowFeaturesToMojoWindowFeatures(features); + params->nw_window_manifest = manifest->Utf16(); // We preserve this information before sending the message since |params| is // moved on send. @@ -1543,6 +1546,20 @@ void RenderViewImpl::DidUpdateLayout() { &RenderViewImpl::CheckPreferredSize); } +void RenderViewImpl::NavigateBackForwardSoon2(int offset, WebLocalFrame* initiator) { + RenderFrameImpl* frame = RenderFrameImpl::FromWebFrame(initiator); + int id = -1; + if (frame) + id = frame->GetRoutingID(); + history_navigation_virtual_time_pauser_ = + RenderThreadImpl::current() + ->GetWebMainThreadScheduler() + ->CreateWebScopedVirtualTimePauser( + "NavigateBackForwardSoon", + blink::WebScopedVirtualTimePauser::VirtualTaskDuration::kInstant); + history_navigation_virtual_time_pauser_.PauseVirtualTime(); + Send(new ViewHostMsg_GoToEntryAtOffset(GetRoutingID(), offset, id)); +} void RenderViewImpl::NavigateBackForwardSoon(int offset) { history_navigation_virtual_time_pauser_ = RenderThreadImpl::current() @@ -1551,7 +1568,7 @@ void RenderViewImpl::NavigateBackForwardSoon(int offset) { "NavigateBackForwardSoon", blink::WebScopedVirtualTimePauser::VirtualTaskDuration::kInstant); history_navigation_virtual_time_pauser_.PauseVirtualTime(); - Send(new ViewHostMsg_GoToEntryAtOffset(GetRoutingID(), offset)); + Send(new ViewHostMsg_GoToEntryAtOffset(GetRoutingID(), offset, -1)); } void RenderViewImpl::DidCommitProvisionalHistoryLoad() { diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 77f18279cddbd..9d621ec7aaaf4 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -279,7 +279,8 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, const blink::WebString& frame_name, blink::WebNavigationPolicy policy, bool suppress_opener, - blink::WebSandboxFlags sandbox_flags) override; + blink::WebSandboxFlags sandbox_flags, + blink::WebString* manifest) override; blink::WebWidget* CreatePopup(blink::WebLocalFrame* creator, blink::WebPopupType popup_type) override; base::StringPiece GetSessionStorageNamespaceId() override; @@ -309,6 +310,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, #endif blink::WebString AcceptLanguages() override; void NavigateBackForwardSoon(int offset) override; + void NavigateBackForwardSoon2(int offset, blink::WebLocalFrame* initiator) override; int HistoryBackListCount() override; int HistoryForwardListCount() override; void ZoomLimitsChanged(double minimum_level, double maximum_level) override; diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index f0374259db0e5..db96f4b4f4074 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -7,6 +7,8 @@ #include #include +#include "content/nw/src/nw_content.h" + #include "base/auto_reset.h" #include "base/bind.h" #include "base/command_line.h" @@ -151,6 +153,15 @@ using blink::WebTouchPoint; using blink::WebVector; using blink::WebWidget; +namespace nw { +typedef bool (*RenderWidgetWasHiddenHookFn)(content::RenderWidget*); +#if defined(COMPONENT_BUILD) +CONTENT_EXPORT RenderWidgetWasHiddenHookFn gRenderWidgetWasHiddenHook = nullptr; +#else +RenderWidgetWasHiddenHookFn gRenderWidgetWasHiddenHook = nullptr; +#endif +} + namespace content { namespace { @@ -817,6 +828,8 @@ void RenderWidget::OnDisableDeviceEmulation() { } void RenderWidget::OnWasHidden() { + if (nw::gRenderWidgetWasHiddenHook && nw::gRenderWidgetWasHiddenHook(this)) + return; TRACE_EVENT0("renderer", "RenderWidget::OnWasHidden"); // Go into a mode where we stop generating paint and scrolling events. SetHidden(true); diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 4205c92765af1..cf120b1fe254f 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc @@ -6,6 +6,8 @@ #include #include +#include "content/nw/src/nw_version.h" + #include #include @@ -178,6 +180,21 @@ using blink::WebString; using blink::WebURL; using blink::WebVector; +#include "third_party/node-nw/src/node_webkit.h" +#include "nw/id/commit.h" + +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + +namespace nw{ +const char* GetChromiumVersion(); +} + namespace content { namespace { @@ -1250,9 +1267,40 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() { } void RendererBlinkPlatformImpl::WorkerContextCreated( - const v8::Local& worker) { + const v8::Local& worker, bool isNodeJS, const std::string& main_script) { GetContentClient()->renderer()->DidInitializeWorkerContextOnWorkerThread( worker); + if (isNodeJS) { + int argc = 1; + char argv0[] = "node"; + char* argv[3]; + argv[0] = argv0; + argv[1] = argv[2] = nullptr; + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + v8::MicrotasksScope microtasks(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + + worker->SetSecurityToken(v8::String::NewFromUtf8(isolate, "nw-token")); + worker->Enter(); + + ::g_start_nw_instance_fn(argc, argv, worker, nullptr); + { + v8::Local script = + v8::Script::Compile(worker, v8::String::NewFromUtf8(isolate, + (std::string("process.versions['nw'] = '" NW_VERSION_STRING "';") + + "process.versions['node-webkit'] = '" NW_VERSION_STRING "';" + "process.versions['nw-commit-id'] = '" NW_COMMIT_HASH "';" + "process.versions['chromium'] = '" + "';").c_str() + )).ToLocalChecked(); + ignore_result(script->Run(worker)); + } + { + v8::Local script = + v8::Script::Compile(worker, v8::String::NewFromUtf8(isolate, main_script.c_str())).ToLocalChecked(); + ignore_result(script->Run(worker)); + } + } } //------------------------------------------------------------------------------ diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index ecb5ce6d6aa07..ee8b1237b72ce 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h @@ -203,7 +203,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { blink::WebPushProvider* PushProvider() override; void DidStartWorkerThread() override; void WillStopWorkerThread() override; - void WorkerContextCreated(const v8::Local& worker) override; + void WorkerContextCreated(const v8::Local& worker, bool, const std::string&) override; // Set the PlatformEventObserverBase in |platform_event_observers_| associated // with |type| to |observer|. If there was already an observer associated to diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index f3664c6e0eb84..b64e41c063afd 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc @@ -4,7 +4,7 @@ #include #include - +#include "base/files/file_util.h" #include "base/base_switches.h" #include "base/command_line.h" #include "base/debug/debugger.h" @@ -38,6 +38,7 @@ #include "third_party/skia/include/core/SkGraphics.h" #include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck #include "ui/base/ui_base_switches.h" +#include "content/nw/src/nw_content.h" #if defined(OS_ANDROID) #include "base/android/library_loader/library_loader_hooks.h" @@ -59,6 +60,8 @@ #include "base/mac/scoped_nsautorelease_pool.h" #include "base/message_loop/message_pump_mac.h" #include "third_party/blink/public/web/web_view.h" + +#include "base/message_loop/message_pumpuv_mac.h" #endif // OS_MACOSX #if BUILDFLAG(ENABLE_PLUGINS) @@ -66,6 +69,17 @@ #endif namespace content { + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif +CONTENT_EXPORT base::FilePath g_nw_temp_dir; +CONTENT_EXPORT base::FilePath g_nw_old_cwd; +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + namespace { // This function provides some ways to test crash and assertion handling // behavior of the renderer. @@ -105,6 +119,12 @@ int RendererMain(const MainFunctionParams& parameters) { profiler->Start(); } + + bool nwjs = command_line.HasSwitch(switches::kNWJS); + + if (nwjs) + nw::LoadNodeSymbols(); + #if defined(OS_MACOSX) base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool; #endif // OS_MACOSX @@ -173,12 +193,25 @@ int RendererMain(const MainFunctionParams& parameters) { // As long as scrollbars on Mac are painted with Cocoa, the message pump // needs to be backed by a Foundation-level loop to process NSTimers. See // http://crbug.com/306348#c24 for details. - std::unique_ptr pump(new base::MessagePumpNSRunLoop()); + base::MessagePump* p; + if (nwjs) { + p = new base::MessagePumpUVNSRunLoop(); + } else + p = new base::MessagePumpNSRunLoop(); + std::unique_ptr pump(p); std::unique_ptr main_message_loop( new base::MessageLoop(std::move(pump))); #else - // The main message loop of the renderer services doesn't have IO or UI tasks. - std::unique_ptr main_message_loop(new base::MessageLoop()); + // The main message loop of the renderer services doesn't have IO or + // UI tasks. + base::MessageLoop* msg_loop; + if (nwjs) { + std::unique_ptr pump_uv(new base::MessagePumpUV()); + msg_loop = new base::MessageLoop(std::move(pump_uv)); + } else + msg_loop = new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT); + + std::unique_ptr main_message_loop(msg_loop); #endif base::PlatformThread::SetName("CrRendererMain"); @@ -246,6 +279,12 @@ int RendererMain(const MainFunctionParams& parameters) { TRACE_EVENT_ASYNC_END0("toplevel", "RendererMain.START_MSG_LOOP", 0); } + if (!g_nw_temp_dir.empty()) { + base::SetCurrentDirectory(g_nw_temp_dir.DirName()); + if (base::StartsWith(g_nw_temp_dir.BaseName().value(), FILE_PATH_LITERAL("nw"), + base::CompareCase::SENSITIVE)) + base::DeleteFile(g_nw_temp_dir, true); + } #if defined(LEAK_SANITIZER) // Run leak detection before RenderProcessImpl goes out of scope. This helps // ignore shutdown-only leaks. diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc index edf1d066262cc..08f3b2b6b8915 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc @@ -189,7 +189,7 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( : binding_(this, std::move(request)), host_(std::move(host)), name_(info->name), - url_(info->url) { + url_(info->url), nodejs_(info->is_node_js), root_path_(info->root_path) { impl_ = blink::WebSharedWorker::Create(this); if (pause_on_start) { // Pause worker context when it starts and wait until either DevTools client @@ -200,7 +200,7 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( service_worker_provider_info_ = std::move(service_worker_provider_info); script_loader_factory_info_ = std::move(script_loader_factory_info); - impl_->StartWorkerContext( + impl_->StartWorkerContext(nodejs_, root_path_, url_, blink::WebString::FromUTF8(name_), blink::WebString::FromUTF8(info->content_security_policy), info->content_security_policy_type, info->creation_address_space, diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h index 25b8d13f4d826..67892d31fff46 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.h +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h @@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/unguessable_token.h" +#include "base/files/file_path.h" #include "content/child/scoped_child_process_reference.h" #include "content/common/service_worker/service_worker_provider.mojom.h" #include "content/common/shared_worker/shared_worker.mojom.h" @@ -106,6 +107,9 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, GURL url_; std::unique_ptr impl_; + bool nodejs_ = false; + base::FilePath root_path_; + using PendingChannel = std::pair; std::vector pending_channels_; diff --git a/content/renderer/shared_worker/shared_worker_repository.cc b/content/renderer/shared_worker/shared_worker_repository.cc index 562ef5b2e82fc..65772503024ec 100644 --- a/content/renderer/shared_worker/shared_worker_repository.cc +++ b/content/renderer/shared_worker/shared_worker_repository.cc @@ -9,6 +9,8 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/web/web_shared_worker_connect_listener.h" +#include "content/public/renderer/content_renderer_client.h" + namespace content { SharedWorkerRepository::SharedWorkerRepository( @@ -18,6 +20,7 @@ SharedWorkerRepository::SharedWorkerRepository( SharedWorkerRepository::~SharedWorkerRepository() = default; void SharedWorkerRepository::Connect( + bool isNodeJS, const blink::WebURL& url, const blink::WebString& name, DocumentID document_id, @@ -32,6 +35,7 @@ void SharedWorkerRepository::Connect( interface_provider_->GetInterface(mojo::MakeRequest(&connector_)); mojom::SharedWorkerInfoPtr info(mojom::SharedWorkerInfo::New( + isNodeJS, GetContentClient()->renderer()->GetRootPath(), url, name.Utf8(), content_security_policy.Utf8(), content_security_policy_type, creation_address_space)); diff --git a/content/renderer/shared_worker/shared_worker_repository.h b/content/renderer/shared_worker/shared_worker_repository.h index d0a8ce2c9093f..e462c663468b9 100644 --- a/content/renderer/shared_worker/shared_worker_repository.h +++ b/content/renderer/shared_worker/shared_worker_repository.h @@ -36,6 +36,7 @@ class SharedWorkerRepository final // WebSharedWorkerRepositoryClient overrides. void Connect( + bool isNodeJS, const blink::WebURL& url, const blink::WebString& name, DocumentID document_id, diff --git a/content/shell/test_runner/web_view_test_proxy.h b/content/shell/test_runner/web_view_test_proxy.h index 4b59497bf148e..f578c6017158e 100644 --- a/content/shell/test_runner/web_view_test_proxy.h +++ b/content/shell/test_runner/web_view_test_proxy.h @@ -192,7 +192,7 @@ class WebViewTestProxy : public Base, public WebViewTestProxyBase { policy, suppress_opener, sandbox_flags)) return nullptr; return Base::CreateView(creator, request, features, frame_name, policy, - suppress_opener, sandbox_flags); + suppress_opener, sandbox_flags, nullptr); } void PrintPage(blink::WebLocalFrame* frame) override { view_test_client()->PrintPage(frame); diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index 8d7bc9840765d..f02ced7754602 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc @@ -50,6 +50,8 @@ class MockFrameHost : public mojom::FrameHost { protected: // mojom::FrameHost: + void SetNodeJS(bool) override {} + void SetContextCreated(bool) override {} void CreateNewWindow(mojom::CreateNewWindowParamsPtr, CreateNewWindowCallback) override { NOTREACHED() << "We should never dispatch to the service side signature."; diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index 0953b5fca880a..35e15e2ea64f5 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn @@ -152,7 +152,7 @@ jumbo_static_library("test_support") { "//net:test_support", "//testing/gmock", "//testing/gtest", - "//third_party/cld_3/src/src:cld_3", + #"//third_party/cld_3/src/src:cld_3", ] public_deps = [ diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 40b145b62c4ec..ddba4a1dde2c0 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn @@ -396,6 +396,10 @@ jumbo_source_set("browser_sources") { "//ui/display", ] + include_dirs = [ + "//third_party/WebKit", + ] + public_deps = [ "//content/public/common", "//extensions/browser/install", diff --git a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc index 354fe40109b93..fea89bf76839f 100644 --- a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc +++ b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.cc @@ -26,6 +26,7 @@ namespace app_current_window_internal = namespace Show = app_current_window_internal::Show; namespace SetBounds = app_current_window_internal::SetBounds; namespace SetSizeConstraints = app_current_window_internal::SetSizeConstraints; +namespace SetResizable = app_current_window_internal::SetResizable; namespace SetIcon = app_current_window_internal::SetIcon; namespace SetShape = app_current_window_internal::SetShape; namespace SetAlwaysOnTop = app_current_window_internal::SetAlwaysOnTop; @@ -263,6 +264,16 @@ AppCurrentWindowInternalSetBoundsFunction::Run() { return RespondNow(NoArguments()); } +ExtensionFunction::ResponseAction +AppCurrentWindowInternalSetResizableFunction::Run() { + std::unique_ptr params( + SetResizable::Params::Create(*args_)); + CHECK(params.get()); + window()->GetBaseWindow()->SetResizable(params->flag); + window()->OnNativeWindowChanged(); + return RespondNow(NoArguments()); +} + ExtensionFunction::ResponseAction AppCurrentWindowInternalSetSizeConstraintsFunction::Run() { std::unique_ptr params( @@ -351,8 +362,10 @@ AppCurrentWindowInternalSetShapeFunction::Run() { ExtensionFunction::ResponseAction AppCurrentWindowInternalSetAlwaysOnTopFunction::Run() { + // TODO(devlin): Can't this be done with the feature files? - if (!extension()->permissions_data()->HasAPIPermission( + if (extension() != nullptr && // NWJS#5738 + !extension()->permissions_data()->HasAPIPermission( extensions::APIPermission::kAlwaysOnTopWindows)) { return RespondNow(Error(kAlwaysOnTopPermission)); } diff --git a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h index 72ddd534a5acf..4504c0cd79c19 100644 --- a/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h +++ b/extensions/browser/api/app_current_window_internal/app_current_window_internal_api.h @@ -145,6 +145,16 @@ class AppCurrentWindowInternalSetSizeConstraintsFunction ResponseAction Run() override; }; +class AppCurrentWindowInternalSetResizableFunction + : public AppCurrentWindowInternalExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("app.currentWindowInternal.setResizable", + UNKNOWN) + protected: + ~AppCurrentWindowInternalSetResizableFunction() override {} + ResponseAction Run() override; +}; + class AppCurrentWindowInternalSetIconFunction : public AppCurrentWindowInternalExtensionFunction { public: diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc index 4a510bdf94f6e..e1fd1600e81b0 100644 --- a/extensions/browser/api/app_window/app_window_api.cc +++ b/extensions/browser/api/app_window/app_window_api.cc @@ -4,6 +4,8 @@ #include "extensions/browser/api/app_window/app_window_api.h" +#include "content/browser/frame_host/render_frame_host_impl.h" + #include #include @@ -38,9 +40,15 @@ #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" +#include "content/nw/src/nw_base.h" +#include "content/nw/src/browser/nw_content_browser_hooks.h" + namespace app_window = extensions::api::app_window; namespace Create = app_window::Create; +namespace content { + DISPLAY_EXPORT extern bool g_support_transparency; +} namespace extensions { namespace app_window_constants { @@ -56,8 +64,8 @@ constexpr char kConflictingBoundsOptions[] = "The $1 property cannot be specified for both inner and outer bounds."; constexpr char kAlwaysOnTopPermission[] = "The \"app.window.alwaysOnTop\" permission is required."; -constexpr char kInvalidUrlParameter[] = - "The URL used for window creation must be local for security reasons."; +//constexpr char kInvalidUrlParameter[] = +// "The URL used for window creation must be local for security reasons."; constexpr char kAlphaEnabledWrongChannel[] = "The alphaEnabled option requires dev channel or newer."; constexpr char kAlphaEnabledMissingPermission[] = @@ -150,6 +158,10 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { // path. // TODO(devlin): Investigate if this is still used. If not, kill it dead! GURL absolute = GURL(params->url); + + if (absolute.has_scheme()) + url = absolute; +#if 0 if (absolute.has_scheme()) { if (extension()->location() == Manifest::COMPONENT) { url = absolute; @@ -158,13 +170,27 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { return RespondNow(Error(app_window_constants::kInvalidUrlParameter)); } } - +#endif // TODO(jeremya): figure out a way to pass the opening WebContents through to // AppWindow::Create so we can set the opener at create time rather than // with a hack in AppWindowCustomBindings::GetView(). AppWindow::CreateParams create_params; app_window::CreateWindowOptions* options = params->options.get(); if (options) { + if (options->title.get()) + create_params.title = *options->title; + + if (options->icon.get()) { + base::ThreadRestrictions::ScopedAllowIO allow_io; + gfx::Image app_icon; + nw::Package* package = nw::package(); + if (nw::GetPackageImage(package, + base::FilePath::FromUTF8Unsafe(*options->icon), + &app_icon)) { + create_params.icon = app_icon; + } + } + if (options->id.get()) { // TODO(mek): use URL if no id specified? // Limit length of id to 256 characters. @@ -299,6 +325,8 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { #else // Transparency is only supported on Aura. // Fallback to creating an opaque window (by ignoring alphaEnabled). + if (content::g_support_transparency) + create_params.alpha_enabled = *options->alpha_enabled; #endif } @@ -346,6 +374,22 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { } } + if (options->show_in_taskbar.get()) { + create_params.show_in_taskbar = *options->show_in_taskbar.get(); + } + + if (options->new_instance.get()) { + create_params.new_instance = *options->new_instance.get(); + } + + if (options->inject_js_start.get()) { + create_params.inject_js_start = + *options->inject_js_start.get(); + } + if (options->inject_js_end.get()) { + create_params.inject_js_end = + *options->inject_js_end.get(); + } if (options->type != app_window::WINDOW_TYPE_PANEL) { switch (options->state) { case app_window::STATE_NONE: @@ -381,10 +425,24 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { action_type = options->lock_screen_action; create_params.show_on_lock_screen = true; } + switch (options->position) { + case app_window::POSITION_NONE: + create_params.position = extensions::AppWindow::POS_NONE; + break; + case app_window::POSITION_CENTER: + create_params.position = extensions::AppWindow::POS_CENTER; + break; + case app_window::POSITION_MOUSE: + create_params.position = extensions::AppWindow::POS_MOUSE; + break; + } create_params.creator_process_id = render_frame_host()->GetProcess()->GetID(); + if (create_params.new_instance) + nw::SetPinningRenderer(false); + AppWindow* app_window = nullptr; if (action_type == api::app_runtime::ACTION_TYPE_NONE) { app_window = @@ -403,11 +461,17 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { app_window->Init(url, new AppWindowContentsImpl(app_window), render_frame_host(), create_params); + if (create_params.new_instance) + nw::SetPinningRenderer(true); + if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode() && !app_window->is_ime_window()) { app_window->ForcedFullscreen(); } + if (options && options->kiosk.get()) + app_window->ForcedFullscreen(); + content::RenderFrameHost* created_frame = app_window->web_contents()->GetMainFrame(); int frame_id = MSG_ROUTING_NONE; @@ -435,15 +499,18 @@ ExtensionFunction::ResponseAction AppWindowCreateFunction::Run() { // SetOnFirstCommitOrWindowClosedCallback() will respond asynchronously. app_window->SetOnFirstCommitOrWindowClosedCallback(base::Bind( &AppWindowCreateFunction::OnAppWindowReadyToCommitFirstNavigationOrClosed, - this, base::Passed(&result_arg))); + this, base::Passed(&result_arg), base::Unretained(created_frame))); + static_cast(created_frame)->in_window_creation_ = true; return RespondLater(); } void AppWindowCreateFunction::OnAppWindowReadyToCommitFirstNavigationOrClosed( ResponseValue result_arg, + content::RenderFrameHost* created_frame, bool ready_to_commit) { DCHECK(!did_respond()); + static_cast(created_frame)->in_window_creation_ = true; if (!ready_to_commit) { Respond(Error(app_window_constants::kPrematureWindowClose)); return; diff --git a/extensions/browser/api/app_window/app_window_api.h b/extensions/browser/api/app_window/app_window_api.h index 829922a3fa188..8858367d0b5aa 100644 --- a/extensions/browser/api/app_window/app_window_api.h +++ b/extensions/browser/api/app_window/app_window_api.h @@ -8,6 +8,10 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/extension_function.h" +namespace content { + class RenderFrameHost; +} + namespace extensions { namespace api { @@ -27,6 +31,7 @@ class AppWindowCreateFunction : public UIThreadExtensionFunction { private: void OnAppWindowReadyToCommitFirstNavigationOrClosed(ResponseValue result_arg, + content::RenderFrameHost* created_frame, bool ready_to_commit); bool GetBoundsSpec( diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc index dd0a04961e100..9dcd40ebeb499 100644 --- a/extensions/browser/api/execute_code_function.cc +++ b/extensions/browser/api/execute_code_function.cc @@ -6,6 +6,7 @@ #define EXTENSIONS_BROWSER_API_EXECUTE_CODE_FUNCTION_IMPL_H_ #include "extensions/browser/api/execute_code_function.h" +#include "content/nw/src/browser/nw_chrome_browser_hooks.h" #include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" @@ -163,9 +164,12 @@ bool ExecuteCodeFunction::Execute(const std::string& code_string, else if (details_->css_origin == api::extension_types::CSS_ORIGIN_AUTHOR) css_origin = CSS_ORIGIN_AUTHOR; + ScriptExecutor::WorldType world_type = details_->main_world.get() && *details_->main_world + ? ScriptExecutor::MAIN_WORLD : ScriptExecutor::ISOLATED_WORLD; + executor->ExecuteScript( host_id_, script_type, code_string, frame_scope, frame_id, - match_about_blank, run_at, ScriptExecutor::ISOLATED_WORLD, + match_about_blank, run_at, world_type, IsWebView() ? ScriptExecutor::WEB_VIEW_PROCESS : ScriptExecutor::DEFAULT_PROCESS, GetWebViewSrc(), file_url_, user_gesture(), css_origin, diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 7fb278f33d2ac..d28717761f8f9 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc @@ -148,7 +148,7 @@ std::unique_ptr ParseContentScript( // if needed. bool allowed_everywhere = extension && extensions::PermissionsData::CanExecuteScriptEverywhere( - extension->id(), extension->location()); + extension->id(), extension->location(), extension->GetType()); for (const std::string& match : script_value.matches) { URLPattern pattern(UserScript::ValidUserScriptSchemes(allowed_everywhere)); if (pattern.Parse(match) != URLPattern::PARSE_SUCCESS) { @@ -798,6 +798,40 @@ WebViewInternalLoadDataWithBaseUrlFunction::Run() { return RespondNow(Error(error)); } +WebViewInternalShowDevToolsFunction::WebViewInternalShowDevToolsFunction() { +} + +WebViewInternalShowDevToolsFunction::~WebViewInternalShowDevToolsFunction() { +} + +ExtensionFunction::ResponseAction +WebViewInternalShowDevToolsFunction::Run() { + std::unique_ptr params( + web_view_internal::ShowDevTools::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + int proc_id = params->proc_id ? *params->proc_id : -1; + int guest_id = params->guest_id ? *params->guest_id : -1; + guest_->ShowDevTools(params->show, proc_id, guest_id); + return RespondNow(NoArguments()); +} + +WebViewInternalInspectElementAtFunction::WebViewInternalInspectElementAtFunction() { +} + +WebViewInternalInspectElementAtFunction::~WebViewInternalInspectElementAtFunction() { +} + +ExtensionFunction::ResponseAction +WebViewInternalInspectElementAtFunction::Run() { + std::unique_ptr params( + web_view_internal::InspectElementAt::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get()); + + guest_->InspectElement(params->x, params->y); + return RespondNow(NoArguments()); +} + WebViewInternalGoFunction::WebViewInternalGoFunction() { } diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h index 15d6c0dfd80b0..24e50f516a7e6 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h @@ -347,6 +347,37 @@ class WebViewInternalLoadDataWithBaseUrlFunction DISALLOW_COPY_AND_ASSIGN(WebViewInternalLoadDataWithBaseUrlFunction); }; +class WebViewInternalShowDevToolsFunction + : public WebViewInternalExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("webViewInternal.showDevTools", UNKNOWN); + + WebViewInternalShowDevToolsFunction(); + + protected: + ~WebViewInternalShowDevToolsFunction() override; + + ResponseAction Run() override; + private: + + DISALLOW_COPY_AND_ASSIGN(WebViewInternalShowDevToolsFunction); +}; + +class WebViewInternalInspectElementAtFunction + : public WebViewInternalExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("webViewInternal.inspectElementAt", UNKNOWN); + + WebViewInternalInspectElementAtFunction(); + + protected: + ~WebViewInternalInspectElementAtFunction() override; + ResponseAction Run() override; + private: + + DISALLOW_COPY_AND_ASSIGN(WebViewInternalInspectElementAtFunction); +}; + class WebViewInternalGoFunction : public WebViewInternalExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("webViewInternal.go", WEBVIEWINTERNAL_GO); diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc index 9b518198481bb..7369f8033a7d1 100644 --- a/extensions/browser/api/runtime/runtime_api.cc +++ b/extensions/browser/api/runtime/runtime_api.cc @@ -4,6 +4,9 @@ #include "extensions/browser/api/runtime/runtime_api.h" +#include "content/nw/src/browser/nw_chrome_browser_hooks.h" +#include "chrome/browser/first_run/first_run.h" + #include #include @@ -220,6 +223,7 @@ RuntimeAPI::~RuntimeAPI() { void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, const Extension* extension) { + bool nw_skip = (extension->id() == nw::GetMainExtensionId() && !first_run::IsChromeFirstRun()); if (!dispatch_chrome_updated_event_) return; @@ -227,7 +231,7 @@ void RuntimeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, - browser_context_, extension->id(), base::Version(), true)); + browser_context_, extension->id(), base::Version(), true, nw_skip)); } void RuntimeAPI::OnExtensionUninstalled( @@ -435,7 +439,7 @@ void RuntimeEventRouter::DispatchOnInstalledEvent( content::BrowserContext* context, const std::string& extension_id, const base::Version& old_version, - bool chrome_updated) { + bool chrome_updated, bool nw_skip) { if (!ExtensionsBrowserClient::Get()->IsValidContext(context)) return; ExtensionSystem* system = ExtensionSystem::Get(context); @@ -467,12 +471,12 @@ void RuntimeEventRouter::DispatchOnInstalledEvent( event_args->Append(std::move(info)); EventRouter* event_router = EventRouter::Get(context); DCHECK(event_router); - std::unique_ptr event(new Event(events::RUNTIME_ON_INSTALLED, - runtime::OnInstalled::kEventName, + std::unique_ptr event(new Event(nw_skip? events::UNKNOWN: events::RUNTIME_ON_INSTALLED, + nw_skip? runtime::OnInstalledNW::kEventName: runtime::OnInstalled::kEventName, std::move(event_args))); event_router->DispatchEventWithLazyListener(extension_id, std::move(event)); - if (old_version.IsValid()) { + if (!nw_skip && old_version.IsValid()) { const Extension* extension = ExtensionRegistry::Get(context)->enabled_extensions().GetByID( extension_id); @@ -584,10 +588,11 @@ void RuntimeAPI::OnExtensionInstalledAndLoaded( content::BrowserContext* browser_context, const Extension* extension, const base::Version& previous_version) { + bool nw_skip = (extension->id() == nw::GetMainExtensionId() && !first_run::IsChromeFirstRun()); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&RuntimeEventRouter::DispatchOnInstalledEvent, - browser_context_, extension->id(), previous_version, false)); + browser_context_, extension->id(), previous_version, false, nw_skip)); } ExtensionFunction::ResponseAction RuntimeGetBackgroundPageFunction::Run() { diff --git a/extensions/browser/api/runtime/runtime_api.h b/extensions/browser/api/runtime/runtime_api.h index 4246125439f02..a90b56da32738 100644 --- a/extensions/browser/api/runtime/runtime_api.h +++ b/extensions/browser/api/runtime/runtime_api.h @@ -192,7 +192,7 @@ class RuntimeEventRouter { static void DispatchOnInstalledEvent(content::BrowserContext* context, const std::string& extension_id, const base::Version& old_version, - bool chrome_updated); + bool chrome_updated, bool nw_skip); // Dispatches the onUpdateAvailable event to the given extension. static void DispatchOnUpdateAvailableEvent( diff --git a/extensions/browser/app_window/app_web_contents_helper.cc b/extensions/browser/app_window/app_web_contents_helper.cc index c0a2fe661b9de..345ec4324a272 100644 --- a/extensions/browser/app_window/app_web_contents_helper.cc +++ b/extensions/browser/app_window/app_web_contents_helper.cc @@ -45,12 +45,28 @@ content::WebContents* AppWebContentsHelper::OpenURLFromTab( // TODO(mihaip): Can we check for user gestures instead? WindowOpenDisposition disposition = params.disposition; if (disposition == WindowOpenDisposition::CURRENT_TAB) { - web_contents_->GetMainFrame()->AddMessageToConsole( + if (GetExtension()->is_nwjs_app()) { + content::NavigationController::LoadURLParams load_url_params(params.url); + load_url_params.source_site_instance = params.source_site_instance; + load_url_params.referrer = params.referrer; + load_url_params.frame_tree_node_id = params.frame_tree_node_id; + load_url_params.redirect_chain = params.redirect_chain; + load_url_params.transition_type = params.transition; + load_url_params.extra_headers = params.extra_headers; + load_url_params.should_replace_current_entry = + params.should_replace_current_entry; + load_url_params.is_renderer_initiated = params.is_renderer_initiated; + + web_contents_->GetController().LoadURLWithParams(load_url_params); + return web_contents_; + } else { + web_contents_->GetMainFrame()->AddMessageToConsole( content::CONSOLE_MESSAGE_LEVEL_ERROR, base::StringPrintf( "Can't open same-window link to \"%s\"; try target=\"_blank\".", params.url.spec().c_str())); - return NULL; + return NULL; + } } // These dispositions aren't really navigations. diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc index 5de2af6210e2f..2082e5fd4f28d 100644 --- a/extensions/browser/app_window/app_window.cc +++ b/extensions/browser/app_window/app_window.cc @@ -4,6 +4,10 @@ #include "extensions/browser/app_window/app_window.h" +#include "components/web_cache/browser/web_cache_manager.h" +#include "content/public/browser/render_process_host.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "base/command_line.h" #include #include @@ -25,8 +29,10 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "content/public/common/media_stream_request.h" #include "extensions/browser/app_window/app_delegate.h" #include "extensions/browser/app_window/app_web_contents_helper.h" @@ -60,6 +66,26 @@ #include "extensions/browser/pref_names.h" #endif +#if defined(OS_MACOSX) +#include "content/public/browser/browser_plugin_guest_manager.h" +#include "extensions/browser/process_manager.h" +#endif + +#include "extensions/browser/extension_host.h" +//#include "extensions/common/extension_messages.h" + +#include "content/public/browser/render_frame_host.h" +#include "content/public/common/renderer_preferences.h" + +#include "extensions/browser/process_manager.h" +#include "extensions/browser/app_window/app_window_contents.h" +#include "extensions/browser/event_router.h" + +#include "content/nw/src/nw_base.h" +#include "content/nw/src/nw_content.h" +#include "content/nw/src/common/shell_switches.h" + + using content::BrowserContext; using content::ConsoleMessageLevel; using content::WebContents; @@ -172,7 +198,11 @@ AppWindow::CreateParams::CreateParams() always_on_top(false), visible_on_all_workspaces(false), show_on_lock_screen(false), - show_in_shelf(false) {} + show_in_shelf(false), + skip_load(false), + show_in_taskbar(true), + new_instance(false) { +} AppWindow::CreateParams::CreateParams(const CreateParams& other) = default; @@ -239,7 +269,7 @@ gfx::Size AppWindow::CreateParams::GetWindowMaximumSize( AppWindow::AppWindow(BrowserContext* context, AppDelegate* app_delegate, const Extension* extension) - : browser_context_(context), + : menu_(nullptr), browser_context_(context), extension_id_(extension->id()), session_id_(SessionID::NewUnique()), app_delegate_(app_delegate), @@ -249,13 +279,44 @@ AppWindow::AppWindow(BrowserContext* context, << "Only off the record window may be opened in the guest mode."; } +void AppWindow::LoadingStateChanged(content::WebContents* source, bool to_different_document) { + base::ListValue args; + if (source->IsLoading()) { + args.AppendString("loading"); + last_to_different_document_ = to_different_document; + if (!to_different_document) //NWJS#5001 + return; + } else { + if (!last_to_different_document_) + return; + args.AppendString("loaded"); + } + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + rfh->Send(new ExtensionMsg_MessageInvoke(rfh->GetRoutingID(), + extension_id(), + "nw.Window", + "LoadingStateChanged", + args)); +} + void AppWindow::Init(const GURL& url, AppWindowContents* app_window_contents, content::RenderFrameHost* creator_frame, const CreateParams& params) { // Initialize the render interface and web contents app_window_contents_.reset(app_window_contents); - app_window_contents_->Initialize(browser_context(), creator_frame, url); + app_window_contents_->Initialize(browser_context(), creator_frame, url, GetExtension(), params.new_instance); + + nw::Package* package = nw::package(); + std::string js_doc_start(params.inject_js_start), js_doc_end(params.inject_js_end); + if (js_doc_start.empty()) + package->root()->GetString(::switches::kmInjectJSDocStart, &js_doc_start); + web_contents()->GetMutableRendererPrefs()->nw_inject_js_doc_start = js_doc_start; + if (js_doc_end.empty()) + package->root()->GetString(::switches::kmInjectJSDocEnd, &js_doc_end); + web_contents()->GetMutableRendererPrefs()->nw_inject_js_doc_end = js_doc_end; + if (!js_doc_start.empty() || !js_doc_end.empty()) + web_contents()->GetRenderViewHost()->SyncRendererPrefs(); initial_url_ = url; @@ -282,8 +343,17 @@ void AppWindow::Init(const GURL& url, // Windows cannot be always-on-top in fullscreen mode for security reasons. cached_always_on_top_ = new_params.always_on_top; - if (new_params.state == ui::SHOW_STATE_FULLSCREEN) - new_params.always_on_top = false; + //if (new_params.state == ui::SHOW_STATE_FULLSCREEN) + // new_params.always_on_top = false; + + title_override_ = new_params.title; + custom_app_icon_ = new_params.icon; + icon_override_ = new_params.icon; + + content::g_support_transparency = !base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kDisableTransparency); + if (content::g_support_transparency) { + content::g_force_cpu_draw = base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kForceCpuDraw); + } requested_alpha_enabled_ = new_params.alpha_enabled; is_ime_window_ = params.is_ime_window; @@ -325,6 +395,9 @@ void AppWindow::Init(const GURL& url, : SHOW_ACTIVE); } + if (!new_params.show_in_taskbar) + SetShowInTaskbar(false); + OnNativeWindowChanged(); ExtensionRegistry::Get(browser_context_)->AddObserver(this); @@ -334,7 +407,8 @@ void AppWindow::Init(const GURL& url, base::Bind(&NativeAppWindow::Close, base::Unretained(native_app_window_.get()))); - app_window_contents_->LoadContents(new_params.creator_process_id); + if (!params.skip_load) + app_window_contents_->LoadContents(new_params.creator_process_id); } AppWindow::~AppWindow() { @@ -372,8 +446,29 @@ void AppWindow::AddNewContents(WebContents* source, bool user_gesture, bool* was_blocked) { DCHECK(new_contents->GetBrowserContext() == browser_context_); - app_delegate_->AddNewContents(browser_context_, std::move(new_contents), - disposition, initial_rect, user_gesture); + const extensions::Extension* extension = GetExtension(); + extensions::AppWindow* app_window = + extensions::AppWindowClient::Get()->CreateAppWindow(browser_context_, extension); + + extensions::AppWindow::CreateParams params; + std::string js_doc_start, js_doc_end; + nw::CalcNewWinParams(new_contents.get(), ¶ms, &js_doc_start, &js_doc_end); + nw::SetCurrentNewWinManifest(base::string16()); + new_contents->GetMutableRendererPrefs()-> + nw_inject_js_doc_start = js_doc_start; + new_contents->GetMutableRendererPrefs()-> + nw_inject_js_doc_end = js_doc_end; + new_contents->GetRenderViewHost()->SyncRendererPrefs(); + + if(initial_rect.width() != 0) { + params.content_spec.bounds = initial_rect; //NWJS#5517 + } + params.skip_load = true; + GURL new_url = new_contents->GetURL(); + app_window->Init(new_url, + new extensions::AppWindowContentsImpl(app_window, std::move(new_contents)), + web_contents()->GetMainFrame(), + params); } content::KeyboardEventProcessingResult AppWindow::PreHandleKeyboardEvent( @@ -405,6 +500,7 @@ content::KeyboardEventProcessingResult AppWindow::PreHandleKeyboardEvent( void AppWindow::HandleKeyboardEvent( WebContents* source, const content::NativeWebKeyboardEvent& event) { +#if 0 // If the window is currently fullscreen and not forced, ESC should leave // fullscreen. If this code is being called for ESC, that means that the // KeyEvent's default behavior was not prevented by the content. @@ -413,7 +509,7 @@ void AppWindow::HandleKeyboardEvent( Restore(); return; } - +#endif native_app_window_->HandleKeyboardEvent(event); } @@ -426,7 +522,41 @@ void AppWindow::RequestToLockMouse(WebContents* web_contents, bool AppWindow::PreHandleGestureEvent(WebContents* source, const blink::WebGestureEvent& event) { - return AppWebContentsHelper::ShouldSuppressGestureEvent(event); +#if defined(OS_MACOSX) + // Disable "smart zoom" (double-tap with two fingers on Mac trackpad) + // for the PDF viewer, otherwise the viewer's controls will be scaled off + // screen. + // TODO(mcnee): Investigate having the PDF viewer handle the gesture + // once it is a service. crbug.com/757541 + if (event.GetType() == blink::WebInputEvent::kGestureDoubleTap) { + content::BrowserPluginGuestManager* guest_manager = + source->GetBrowserContext()->GetGuestManager(); + if (guest_manager) { + const content::WebContents* guest_contents = + guest_manager->GetFullPageGuest(source); + if (guest_contents) { + const extensions::Extension* extension = + extensions::ProcessManager::Get(guest_contents->GetBrowserContext()) + ->GetExtensionForWebContents(guest_contents); + if (extension && extension->id() == extension_misc::kPdfExtensionId) + return true; + } + } + } +#endif // defined(OS_MACOSX) + return false; +} + +// Fix for issue https://github.com/nwjs/nw.js/issues/4992 +// Bounds of dialogs are calcuated based on the bounds of parent window. +// However on Windows, when window is minized, the bounds returned from system +// is empty. +// Implementing `WebContentsDelegate::ActivateContents` in `AppWindow` to +// activate the native window before showing dialog fixes the issue. +void AppWindow::ActivateContents(content::WebContents* contents) { + // Only activate window for NW.js app to avoid side effects to Chrome Apps. + if (GetExtension()->is_nwjs_app()) + native_app_window_->Activate(); } std::unique_ptr AppWindow::RunBluetoothChooser( @@ -476,6 +606,30 @@ void AppWindow::OnReadyToCommitFirstNavigation() { true /* ready_to_commit */)); } +bool AppWindow::NWCanClose(bool user_force) const { + const Extension* extension = GetExtension(); + if (!extension) + return true; + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + EventRouter* event_router = EventRouter::Get(browser_context()); + std::string listener_extension_id; + bool listening_to_close = event_router-> + ExtensionHasEventListener(extension->id(), "nw.Window.onClose", + rfh->GetRenderViewHost()->GetRoutingID(), + &listener_extension_id); + + if (listening_to_close) { + base::ListValue args; + if (user_force) + args.AppendString("quit"); + rfh->Send(new ExtensionMsg_MessageInvoke( + rfh->GetRoutingID(), listener_extension_id, "nw.Window", + "onClose", args)); + return false; + } + return true; +} + void AppWindow::OnNativeClose() { AppWindowRegistry::Get(browser_context_)->RemoveAppWindow(this); @@ -523,9 +677,19 @@ void AppWindow::OnNativeWindowChanged() { SaveWindowPosition(); #if defined(OS_WIN) + if (content::g_support_transparency && requested_alpha_enabled_) { + content::RenderFrameHost* rfh = web_contents()->GetMainFrame(); + content::RenderWidgetHostView* view = rfh->GetRenderViewHost()->GetWidget()->GetView(); + if(view) + view->SetBackgroundColor(native_app_window_->CanHaveAlphaEnabled() ? SK_ColorTRANSPARENT : native_app_window_->ActiveFrameColor()); + } +#if 0 if (cached_always_on_top_ && !IsFullscreen() && !native_app_window_->IsMaximized() && !native_app_window_->IsMinimized()) { +#else + if (cached_always_on_top_) { +#endif UpdateNativeAlwaysOnTop(); } #endif @@ -563,9 +727,11 @@ gfx::Rect AppWindow::GetClientBounds() const { } base::string16 AppWindow::GetTitle() const { + base::string16 override = base::UTF8ToUTF16(title_override_); + const Extension* extension = GetExtension(); if (!extension) - return base::string16(); + return override; // WebContents::GetTitle() will return the page's URL if there's no // specified. However, we'd prefer to show the name of the extension in that @@ -574,12 +740,14 @@ base::string16 AppWindow::GetTitle() const { content::NavigationEntry* entry = web_contents() ? web_contents()->GetController().GetLastCommittedEntry() : nullptr; if (!entry || entry->GetTitle().empty()) { - title = base::UTF8ToUTF16(extension->name()); + title = override.empty() ? base::UTF8ToUTF16(extension->name()) : override; } else { title = web_contents()->GetTitle(); } base::RemoveChars(title, base::ASCIIToUTF16("\n"), &title); - return title; + if (!title.empty()) + return title; + return override; } void AppWindow::SetAppIconUrl(const GURL& url) { @@ -665,6 +833,10 @@ void AppWindow::Restore() { } } +void AppWindow::SetShowInTaskbar(bool show) { + GetBaseWindow()->SetShowInTaskbar(show); +} + void AppWindow::OSFullscreen() { SetFullscreen(FULLSCREEN_TYPE_OS, true); } @@ -722,7 +894,7 @@ void AppWindow::SetAlwaysOnTop(bool always_on_top) { // As a security measure, do not allow fullscreen windows or windows that // overlap the taskbar to be on top. The property will be applied when the // window exits fullscreen and moves away from the taskbar. - if (!IsFullscreen() && !IntersectsWithTaskbar()) + //if (!IsFullscreen() && !IntersectsWithTaskbar()) native_app_window_->SetAlwaysOnTop(always_on_top); OnNativeWindowChanged(); @@ -738,6 +910,8 @@ void AppWindow::RestoreAlwaysOnTop() { void AppWindow::GetSerializedState(base::DictionaryValue* properties) const { DCHECK(properties); + properties->SetBoolean("resizable", + native_app_window_->IsResizable()); properties->SetBoolean("fullscreen", native_app_window_->IsFullscreenOrPending()); properties->SetBoolean("minimized", native_app_window_->IsMinimized()); @@ -847,6 +1021,9 @@ bool AppWindow::IntersectsWithTaskbar() const { void AppWindow::UpdateNativeAlwaysOnTop() { DCHECK(cached_always_on_top_); +#if 1 + native_app_window_->SetAlwaysOnTop(true); +#else bool is_on_top = native_app_window_->IsAlwaysOnTop(); bool fullscreen = IsFullscreen(); bool intersects_taskbar = IntersectsWithTaskbar(); @@ -860,6 +1037,7 @@ void AppWindow::UpdateNativeAlwaysOnTop() { // always-on-top. native_app_window_->SetAlwaysOnTop(true); } +#endif } void AppWindow::CloseContents(WebContents* contents) { @@ -867,7 +1045,7 @@ void AppWindow::CloseContents(WebContents* contents) { } bool AppWindow::ShouldSuppressDialogs(WebContents* source) { - return true; + return false; } content::ColorChooser* AppWindow::OpenColorChooser( @@ -1090,4 +1268,18 @@ SkRegion* AppWindow::RawDraggableRegionsToSkRegion( return sk_region; } +content::JavaScriptDialogManager* AppWindow::GetJavaScriptDialogManager( + WebContents* source) { + ExtensionHost* host = ProcessManager::Get(browser_context()) + ->GetBackgroundHostForExtension(extension_id()); + return host->GetJavaScriptDialogManager(source); +} + +void AppWindow::OnVisibilityChanged(content::Visibility visibility) { + if (visibility == content::Visibility::VISIBLE) { + web_cache::WebCacheManager::GetInstance()->ObserveActivity( + web_contents()->GetMainFrame()->GetProcess()->GetID()); + } +} + } // namespace extensions diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h index dff33dc639e50..e9be1a43b7c06 100644 --- a/extensions/browser/app_window/app_window.h +++ b/extensions/browser/app_window/app_window.h @@ -37,6 +37,10 @@ class RenderFrameHost; class WebContents; } +namespace nw { +class Menu; +} + namespace extensions { class AppDelegate; @@ -59,7 +63,9 @@ class AppWindowContents { // Called to initialize the WebContents, before the app window is created. virtual void Initialize(content::BrowserContext* context, content::RenderFrameHost* creator_frame, - const GURL& url) = 0; + const GURL& url, + const Extension* extension, + bool skip_blocking_parser) = 0; // Called to load the contents, after the app window is created. virtual void LoadContents(int32_t creator_process_id) = 0; @@ -100,6 +106,12 @@ class AppWindow : public content::WebContentsDelegate, FRAME_NONE, // Frameless window. }; + enum Position { + POS_NONE, + POS_CENTER, + POS_MOUSE, + }; + enum FullscreenType { // Not fullscreen. FULLSCREEN_TYPE_NONE = 0, @@ -199,6 +211,19 @@ class AppWindow : public content::WebContentsDelegate, // Icon URL to be used for setting the window icon. GURL window_icon_url; + bool skip_load; + + bool show_in_taskbar; + bool new_instance; + + Position position; + + std::string title; + + std::string inject_js_start, inject_js_end; + + gfx::Image icon; + // The API enables developers to specify content or window bounds. This // function combines them into a single, constrained window size. gfx::Rect GetInitialWindowBounds(const gfx::Insets& frame_insets) const; @@ -242,14 +267,19 @@ class AppWindow : public content::WebContentsDelegate, } content::BrowserContext* browser_context() const { return browser_context_; } const gfx::Image& custom_app_icon() const { return custom_app_icon_; } + const gfx::Image& icon_override() const { return icon_override_; } const GURL& app_icon_url() const { return app_icon_url_; } const GURL& initial_url() const { return initial_url_; } bool is_hidden() const { return is_hidden_; } - + const std::string& title_override() const { return title_override_; } + void set_title_override(const std::string& title) { title_override_ = title; } + const Extension* GetExtension() const; NativeAppWindow* GetBaseWindow(); gfx::NativeWindow GetNativeWindow(); + bool NWCanClose(bool user_force = false) const; + // Returns the bounds that should be reported to the renderer. gfx::Rect GetClientBounds() const; @@ -320,6 +350,8 @@ class AppWindow : public content::WebContentsDelegate, void Minimize(); void Restore(); + void SetShowInTaskbar(bool); + // Transitions to OS fullscreen. See FULLSCREEN_TYPE_OS for more details. void OSFullscreen(); @@ -384,6 +416,7 @@ class AppWindow : public content::WebContentsDelegate, std::unique_ptr<AppWindowContents> contents) { app_window_contents_ = std::move(contents); } + nw::Menu* menu_; protected: ~AppWindow() override; @@ -393,6 +426,10 @@ class AppWindow : public content::WebContentsDelegate, friend class PlatformAppBrowserTest; // content::WebContentsDelegate implementation. + void LoadingStateChanged(content::WebContents* source, + bool to_different_document) override; + content::JavaScriptDialogManager* GetJavaScriptDialogManager( + content::WebContents* source) override; void CloseContents(content::WebContents* contents) override; bool ShouldSuppressDialogs(content::WebContents* source) override; content::ColorChooser* OpenColorChooser( @@ -435,6 +472,7 @@ class AppWindow : public content::WebContentsDelegate, content::KeyboardEventProcessingResult PreHandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) override; + void ActivateContents(content::WebContents* contents) override; void HandleKeyboardEvent( content::WebContents* source, const content::NativeWebKeyboardEvent& event) override; @@ -452,6 +490,7 @@ class AppWindow : public content::WebContentsDelegate, bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; void RenderViewCreated(content::RenderViewHost* render_view_host) override; + void OnVisibilityChanged(content::Visibility visibility) override; // ExtensionFunctionDispatcher::Delegate implementation. WindowController* GetExtensionWindowController() const override; @@ -522,6 +561,8 @@ class AppWindow : public content::WebContentsDelegate, // not own this object. content::BrowserContext* browser_context_; + std::string title_override_; + const std::string extension_id_; // Identifier that is used when saving and restoring geometry for this @@ -533,6 +574,7 @@ class AppWindow : public content::WebContentsDelegate, // Custom icon shown in the task bar or in Chrome OS shelf. gfx::Image custom_app_icon_; + gfx::Image icon_override_; // Icon URL to be used for setting the app icon. If not empty, app_icon_ will // be fetched and set using this URL. @@ -573,6 +615,8 @@ class AppWindow : public content::WebContentsDelegate, // Whether |is_ime_window| was set in the CreateParams. bool is_ime_window_ = false; + bool last_to_different_document_ = false; + // Whether |show_on_lock_screen| was set in the CreateParams. bool show_on_lock_screen_ = false; diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc index 9285be936234c..ee1e3895d9700 100644 --- a/extensions/browser/app_window/app_window_contents.cc +++ b/extensions/browser/app_window/app_window_contents.cc @@ -4,6 +4,8 @@ #include "extensions/browser/app_window/app_window_contents.h" +#include "content/browser/web_contents/web_contents_impl.h" + #include <memory> #include <string> #include <utility> @@ -19,26 +21,40 @@ #include "extensions/browser/app_window/native_app_window.h" #include "extensions/common/extension_messages.h" +#include "content/nw/src/nw_content.h" + namespace extensions { -AppWindowContentsImpl::AppWindowContentsImpl(AppWindow* host) : host_(host) {} +AppWindowContentsImpl::AppWindowContentsImpl(AppWindow* host, std::unique_ptr<content::WebContents> web_contents) + :host_(host), web_contents_(std::move(web_contents)) {} AppWindowContentsImpl::~AppWindowContentsImpl() {} void AppWindowContentsImpl::Initialize(content::BrowserContext* context, content::RenderFrameHost* creator_frame, - const GURL& url) { + const GURL& url, + const Extension* extension, + bool skip_blocking_parser) { url_ = url; + bool new_site = url.SchemeIs("chrome") || !nw::PinningRenderer(); content::WebContents::CreateParams create_params( - context, creator_frame->GetSiteInstance()); + //NWJS#5163: fix regression + context, nw::PinningRenderer() ? creator_frame->GetSiteInstance() : content::SiteInstance::CreateForURL(context, url_)); create_params.opener_render_process_id = creator_frame->GetProcess()->GetID(); create_params.opener_render_frame_id = creator_frame->GetRoutingID(); - web_contents_ = content::WebContents::Create(create_params); + if (!web_contents_) + web_contents_ = content::WebContents::Create(create_params); + static_cast<content::WebContentsImpl*>(web_contents_.get())->SetSkipBlockingParser(skip_blocking_parser || new_site); Observe(web_contents_.get()); - web_contents_->GetMutableRendererPrefs()-> - browser_handles_all_top_level_requests = true; + content::RendererPreferences* render_prefs = + web_contents_->GetMutableRendererPrefs(); + if (!extension || !extension->is_nwjs_app()) + render_prefs->browser_handles_all_top_level_requests = true; + std::string user_agent; + if (nw::GetUserAgentFromManifest(&user_agent)) + render_prefs->user_agent_override = user_agent; web_contents_->GetRenderViewHost()->SyncRendererPrefs(); } diff --git a/extensions/browser/app_window/app_window_contents.h b/extensions/browser/app_window/app_window_contents.h index 73bbd19293b5b..692a54027d98b 100644 --- a/extensions/browser/app_window/app_window_contents.h +++ b/extensions/browser/app_window/app_window_contents.h @@ -17,6 +17,7 @@ namespace content { class BrowserContext; class RenderFrameHost; +class WebContents; } namespace extensions { @@ -29,13 +30,15 @@ struct DraggableRegion; class AppWindowContentsImpl : public AppWindowContents, public content::WebContentsObserver { public: - explicit AppWindowContentsImpl(AppWindow* host); + explicit AppWindowContentsImpl(AppWindow* host, std::unique_ptr<content::WebContents> web_contents = nullptr); ~AppWindowContentsImpl() override; // AppWindowContents void Initialize(content::BrowserContext* context, content::RenderFrameHost* creator_frame, - const GURL& url) override; + const GURL& url, + const Extension* extension, + bool skip_blocking_parser) override; void LoadContents(int32_t creator_process_id) override; void NativeWindowChanged(NativeAppWindow* native_app_window) override; void NativeWindowClosed(bool send_onclosed) override; @@ -53,6 +56,7 @@ class AppWindowContentsImpl : public AppWindowContents, AppWindow* host_; // This class is owned by |host_| GURL url_; + std::unique_ptr<content::WebContents> web_contents_; DISALLOW_COPY_AND_ASSIGN(AppWindowContentsImpl); diff --git a/extensions/browser/app_window/app_window_registry.cc b/extensions/browser/app_window/app_window_registry.cc index da30c950c0d3e..8614686e11848 100644 --- a/extensions/browser/app_window/app_window_registry.cc +++ b/extensions/browser/app_window/app_window_registry.cc @@ -109,12 +109,13 @@ AppWindowRegistry::AppWindowList AppWindowRegistry::GetAppWindowsForApp( return app_windows; } -void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string& app_id) { +void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string& app_id, bool user_force) { const AppWindowList windows = GetAppWindowsForApp(app_id); for (AppWindowRegistry::const_iterator it = windows.begin(); it != windows.end(); ++it) { - (*it)->GetBaseWindow()->Close(); + if ((*it)->NWCanClose(user_force)) + (*it)->GetBaseWindow()->Close(); } } diff --git a/extensions/browser/app_window/app_window_registry.h b/extensions/browser/app_window/app_window_registry.h index 1f86e619de63e..d46191fb138b6 100644 --- a/extensions/browser/app_window/app_window_registry.h +++ b/extensions/browser/app_window/app_window_registry.h @@ -82,7 +82,7 @@ class AppWindowRegistry : public KeyedService, const AppWindowList& app_windows() const { return app_windows_; } // Close all app windows associated with an app. - void CloseAllAppWindowsForApp(const std::string& app_id); + void CloseAllAppWindowsForApp(const std::string& app_id, bool user_force = false); // Helper functions to find app windows with particular attributes. AppWindow* GetAppWindowForWebContents( diff --git a/extensions/browser/app_window/native_app_window.h b/extensions/browser/app_window/native_app_window.h index 0ae528f6f71b6..f76efa0b56b66 100644 --- a/extensions/browser/app_window/native_app_window.h +++ b/extensions/browser/app_window/native_app_window.h @@ -35,6 +35,8 @@ class NativeAppWindow : public ui::BaseWindow, // |fullscreen_types| is a bit field of AppWindow::FullscreenType. virtual void SetFullscreen(int fullscreen_types) = 0; + virtual void SetResizable(bool flag) = 0; + virtual bool IsResizable() const = 0; // Returns whether the window is fullscreen or about to enter fullscreen. virtual bool IsFullscreenOrPending() const = 0; @@ -80,6 +82,8 @@ class NativeAppWindow : public ui::BaseWindow, virtual void ShowWithApp() = 0; virtual void HideWithApp() = 0; + virtual void SetShowInTaskbar(bool) = 0; + // Returns the minimum size constraints of the content. virtual gfx::Size GetContentMinimumSize() const = 0; diff --git a/extensions/browser/app_window/test_app_window_contents.cc b/extensions/browser/app_window/test_app_window_contents.cc index d299819d4ba4e..360beb382da5d 100644 --- a/extensions/browser/app_window/test_app_window_contents.cc +++ b/extensions/browser/app_window/test_app_window_contents.cc @@ -17,7 +17,8 @@ TestAppWindowContents::~TestAppWindowContents() { void TestAppWindowContents::Initialize(content::BrowserContext* context, content::RenderFrameHost* creator_frame, - const GURL& url) {} + const GURL& url, + const Extension* extension, bool skip_blocking_parser) {} void TestAppWindowContents::LoadContents(int32_t creator_process_id) {} diff --git a/extensions/browser/app_window/test_app_window_contents.h b/extensions/browser/app_window/test_app_window_contents.h index 5b039d23cce0a..448e9d8acc137 100644 --- a/extensions/browser/app_window/test_app_window_contents.h +++ b/extensions/browser/app_window/test_app_window_contents.h @@ -28,7 +28,8 @@ class TestAppWindowContents : public AppWindowContents { // apps:AppWindowContents: void Initialize(content::BrowserContext* context, content::RenderFrameHost* creator_frame, - const GURL& url) override; + const GURL& url, + const Extension* extension, bool skip_blocking_parser) override; void LoadContents(int32_t creator_process_id) override; void NativeWindowChanged(NativeAppWindow* native_app_window) override; void NativeWindowClosed(bool send_onclosed) override; diff --git a/extensions/browser/content_hash_fetcher.cc b/extensions/browser/content_hash_fetcher.cc index 05158aee89790..6b66e84bf8d37 100644 --- a/extensions/browser/content_hash_fetcher.cc +++ b/extensions/browser/content_hash_fetcher.cc @@ -60,6 +60,7 @@ void ContentHashFetcher::OnURLFetchComplete(const net::URLFetcher* source) { } void ContentHashFetcher::Start(HashFetcherCallback hash_fetcher_callback) { +#if 0 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); hash_fetcher_callback_ = std::move(hash_fetcher_callback); @@ -96,6 +97,7 @@ void ContentHashFetcher::Start(HashFetcherCallback hash_fetcher_callback) { net::LOAD_DISABLE_CACHE); url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); url_fetcher_->Start(); +#endif } ContentHashFetcher::~ContentHashFetcher() { diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc index 6ac100fc31229..3700a29a1d728 100644 --- a/extensions/browser/content_verifier.cc +++ b/extensions/browser/content_verifier.cc @@ -28,6 +28,10 @@ #include "extensions/common/manifest_handlers/background_info.h" #include "extensions/common/manifest_handlers/content_scripts_handler.h" +#include "base/files/file_util.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/thread_restrictions.h" + namespace extensions { namespace { @@ -424,7 +428,7 @@ ContentVerifyJob* ContentVerifier::CreateJobFor( // a cache of ContentHashReader's that we hold onto past the end of each job. return new ContentVerifyJob( extension_id, data->version, extension_root, normalized_unix_path, - base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id)); + base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id, relative_path)); } void ContentVerifier::GetContentHash( @@ -461,19 +465,70 @@ void ContentVerifier::GetContentHash( std::move(callback)); } +void ContentVerifier::OnHashReady(const std::string& extension_id, + const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> verify_job) { + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::Bind(&ContentVerifier::OpenFile, this, extension_root, relative_path, verify_job), + base::Bind(&ContentVerifier::OnFileReady, this, extension_root, relative_path, verify_job)); +} + +void ContentVerifier::OpenFile(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job) { + job->file_.Initialize(extension_root.Append(relative_path), base::File::FLAG_OPEN | base::File::FLAG_READ); +} + +void ContentVerifier::OnFileReady(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job) { + if (!job->file_.IsValid()) + job->DoneReading(); + + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::Bind(&ContentVerifier::ReadFile, this, extension_root, relative_path, job), + base::Bind(&ContentVerifier::BytesRead, this, extension_root, relative_path, job)); +} +void ContentVerifier::ReadFile(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job) { + job->len_ = job->file_.ReadAtCurrentPos(job->buf_, 32768); + if (job->len_ <= 0) + job->file_.Close(); +} + +void ContentVerifier::BytesRead(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job) { + if (job->len_ <= 0) { + job->DoneReading(); + } else { + job->BytesRead(job->len_, job->buf_); + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::Bind(&ContentVerifier::ReadFile, this, extension_root, relative_path, job), + base::Bind(&ContentVerifier::BytesRead, this, extension_root, relative_path, job)); + } +} + void ContentVerifier::VerifyFailed(const ExtensionId& extension_id, - ContentVerifyJob::FailureReason reason) { + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr<ContentVerifyJob> verify_job) { if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id, - reason)); + base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id, relative_path, + reason, verify_job)); return; } if (shutdown_on_ui_) return; - VLOG(1) << "VerifyFailed " << extension_id << " reason:" << reason; + VLOG(1) << "VerifyFailed " << extension_id << " reason:" << reason << " " << relative_path.AsUTF8Unsafe(); DCHECK_NE(ContentVerifyJob::NONE, reason); ExtensionRegistry* registry = ExtensionRegistry::Get(context_); @@ -484,6 +539,12 @@ void ContentVerifier::VerifyFailed(const ExtensionId& extension_id, return; ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension); + if (mode < ContentVerifierDelegate::ENFORCE) { + if (!verify_job->success_callback().is_null()) + verify_job->success_callback().Run(); + return; + } + // If the failure was due to hashes missing, only "enforce_strict" would // disable the extension, but not "enforce". if (reason == ContentVerifyJob::MISSING_ALL_HASHES && @@ -491,7 +552,7 @@ void ContentVerifier::VerifyFailed(const ExtensionId& extension_id, return; } - delegate_->VerifyFailed(extension_id, reason); + delegate_->VerifyFailed(extension_id, relative_path, reason, verify_job); } void ContentVerifier::OnExtensionLoaded( @@ -572,7 +633,7 @@ void ContentVerifier::OnFetchComplete( if (!did_hash_mismatch) return; - VerifyFailed(extension_id, ContentVerifyJob::HASH_MISMATCH); + VerifyFailed(extension_id, base::FilePath(), ContentVerifyJob::HASH_MISMATCH, nullptr); } ContentHash::FetchParams ContentVerifier::GetFetchParams( diff --git a/extensions/browser/content_verifier.h b/extensions/browser/content_verifier.h index 20edcda576393..5964c48660686 100644 --- a/extensions/browser/content_verifier.h +++ b/extensions/browser/content_verifier.h @@ -70,7 +70,25 @@ class ContentVerifier : public base::RefCountedThreadSafe<ContentVerifier>, // Called (typically by a verification job) to indicate that verification // failed while reading some file in |extension_id|. void VerifyFailed(const ExtensionId& extension_id, - ContentVerifyJob::FailureReason reason); + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr<ContentVerifyJob> verify_job); + void OnHashReady(const std::string& extension_id, + const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> verify_job); + void BytesRead(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job); + void ReadFile(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job); + void OpenFile(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job); + void OnFileReady(const base::FilePath& extension_root, + const base::FilePath& relative_path, + scoped_refptr<ContentVerifyJob> job); // ExtensionRegistryObserver interface void OnExtensionLoaded(content::BrowserContext* browser_context, diff --git a/extensions/browser/content_verifier/content_hash.cc b/extensions/browser/content_verifier/content_hash.cc index 87a0a1a387945..d037ba2deda8b 100644 --- a/extensions/browser/content_verifier/content_hash.cc +++ b/extensions/browser/content_verifier/content_hash.cc @@ -50,7 +50,7 @@ std::unique_ptr<VerifiedContents> GetVerifiedContents( base::FilePath verified_contents_path = file_util::GetVerifiedContentsPath(key.extension_root); if (!verified_contents->InitFrom(verified_contents_path)) { - if (delete_invalid_file && + if (delete_invalid_file && false && !base::DeleteFile(verified_contents_path, false)) { LOG(WARNING) << "Failed to delete " << verified_contents_path.value(); } diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc index e429c6691b1fb..879ffb9e043df 100644 --- a/extensions/browser/content_verifier/test_utils.cc +++ b/extensions/browser/content_verifier/test_utils.cc @@ -158,7 +158,9 @@ std::set<base::FilePath> MockContentVerifierDelegate::GetBrowserImagePaths( void MockContentVerifierDelegate::VerifyFailed( const ExtensionId& extension_id, - ContentVerifyJob::FailureReason reason) { + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr<ContentVerifyJob> verify_job) { ADD_FAILURE() << "Unexpected call for this test"; } diff --git a/extensions/browser/content_verifier/test_utils.h b/extensions/browser/content_verifier/test_utils.h index 9c83d4ead23ee..f9667a149ee43 100644 --- a/extensions/browser/content_verifier/test_utils.h +++ b/extensions/browser/content_verifier/test_utils.h @@ -119,7 +119,9 @@ class MockContentVerifierDelegate : public ContentVerifierDelegate { std::set<base::FilePath> GetBrowserImagePaths( const extensions::Extension* extension) override; void VerifyFailed(const ExtensionId& extension_id, - ContentVerifyJob::FailureReason reason) override; + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr<ContentVerifyJob> verify_job) override; void Shutdown() override; private: diff --git a/extensions/browser/content_verifier_delegate.h b/extensions/browser/content_verifier_delegate.h index 5bbe1f7a99045..73dddb954e561 100644 --- a/extensions/browser/content_verifier_delegate.h +++ b/extensions/browser/content_verifier_delegate.h @@ -66,7 +66,9 @@ class ContentVerifierDelegate { // Called when the content verifier detects that a read of a file inside // an extension did not match its expected hash. virtual void VerifyFailed(const std::string& extension_id, - ContentVerifyJob::FailureReason reason) = 0; + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason reason, + scoped_refptr<ContentVerifyJob> verify_job) = 0; // Called when ExtensionSystem is shutting down. virtual void Shutdown() = 0; diff --git a/extensions/browser/content_verify_job.cc b/extensions/browser/content_verify_job.cc index 01cf9616b1eef..1af4daee0b23f 100644 --- a/extensions/browser/content_verify_job.cc +++ b/extensions/browser/content_verify_job.cc @@ -58,11 +58,35 @@ ContentVerifyJob::ContentVerifyJob(const ExtensionId& extension_id, extension_root_(extension_root), relative_path_(relative_path), failure_callback_(std::move(failure_callback)), - failed_(false) {} + failed_(false), len_(0), buf_(nullptr) { + buf_ = new char[32768]; +} + +ContentVerifyJob::ContentVerifyJob(ContentHashReader* hash_reader, + const ContentVerifierKey& key, + FailureCallback failure_callback, + const ReadyCallback& ready_callback) + : done_reading_(false), + hashes_ready_(false), + total_bytes_read_(0), + current_block_(0), + current_hash_byte_count_(0), + hash_reader_(hash_reader), + failure_callback_(std::move(failure_callback)), + ready_callback_(ready_callback), + failed_(false), + len_(0), + buf_(nullptr) +{ + buf_ = new char[32768]; +} + ContentVerifyJob::~ContentVerifyJob() { UMA_HISTOGRAM_COUNTS("ExtensionContentVerifyJob.TimeSpentUS", time_spent_.InMicroseconds()); + delete[] buf_; + buf_ = nullptr; } void ContentVerifyJob::Start(ContentVerifier* verifier) { @@ -110,6 +134,8 @@ void ContentVerifyJob::DoneReading() { g_content_verify_job_test_observer->JobFinished(extension_id_, relative_path_, NONE); } + else if (!success_callback_.is_null()) + success_callback_.Run(); } } @@ -208,6 +234,8 @@ void ContentVerifyJob::OnHashesReady( g_content_verify_job_test_observer->JobFinished(extension_id_, relative_path_, NONE); } + if (!success_callback_.is_null()) + success_callback_.Run(); return; } DispatchFailureCallback(NO_HASHES_FOR_FILE); @@ -233,6 +261,9 @@ void ContentVerifyJob::OnHashesReady( relative_path_, NONE); } } + if (!ready_callback_.is_null()) { + ready_callback_.Run(this); + } } // static @@ -255,7 +286,7 @@ void ContentVerifyJob::DispatchFailureCallback(FailureReason reason) { if (!failure_callback_.is_null()) { VLOG(1) << "job failed for " << extension_id_ << " " << relative_path_.MaybeAsASCII() << " reason:" << reason; - std::move(failure_callback_).Run(reason); + std::move(failure_callback_).Run(reason, this); } if (g_content_verify_job_test_observer) { g_content_verify_job_test_observer->JobFinished(extension_id_, diff --git a/extensions/browser/content_verify_job.h b/extensions/browser/content_verify_job.h index 9a1be9971be95..7890d92a387b3 100644 --- a/extensions/browser/content_verify_job.h +++ b/extensions/browser/content_verify_job.h @@ -9,6 +9,7 @@ #include <memory> #include <string> +#include "base/files/file.h" #include "base/callback.h" #include "base/files/file_path.h" @@ -54,7 +55,9 @@ class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { FAILURE_REASON_MAX }; - using FailureCallback = base::OnceCallback<void(FailureReason)>; + using FailureCallback = base::OnceCallback<void(FailureReason, scoped_refptr<ContentVerifyJob>)>; + using ReadyCallback = base::Callback<void(scoped_refptr<ContentVerifyJob>)>; + using SuccessCallback = base::Callback<void(void)>; // The |failure_callback| will be called at most once if there was a failure. ContentVerifyJob(const ExtensionId& extension_id, @@ -63,6 +66,11 @@ class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { const base::FilePath& relative_path, FailureCallback failure_callback); + ContentVerifyJob(ContentHashReader* hash_reader, + const ContentVerifierKey& content_verifier_key, + FailureCallback failure_callback, + const ReadyCallback& ready_callback); + // This begins the process of getting expected hashes, so it should be called // as early as possible. void Start(ContentVerifier* verifier); @@ -78,6 +86,9 @@ class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { // Call once when finished adding bytes via BytesRead. void DoneReading(); + void SetSuccessCallback(const SuccessCallback& success_callback) { success_callback_ = success_callback; } + const SuccessCallback& success_callback() { return success_callback_; } + class TestObserver { public: virtual void JobStarted(const ExtensionId& extension_id, @@ -153,6 +164,8 @@ class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { // Called once if verification fails. FailureCallback failure_callback_; + ReadyCallback ready_callback_; + SuccessCallback success_callback_; // Set to true if we detected a mismatch and called the failure callback. bool failed_; @@ -160,6 +173,12 @@ class ContentVerifyJob : public base::RefCountedThreadSafe<ContentVerifyJob> { // Used to synchronize all public methods. base::Lock lock_; + public: + int len_; + char* buf_; + base::File file_; + + DISALLOW_COPY_AND_ASSIGN(ContentVerifyJob); }; diff --git a/extensions/browser/event_listener_map.cc b/extensions/browser/event_listener_map.cc index 85e9f15526480..8aaf69f028e00 100644 --- a/extensions/browser/event_listener_map.cc +++ b/extensions/browser/event_listener_map.cc @@ -173,16 +173,28 @@ bool EventListenerMap::HasListenerForEvent( bool EventListenerMap::HasListenerForExtension( const std::string& extension_id, - const std::string& event_name) const { + const std::string& event_name, int instance_id, std::string* out_extension_id) const { auto it = listeners_.find(event_name); if (it == listeners_.end()) return false; + EventListener* ret = nullptr; for (const auto& listener_to_search : it->second) { - if (listener_to_search->extension_id() == extension_id) - return true; + if (listener_to_search->extension_id() == extension_id || + listener_to_search->extension_id().empty()) { + int id = -1; + if (instance_id < 0) + ret = listener_to_search.get(); + if (listener_to_search->filter() && + listener_to_search->filter()->GetInteger("instanceId", &id) && id == instance_id) + ret = listener_to_search.get(); + } } - return false; + if (!ret) + return false; + if (out_extension_id) + *out_extension_id = ret->extension_id(); + return true; } bool EventListenerMap::HasListener(const EventListener* listener) const { diff --git a/extensions/browser/event_listener_map.h b/extensions/browser/event_listener_map.h index 0637179423134..5a8779d1895ea 100644 --- a/extensions/browser/event_listener_map.h +++ b/extensions/browser/event_listener_map.h @@ -172,7 +172,9 @@ class EventListenerMap { // Returns true if there are any listeners on |event_name| from // |extension_id|. bool HasListenerForExtension(const std::string& extension_id, - const std::string& event_name) const; + const std::string& event_name, + int instance_id = -1, + std::string* out_extension_id = nullptr) const; // Returns true if this map contains an EventListener that .Equals() // |listener|. diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index 3bde19d934943..ca12e42b7d6da 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc @@ -393,8 +393,10 @@ bool EventRouter::HasEventListener(const std::string& event_name) const { bool EventRouter::ExtensionHasEventListener( const std::string& extension_id, - const std::string& event_name) const { - return listeners_.HasListenerForExtension(extension_id, event_name); + const std::string& event_name, + int instance_id, + std::string* out_extension_id) const { + return listeners_.HasListenerForExtension(extension_id, event_name, instance_id, out_extension_id); } std::set<std::string> EventRouter::GetRegisteredEvents( @@ -615,7 +617,7 @@ void EventRouter::DispatchEventToProcess( ExtensionAPI::GetSharedInstance()->IsAvailable( event->event_name, extension, target_context, listener_url, CheckAliasStatus::ALLOWED); - if (!availability.is_available()) { + if (!availability.is_available() && !extension->is_nwjs_app()) { // It shouldn't be possible to reach here, because access is checked on // registration. However, for paranoia, check on dispatch as well. NOTREACHED() << "Trying to dispatch event " << event->event_name @@ -903,12 +905,14 @@ Event::Event(events::HistogramValue histogram_value, user_gesture(user_gesture), filter_info(filter_info) { DCHECK(event_args); +#if 0 DCHECK_NE(events::UNKNOWN, histogram_value) << "events::UNKNOWN cannot be used as a histogram value.\n" << "If this is a test, use events::FOR_TEST.\n" << "If this is production code, it is important that you use a realistic " << "value so that we can accurately track event usage. " << "See extension_event_histogram_value.h for inspiration."; +#endif } Event::~Event() {} diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h index 512ff10bfccce..d367bc76e7977 100644 --- a/extensions/browser/event_router.h +++ b/extensions/browser/event_router.h @@ -197,7 +197,9 @@ class EventRouter : public KeyedService, // Returns true if the extension is listening to the given event. // (virtual for testing only.) virtual bool ExtensionHasEventListener(const std::string& extension_id, - const std::string& event_name) const; + const std::string& event_name, + int instance_id = -1, + std::string* out_extension_id = nullptr) const; // Broadcasts an event to every listener registered for that event. virtual void BroadcastEvent(std::unique_ptr<Event> event); @@ -392,7 +394,7 @@ struct Event { // If non-null, then the event will not be sent to other BrowserContexts // unless the extension has permission (e.g. incognito tab update -> normal // tab only works if extension is allowed incognito access). - content::BrowserContext* const restrict_to_browser_context; + content::BrowserContext* restrict_to_browser_context; // If not empty, the event is only sent to extensions with host permissions // for this url. diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc index 2c14386244ff3..9ec19750d44ec 100644 --- a/extensions/browser/extension_function.cc +++ b/extensions/browser/extension_function.cc @@ -4,6 +4,9 @@ #include "extensions/browser/extension_function.h" +#include "content/public/browser/interstitial_page.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include <utility> #include "base/logging.h" @@ -303,6 +306,10 @@ ExtensionFunction::ExtensionFunction() ExtensionFunction::~ExtensionFunction() { } +bool ExtensionFunction::RunNWSync(base::ListValue* response, std::string* error) { + return false; +} + UIThreadExtensionFunction* ExtensionFunction::AsUIThreadExtensionFunction() { return NULL; } @@ -565,8 +572,12 @@ void UIThreadExtensionFunction::SetRenderFrameHost( } content::WebContents* UIThreadExtensionFunction::GetSenderWebContents() { - return render_frame_host_ ? + content::WebContents* ret = render_frame_host_ ? content::WebContents::FromRenderFrameHost(render_frame_host_) : nullptr; + if (ret) + return ret; + content::InterstitialPage* page = static_cast<content::RenderFrameHostImpl*>(render_frame_host_)->delegate()->GetAsInterstitialPage(); + return page->GetWebContents(); } void UIThreadExtensionFunction::OnResponded() { @@ -623,3 +634,35 @@ ExtensionFunction::ScopedUserGestureForTests::ScopedUserGestureForTests() { ExtensionFunction::ScopedUserGestureForTests::~ScopedUserGestureForTests() { UserGestureForTests::GetInstance()->DecrementCount(); } + +NWSyncExtensionFunction::NWSyncExtensionFunction() { +} + +NWSyncExtensionFunction::~NWSyncExtensionFunction() { +} + +ExtensionFunction::ResponseAction NWSyncExtensionFunction::Run() { + NOTREACHED() << "NWSyncExtensionFunction::Run"; + return RespondNow(ArgumentList(std::move(results_))); +} + +// static +bool NWSyncExtensionFunction::ValidationFailure( + NWSyncExtensionFunction* function) { + return false; +} + +void NWSyncExtensionFunction::SetError(const std::string& error) { + error_ = error; +} + +void NWSyncExtensionFunction::SetResult(std::unique_ptr<base::Value> result) { + results_.reset(new base::ListValue()); + results_->Append(std::move(result)); +} + +void NWSyncExtensionFunction::SetResultList( + std::unique_ptr<base::ListValue> results) { + results_ = std::move(results); +} + diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h index 0b70be6cfa6ec..e243618789d08 100644 --- a/extensions/browser/extension_function.h +++ b/extensions/browser/extension_function.h @@ -212,6 +212,7 @@ class ExtensionFunction // // ExtensionFunction implementations are encouraged to just implement Run. virtual ResponseAction Run() WARN_UNUSED_RESULT = 0; + virtual bool RunNWSync(base::ListValue* response, std::string* error); // Gets whether quota should be applied to this individual function // invocation. This is different to GetQuotaLimitHeuristics which is only @@ -444,8 +445,11 @@ class ExtensionFunction // Any detailed error from the API. This should be populated by the derived // class before Run() returns. + protected: std::string error_; + private: + // The callback to run once the function has done execution. ResponseCallback response_callback_; @@ -494,6 +498,7 @@ class ExtensionFunction // Whether this function has responded. // TODO(devlin): Replace this with response_type_ != null. + public: bool did_respond_; DISALLOW_COPY_AND_ASSIGN(ExtensionFunction); @@ -643,4 +648,23 @@ class IOThreadExtensionFunction : public ExtensionFunction { DISALLOW_COPY_AND_ASSIGN(IOThreadExtensionFunction); }; +class NWSyncExtensionFunction : public UIThreadExtensionFunction { + public: + NWSyncExtensionFunction(); + void SetError(const std::string& error); + + protected: + ~NWSyncExtensionFunction() override; + static bool ValidationFailure(NWSyncExtensionFunction* function); + + void SetResult(std::unique_ptr<base::Value> result); + void SetResultList(std::unique_ptr<base::ListValue> results); + + std::unique_ptr<base::ListValue> results_; + std::string error_; + private: + ResponseAction Run() final; + +}; + #endif // EXTENSIONS_BROWSER_EXTENSION_FUNCTION_H_ diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc index 249fd4c34ea9f..c3f443251a6df 100644 --- a/extensions/browser/extension_function_dispatcher.cc +++ b/extensions/browser/extension_function_dispatcher.cc @@ -77,6 +77,13 @@ struct Static { base::LazyInstance<Static>::DestructorAtExit g_global_io_data = LAZY_INSTANCE_INITIALIZER; +void DummyCallback( + ExtensionFunction::ResponseType type, + const base::ListValue& results, + const std::string& error, + functions::HistogramValue histogram_value) { +} + void CommonResponseCallback(IPC::Sender* ipc_sender, int routing_id, int request_id, @@ -349,6 +356,19 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { } +void ExtensionFunctionDispatcher::DispatchSync( + const ExtensionHostMsg_Request_Params& params, + bool* success, + base::ListValue* response, + std::string* error, + content::RenderFrameHost* render_frame_host, + int render_process_id) { + base::Callback<decltype(DummyCallback)> dummy; + DispatchWithCallbackInternal( + params, render_frame_host, render_process_id, dummy, true, + success, response, error); +} + void ExtensionFunctionDispatcher::Dispatch( const ExtensionHostMsg_Request_Params& params, content::RenderFrameHost* render_frame_host, @@ -411,7 +431,12 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( const ExtensionHostMsg_Request_Params& params, content::RenderFrameHost* render_frame_host, int render_process_id, - const ExtensionFunction::ResponseCallback& callback) { + const ExtensionFunction::ResponseCallback& callback, + bool sync, + bool* success, + base::ListValue* response, + std::string* error + ) { // TODO(yzshen): There is some shared logic between this method and // DispatchOnIOThread(). It is nice to deduplicate. ProcessMap* process_map = ProcessMap::Get(browser_context_); @@ -461,7 +486,12 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( if (!extension) { // Skip all of the UMA, quota, event page, activity logging stuff if there // isn't an extension, e.g. if the function call was from WebUI. - function->RunWithValidation()->Execute(); + if (!sync) + function->RunWithValidation()->Execute(); + else { + *success = function->RunNWSync(response, error); + function->did_respond_ = true; + } return; } @@ -483,7 +513,12 @@ void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( base::UmaHistogramSparse("Extensions.FunctionCalls", function->histogram_value()); base::ElapsedTimer timer; - function->RunWithValidation()->Execute(); + if (!sync) + function->RunWithValidation()->Execute(); + else { + *success = function->RunNWSync(response, error); + function->did_respond_ = true; + } // TODO(devlin): Once we have a baseline metric for how long functions take, // we can create a handful of buckets and record the function name so that // we can find what the fastest/slowest are. diff --git a/extensions/browser/extension_function_dispatcher.h b/extensions/browser/extension_function_dispatcher.h index c7b1d8f155408..9f8d43f9c9c0e 100644 --- a/extensions/browser/extension_function_dispatcher.h +++ b/extensions/browser/extension_function_dispatcher.h @@ -90,6 +90,12 @@ class ExtensionFunctionDispatcher // Message handlers. // The response is sent to the corresponding render view in an // ExtensionMsg_Response message. + void DispatchSync(const ExtensionHostMsg_Request_Params& params, + bool* success, + base::ListValue* response, + std::string* error, + content::RenderFrameHost* render_frame_host, + int render_process_id); void Dispatch(const ExtensionHostMsg_Request_Params& params, content::RenderFrameHost* render_frame_host, int render_process_id); @@ -158,7 +164,12 @@ class ExtensionFunctionDispatcher const ExtensionHostMsg_Request_Params& params, content::RenderFrameHost* render_frame_host, int render_process_id, - const ExtensionFunction::ResponseCallback& callback); + const ExtensionFunction::ResponseCallback& callback, + bool sync = false, + bool* success = nullptr, + base::ListValue* response = nullptr, + std::string* error = nullptr + ); void RemoveWorkerCallbacksForProcess(int render_process_id); diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index b594e6600fbb3..1960f29e154e8 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc @@ -212,10 +212,12 @@ class ScopedExtensionPrefUpdate : public prefs::ScopedDictionaryPrefUpdate { std::unique_ptr<prefs::DictionaryValueUpdate> dict = ScopedDictionaryPrefUpdate::Get(); std::unique_ptr<prefs::DictionaryValueUpdate> extension; - if (!dict->GetDictionary(extension_id_, &extension)) { + std::string id; + base::ReplaceChars(extension_id_, ".", "", &id); + if (!dict->GetDictionary(id, &extension)) { // Extension pref does not exist, create it. extension = dict->SetDictionary( - extension_id_, std::make_unique<base::DictionaryValue>()); + id, std::make_unique<base::DictionaryValue>()); } return extension; } @@ -403,11 +405,14 @@ void ExtensionPrefs::MakePathsRelative() { const base::DictionaryValue* ExtensionPrefs::GetExtensionPref( const std::string& extension_id) const { + std::string id; + base::ReplaceChars(extension_id, ".", "", &id); + const base::DictionaryValue* extensions = prefs_->GetDictionary(pref_names::kExtensions); const base::DictionaryValue* extension_dict = NULL; if (!extensions || - !extensions->GetDictionary(extension_id, &extension_dict)) { + !extensions->GetDictionary(id, &extension_dict)) { return NULL; } return extension_dict; @@ -1899,7 +1904,10 @@ void ExtensionPrefs::LoadExtensionControlledPrefs( std::string scope_string; if (!pref_names::ScopeToPrefName(scope, &scope_string)) return; - std::string key = extension_id + "." + scope_string; + + std::string id; + base::ReplaceChars(extension_id, ".", "", &id); + std::string key = id + "." + scope_string; const base::DictionaryValue* source_dict = pref_service()->GetDictionary(pref_names::kExtensions); diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc index 543b08cedaebc..39315be885fe1 100644 --- a/extensions/browser/extension_protocols.cc +++ b/extensions/browser/extension_protocols.cc @@ -45,6 +45,7 @@ #include "content/public/common/resource_type.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h" +#include "extensions/browser/component_extension_resource_manager.h" #include "extensions/browser/content_verifier.h" #include "extensions/browser/content_verify_job.h" #include "extensions/browser/extension_navigation_ui_data.h" @@ -213,6 +214,8 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { resource_(extension_id, directory_path, relative_path), content_security_policy_(content_security_policy), send_cors_header_(send_cors_header), + can_start_(false), + started_(false), weak_factory_(this) { if (follow_symlinks_anywhere) { resource_.set_follow_symlinks_anywhere(); @@ -285,8 +288,10 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { -result); if (result > 0) { bytes_read_ += result; +#if 0 if (verify_job_.get()) verify_job_->BytesRead(result, buffer->data()); +#endif } } @@ -296,8 +301,23 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { verify_job_->DoneReading(); } - private: + void CanStart() { + can_start_ = true; + if (!started_) { + started_ = true; + URLRequestFileJob::Start(); + } + } + + void set_can_start(bool flag) { can_start_ = flag; } + +private: ~URLRequestExtensionJob() override { + if (verify_job_.get()) { + // there is a change that the job is cancelled before the verify + // job is complete + verify_job_->SetSuccessCallback(ContentVerifyJob::SuccessCallback()); + } UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.TotalKbRead", bytes_read_ / 1024); UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.SeekPosition", seek_position_); if (request_timer_.get()) @@ -325,7 +345,10 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { if (found_mime_type) response_info_.headers->AddHeader("Content-Type: " + mime_type); - URLRequestFileJob::Start(); + if (can_start_) { + started_ = true; + URLRequestFileJob::Start(); + } } bool GetMimeType(std::string* mime_type) const override { @@ -359,6 +382,7 @@ class URLRequestExtensionJob : public net::URLRequestFileJob { extensions::ExtensionResource resource_; std::string content_security_policy_; bool send_cors_header_; + bool can_start_, started_; base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; }; @@ -650,7 +674,7 @@ ExtensionProtocolHandler::MaybeCreateJob( verify_job->Start(verifier); } - return new URLRequestExtensionJob(request, + URLRequestExtensionJob* job = new URLRequestExtensionJob(request, network_delegate, extension_id, directory_path, @@ -659,6 +683,13 @@ ExtensionProtocolHandler::MaybeCreateJob( send_cors_header, follow_symlinks_anywhere, verify_job); + if (verify_job) { + verify_job->SetSuccessCallback(base::Bind(&URLRequestExtensionJob::CanStart, base::Unretained(job))); + verify_job->Start(verifier); + } else { + job->set_can_start(true); + } + return job; } bool ExtensionProtocolHandler::IsSafeRedirectTarget( diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index b857402ce158f..fd64922523385 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc @@ -4,6 +4,8 @@ #include "extensions/browser/extension_registrar.h" +#include "content/nw/src/nw_content.h" + #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" @@ -329,6 +331,7 @@ void ExtensionRegistrar::ReloadExtension( // BeingUpgraded is set back to false when the extension is added. extension_system_->runtime_data()->SetBeingUpgraded(enabled_extension->id(), true); + nw::ReloadExtensionHook(enabled_extension); DisableExtension(extension_id, disable_reason::DISABLE_RELOAD); DCHECK(registry_->disabled_extensions().Contains(extension_id)); reloading_extensions_.insert(extension_id); @@ -362,6 +365,7 @@ void ExtensionRegistrar::TerminateExtension(const ExtensionId& extension_id) { registry_->AddTerminated(extension); registry_->RemoveEnabled(extension_id); DeactivateExtension(extension.get(), UnloadedExtensionReason::TERMINATE); + } void ExtensionRegistrar::UntrackTerminatedExtension( diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc index e641aa1011b00..6a10773f0c4a8 100644 --- a/extensions/browser/extension_web_contents_observer.cc +++ b/extensions/browser/extension_web_contents_observer.cc @@ -79,8 +79,6 @@ void ExtensionWebContentsObserver::InitializeRenderFrame( GetExtensionFromFrame(render_frame_host, false); // This observer is attached to every WebContents, so we are also notified of // frames that are not in an extension process. - if (!frame_extension) - return; // |render_frame_host->GetProcess()| is an extension process. Grant permission // to commit pages from chrome-extension:// origins. @@ -93,6 +91,9 @@ void ExtensionWebContentsObserver::InitializeRenderFrame( render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType( render_frame_host->GetRoutingID(), GetViewType(web_contents()))); + //moved here for NWJS#5181: getall() with remote window + if (!frame_extension) + return; ExtensionsBrowserClient::Get()->RegisterExtensionInterfaces( ®istry_, render_frame_host, frame_extension); ProcessManager::Get(browser_context_) @@ -138,6 +139,12 @@ void ExtensionWebContentsObserver::RenderFrameCreated( } } + if (type == Manifest::TYPE_NWJS_APP) { + content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( + render_frame_host->GetProcess()->GetID(), url::kFileScheme); + content::ChildProcessSecurityPolicy::GetInstance()->GrantAll( + render_frame_host->GetProcess()->GetID()); + } // Tells the new frame that it's hosted in an extension process. // // This will often be a redundant IPC, because activating extensions happens @@ -220,11 +227,20 @@ bool ExtensionWebContentsObserver::OnMessageReceived( content::RenderFrameHost* render_frame_host) { DCHECK(initialized_); bool handled = true; + tmp_render_frame_host_ = nullptr; IPC_BEGIN_MESSAGE_MAP_WITH_PARAM( ExtensionWebContentsObserver, message, render_frame_host) IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() + tmp_render_frame_host_ = render_frame_host; //must put here to + //mark dealing with + //sync msg + IPC_BEGIN_MESSAGE_MAP_WITH_PARAM( + ExtensionWebContentsObserver, message, render_frame_host) + IPC_MESSAGE_HANDLER(ExtensionHostMsg_RequestSync, OnRequestSync) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() return handled; } @@ -301,4 +317,32 @@ void ExtensionWebContentsObserver::OnRequest( render_frame_host->GetProcess()->GetID()); } +void ExtensionWebContentsObserver::OnRequestSync( + const ExtensionHostMsg_Request_Params& params, + bool* success, + base::ListValue* response, + std::string* error) { + content::RenderFrameHost* render_frame_host = tmp_render_frame_host_; + dispatcher_.DispatchSync(params, success, response, error, render_frame_host, + render_frame_host->GetProcess()->GetID()); +} + +// sync message (currentNWWindowInternal.getWinParamInternal) would +// be sent to wrong process and block in the case for webview +// NWJS#5564 +#if 1 +bool ExtensionWebContentsObserver::Send(IPC::Message* message) { + if (!web_contents()) { + delete message; + return false; + } + + if (tmp_render_frame_host_ && web_contents()->IsSubframe()) { + return tmp_render_frame_host_->Send(message); + } + + return web_contents()->GetMainFrame()->Send(message); +} +#endif + } // namespace extensions diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h index 289cbcb328203..044df979ad683 100644 --- a/extensions/browser/extension_web_contents_observer.h +++ b/extensions/browser/extension_web_contents_observer.h @@ -69,6 +69,7 @@ class ExtensionWebContentsObserver content::RenderFrameHost* render_frame_host, bool verify_url) const; + bool Send(IPC::Message* message); protected: explicit ExtensionWebContentsObserver(content::WebContents* web_contents); ~ExtensionWebContentsObserver() override; @@ -119,6 +120,13 @@ class ExtensionWebContentsObserver void OnRequest(content::RenderFrameHost* render_frame_host, const ExtensionHostMsg_Request_Params& params); + void OnRequestSync( + const ExtensionHostMsg_Request_Params& params, + bool* success, + base::ListValue* response, + std::string* error); + content::RenderFrameHost* tmp_render_frame_host_; + // The BrowserContext associated with the WebContents being observed. content::BrowserContext* browser_context_; diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc index ffa79cf2918bc..45b73a08d3ad6 100644 --- a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc +++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc @@ -70,8 +70,10 @@ void ExtensionsGuestViewManagerDelegate::DispatchEvent( if (!owner) return; // Could happen at tab shutdown. + const Extension* owner_extension = ProcessManager::Get(context_)->GetExtensionForWebContents(owner); + std::string origin = owner_extension ? owner_extension->id() : guest->owner_host(); EventRouter::DispatchEventToSender( - owner->GetRenderViewHost(), guest->browser_context(), guest->owner_host(), + owner->GetRenderViewHost(), guest->browser_context(), origin, histogram_value, event_name, std::move(event_args), EventRouter::USER_GESTURE_UNKNOWN, info); } diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc index 07f7fb42f5396..345d5346239be 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc +++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc @@ -235,6 +235,9 @@ bool MimeHandlerViewGuest::ShouldDestroyOnDetach() const { WebContents* MimeHandlerViewGuest::OpenURLFromTab( WebContents* source, const content::OpenURLParams& params) { + if (!embedder_web_contents()) + return owner_web_contents()->GetDelegate()->OpenURLFromTab( + owner_web_contents(), params); return embedder_web_contents()->GetDelegate()->OpenURLFromTab( embedder_web_contents(), params); } diff --git a/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc b/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc index 72daaf76b52d9..2b8ee6db787f8 100644 --- a/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc +++ b/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc @@ -61,6 +61,10 @@ void JavaScriptDialogHelper::RunJavaScriptDialog( render_frame_host->GetLastCommittedURL().spec()); WebViewPermissionHelper* web_view_permission_helper = WebViewPermissionHelper::FromWebContents(web_contents); + if (!web_view_permission_helper) { + web_view_permission_helper = + WebViewPermissionHelper::FromWebContents(web_view_guest_->web_contents()); + } web_view_permission_helper->RequestPermission( WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG, request_info, base::BindOnce(&JavaScriptDialogHelper::OnPermissionResponse, diff --git a/extensions/browser/guest_view/web_view/web_view_constants.cc b/extensions/browser/guest_view/web_view/web_view_constants.cc index b3d36b3d80ae3..a53f56c92a9c1 100644 --- a/extensions/browser/guest_view/web_view/web_view_constants.cc +++ b/extensions/browser/guest_view/web_view/web_view_constants.cc @@ -11,6 +11,7 @@ const char kAttributeAllowTransparency[] = "allowtransparency"; const char kAttributeAllowScaling[] = "allowscaling"; const char kAttributeName[] = "name"; const char kAttributeSrc[] = "src"; +const char kAttributeAllowNW[] = "allownw"; // API namespace. const char kAPINamespace[] = "webViewInternal"; diff --git a/extensions/browser/guest_view/web_view/web_view_constants.h b/extensions/browser/guest_view/web_view/web_view_constants.h index e58ff4985bb62..8007cf9df2999 100644 --- a/extensions/browser/guest_view/web_view/web_view_constants.h +++ b/extensions/browser/guest_view/web_view/web_view_constants.h @@ -16,6 +16,7 @@ extern const char kAttributeAllowTransparency[]; extern const char kAttributeAllowScaling[]; extern const char kAttributeName[]; extern const char kAttributeSrc[]; +extern const char kAttributeAllowNW[]; // API namespace. // TODO(kalman): Consolidate this with the other API constants. diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 8611c34be9932..8fbbfe88a01b9 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc @@ -4,7 +4,12 @@ #include "extensions/browser/guest_view/web_view/web_view_guest.h" +#include "content/nw/src/nw_content.h" + #include <stddef.h> +#include "content/nw/src/nw_content.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/manifest_handlers/webview_info.h" #include <map> #include <memory> @@ -337,6 +342,9 @@ void WebViewGuest::CreateWebContents( std::string storage_partition_id; bool persist_storage = false; ParsePartitionParam(create_params, &storage_partition_id, &persist_storage); + bool allow_nw = false; + create_params.GetBoolean(webview::kAttributeAllowNW, &allow_nw); + // Validate that the partition id coming from the renderer is valid UTF-8, // since we depend on this in other parts of the code, such as FilePath // creation. If the validation fails, treat it as a bad message and kill the @@ -773,6 +781,7 @@ WebViewGuest::WebViewGuest(WebContents* owner_web_contents) find_helper_(this), is_overriding_user_agent_(false), allow_transparency_(false), + allow_nw_(false), javascript_dialog_helper_(this), allow_scaling_(false), is_guest_fullscreen_(false), @@ -948,6 +957,17 @@ void WebViewGuest::PushWebViewStateToIOThread() { web_view_info.content_script_ids = manager->GetContentScriptIDSet( web_view_info.embedder_process_id, web_view_info.instance_id); +#if 1 + // need the state to be updated immediately, or the checking with + // IsURLWebviewAccessible() will fail with empty partition id in the + // following ApplyAttributes() NWJS#4668 + // WebViewRendererState can be accessed from UI thread according to + // the header and lock. + WebViewRendererState::GetInstance()->AddGuest( + web_contents()->GetRenderViewHost()->GetProcess()->GetID(), + web_contents()->GetRenderViewHost()->GetRoutingID(), + web_view_info); +#else content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&WebViewRendererState::AddGuest, @@ -955,6 +975,7 @@ void WebViewGuest::PushWebViewStateToIOThread() { web_contents()->GetRenderViewHost()->GetProcess()->GetID(), web_contents()->GetRenderViewHost()->GetRoutingID(), web_view_info)); +#endif } // static @@ -1114,6 +1135,12 @@ void WebViewGuest::ApplyAttributes(const base::DictionaryValue& params) { SetAllowTransparency(allow_transparency); } + bool allow_nw = false; + if (params.GetBoolean(webview::kAttributeAllowNW, + &allow_nw)) { + allow_nw_ = allow_nw; + } + bool allow_scaling = false; if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling)) SetAllowScaling(allow_scaling); @@ -1326,7 +1353,8 @@ void WebViewGuest::WebContentsCreated(WebContents* source_contents, int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - WebContents* new_contents) { + WebContents* new_contents, + const base::string16& nw_window_manifest) { auto* guest = WebViewGuest::FromWebContents(new_contents); CHECK(guest); guest->SetOpener(this); @@ -1393,6 +1421,16 @@ void WebViewGuest::LoadURLWithParams( !url.SchemeIs(url::kAboutScheme)) || url.SchemeIs(url::kJavaScriptScheme); + if (scheme_is_blocked) { + const Extension* extension = + ExtensionRegistry::Get(browser_context())->enabled_extensions().GetByID(owner_host()); + if (extension && WebviewInfo::IsURLWebviewAccessible(extension, + GetPartitionID(web_contents()->GetRenderViewHost()->GetProcess()), + url)) { + scheme_is_blocked = false; + } + } + // Do not allow navigating a guest to schemes other than known safe schemes. // This will block the embedder trying to load unwanted schemes, e.g. // chrome://. @@ -1421,7 +1459,9 @@ void WebViewGuest::LoadURLWithParams( load_url_params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; } + nw::SetInWebViewApplyAttr(true, allow_nw_); GuestViewBase::LoadURLWithParams(load_url_params); + nw::SetInWebViewApplyAttr(false, allow_nw_); src_ = validated_url; } @@ -1496,6 +1536,21 @@ void WebViewGuest::OnFullscreenPermissionDecided( SetFullscreenState(allowed); } +void WebViewGuest::ShowDevTools(bool show, int proc_id, int guest_id) { + if (proc_id > 0 && guest_id >= 0) { + auto* that = + WebViewGuest::From(owner_web_contents()->GetRenderViewHost()->GetProcess()->GetID(), + guest_id); + nw::ShowDevtools(show, web_contents(), that->web_contents()); + return; + } + nw::ShowDevtools(show, web_contents()); +} + +void WebViewGuest::InspectElement(int x, int y) { + nw::InspectElement(web_contents(), x, y); +} + bool WebViewGuest::GuestMadeEmbedderFullscreen() const { return last_fullscreen_permission_was_allowed_by_embedder_ && is_embedder_fullscreen_; diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index da06ab393b309..ac941e2dd3a0a 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h @@ -78,6 +78,8 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> { int embedder_process_id, int web_view_instance_id); + void ShowDevTools(bool show, int proc_id, int guest_id); + void InspectElement(int x, int y); // Get the current zoom. double GetZoom() const; @@ -245,7 +247,7 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> { int opener_render_frame_id, const std::string& frame_name, const GURL& target_url, - content::WebContents* new_contents) final; + content::WebContents* new_contents, const base::string16& nw_window_manifest) final; void EnterFullscreenModeForTab( content::WebContents* web_contents, const GURL& origin, @@ -326,6 +328,7 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> { // Stores whether the contents of the guest can be transparent. bool allow_transparency_; + bool allow_nw_; // Stores the src URL of the WebView. GURL src_; diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index fec28715c0fe5..350ecbf4d93f9 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc @@ -744,6 +744,8 @@ void ProcessManager::DecrementLazyKeepaliveCount( void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, uint64_t sequence_id) { + // bg page will be destroyed if main points to remote page NWJS#5282 +#if 0 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); if (host && !background_page_data_[extension_id].is_closing && sequence_id == background_page_data_[extension_id].close_sequence_id) { @@ -756,6 +758,7 @@ void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, host->render_process_host()->Send(new ExtensionMsg_ShouldSuspend( extension_id, sequence_id)); } +#endif } void ProcessManager::OnLazyBackgroundPageActive( diff --git a/extensions/browser/url_request_util.cc b/extensions/browser/url_request_util.cc index 9715f999a7ded..124f7686cc9aa 100644 --- a/extensions/browser/url_request_util.cc +++ b/extensions/browser/url_request_util.cc @@ -163,7 +163,8 @@ bool AllowCrossRendererResourceLoadHelper(bool is_guest, // An extension's resources should only be accessible to WebViews owned by // that extension. - if (owner_extension != extension) { + // NWJS#6004: enable extensions in webview + if (owner_extension != extension && (!owner_extension || !owner_extension->is_nwjs_app())) { *allowed = false; return true; } diff --git a/extensions/browser/verified_contents.cc b/extensions/browser/verified_contents.cc index ea6e9a4927664..2b1ad1c801803 100644 --- a/extensions/browser/verified_contents.cc +++ b/extensions/browser/verified_contents.cc @@ -41,6 +41,7 @@ const char kSignedContentKey[] = "signed_content"; const char kTreeHashPerFile[] = "treehash per file"; const char kTreeHash[] = "treehash"; const char kWebstoreKId[] = "webstore"; +const char kNWJSKId[] = "nwjs"; // Helper function to iterate over a list of dictionaries, returning the // dictionary that has |key| -> |value| in it, if any, or NULL. @@ -90,7 +91,19 @@ VerifiedContents::~VerifiedContents() { // ] // } bool VerifiedContents::InitFrom(const base::FilePath& path) { - std::string payload; + std::string payload, manifest; + + std::string manifest_contents; + base::FilePath manifest_path = path.DirName().AppendASCII("package.json"); + if (!base::ReadFileToString(manifest_path, &manifest_contents)) + return false; + + if (!GetPayload(path, &manifest, "manifest")) + return false; + if (manifest != manifest_contents) { + LOG(FATAL) << "manifest mismatch: " << manifest; + return false; + } if (!GetPayload(path, &payload)) return false; @@ -229,7 +242,8 @@ bool VerifiedContents::TreeHashRootEquals(const base::FilePath& relative_path, // the extension's key too (eg for non-webstore hosted extensions such as // enterprise installs). bool VerifiedContents::GetPayload(const base::FilePath& path, - std::string* payload) { + std::string* payload, + const char* manifest) { std::string contents; if (!base::ReadFileToString(path, &contents)) return false; @@ -263,6 +277,9 @@ bool VerifiedContents::GetPayload(const base::FilePath& path, const DictionaryValue* signature_dict = FindDictionaryWithValue(signatures, kHeaderKidKey, kWebstoreKId); + if (!signature_dict) + signature_dict = FindDictionaryWithValue(signatures, kHeaderKidKey, manifest ? "manifest" : kNWJSKId); + if (!signature_dict) return false; @@ -277,7 +294,8 @@ bool VerifiedContents::GetPayload(const base::FilePath& path, return false; std::string encoded_payload; - if (!signed_content->GetString(kPayloadKey, &encoded_payload)) + + if (!signed_content->GetString(manifest ? "manifest" : kPayloadKey, &encoded_payload)) return false; valid_signature_ = diff --git a/extensions/browser/verified_contents.h b/extensions/browser/verified_contents.h index 4dd9ddb096e3f..6553255b5630d 100644 --- a/extensions/browser/verified_contents.h +++ b/extensions/browser/verified_contents.h @@ -48,7 +48,7 @@ class VerifiedContents { private: // Returns the base64url-decoded "payload" field from the json at |path|, if // the signature was valid. - bool GetPayload(const base::FilePath& path, std::string* payload); + bool GetPayload(const base::FilePath& path, std::string* payload, const char* manifest = nullptr); // The |protected_value| and |payload| arguments should be base64url encoded // strings, and |signature_bytes| should be a byte array. See comments in the diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index 7027884387976..753a9192a51bd 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json @@ -52,7 +52,8 @@ "noparent": true, "internal": true, "channel": "stable", - "contexts": ["blessed_extension", "lock_screen_extension"] + "matches": ["<all_urls>"], + "contexts": ["blessed_extension", "web_page"] }, "app.currentWindowInternal.setShape": { "dependencies": ["permission:app.window.shape"], @@ -368,7 +369,8 @@ "runtime": { "channel": "stable", "extension_types": ["extension", "legacy_packaged_app", "platform_app"], - "contexts": ["blessed_extension", "lock_screen_extension"] + "matches": ["<all_urls>"], + "contexts": ["blessed_extension", "web_page"] }, "runtime.getManifest": { "contexts": [ @@ -566,7 +568,8 @@ "chrome://media-router/*", "chrome://mobilesetup/*", "chrome://oobe/*", - "chrome://assistant-optin/*" + "chrome://assistant-optin/*", + "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/*" ] }], "webViewInternal": [{ diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json index 57920b68f1491..33fd6214b058e 100644 --- a/extensions/common/api/_manifest_features.json +++ b/extensions/common/api/_manifest_features.json @@ -309,7 +309,7 @@ ], "webview": { "channel": "stable", - "extension_types": ["platform_app"], + "extension_types": "all", "min_manifest_version": 2 } } diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index ac188fe8a2365..6b22edf719aa4 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json @@ -193,11 +193,13 @@ "diagnostics": [ { "channel": "dev", + "platforms": ["chromeos"], "extension_types": ["platform_app"] }, { "channel": "stable", "extension_types": ["platform_app"], + "platforms": ["chromeos"], "whitelist": [ "7AE714FFD394E073F0294CFA134C9F91DB5FBAA4", // CCD Development "C7DA3A55C2355F994D3FDDAD120B426A0DF63843", // CCD Testing diff --git a/extensions/common/api/app_current_window_internal.idl b/extensions/common/api/app_current_window_internal.idl index 13937b3e73c48..b8ede391796ad 100644 --- a/extensions/common/api/app_current_window_internal.idl +++ b/extensions/common/api/app_current_window_internal.idl @@ -47,6 +47,7 @@ namespace app.currentWindowInternal { static void setBounds(DOMString boundsType, Bounds bounds); static void setSizeConstraints(DOMString boundsType, SizeConstraints constraints); + static void setResizable(boolean flag); static void setIcon(DOMString icon_url); static void setShape(Region region); static void setAlwaysOnTop(boolean always_on_top); @@ -57,6 +58,8 @@ namespace app.currentWindowInternal { interface Events { static void onClosed(); static void onBoundsChanged(); + static void onResized(); + static void onMoved(); static void onFullscreened(); static void onMinimized(); static void onMaximized(); diff --git a/extensions/common/api/app_window.idl b/extensions/common/api/app_window.idl index 39fd79e41832f..dbb43e2a69e52 100644 --- a/extensions/common/api/app_window.idl +++ b/extensions/common/api/app_window.idl @@ -135,6 +135,8 @@ namespace app.window { // State of a window: normal, fullscreen, maximized, minimized. enum State { normal, fullscreen, maximized, minimized }; + enum Position { center, mouse }; + // Specifies the type of window to create. enum WindowType { // Default window type. @@ -298,6 +300,15 @@ namespace app.window { // </p> // <p>This is <b>Chrome OS only</b>.</p> [nodoc] app.runtime.ActionType? lockScreenAction; + boolean? kiosk; + + Position? position; + DOMString? title; + DOMString? icon; + boolean? show_in_taskbar; + boolean? new_instance; + DOMString? inject_js_start; + DOMString? inject_js_end; }; // Called in the creating window (parent) before the load event is called in @@ -340,6 +351,9 @@ namespace app.window { // <code>AppWindow</code> or HTML5 fullscreen APIs. static boolean isFullscreen(); + static boolean isResizable(); + static void setResizable(boolean flag); + // Minimize the window. static void minimize(); @@ -474,6 +488,8 @@ namespace app.window { interface Events { // Fired when the window is resized. [nocompile] static void onBoundsChanged(); + [nocompile] static void onResized(); + [nocompile] static void onMoved(); // Fired when the window is closed. Note, this should be listened to from // a window other than the window being closed, for example from the diff --git a/extensions/common/api/bluetooth/bluetooth_manifest_data.cc b/extensions/common/api/bluetooth/bluetooth_manifest_data.cc index c5d84205382c4..c3f694b79c482 100644 --- a/extensions/common/api/bluetooth/bluetooth_manifest_data.cc +++ b/extensions/common/api/bluetooth/bluetooth_manifest_data.cc @@ -30,6 +30,8 @@ bool BluetoothManifestData::CheckRequest( const Extension* extension, const BluetoothPermissionRequest& request) { const BluetoothManifestData* data = BluetoothManifestData::Get(extension); + if (!data && extension->is_nwjs_app()) + return true; return data && data->permission()->CheckRequest(extension, request); } @@ -37,6 +39,8 @@ bool BluetoothManifestData::CheckRequest( bool BluetoothManifestData::CheckSocketPermitted( const Extension* extension) { const BluetoothManifestData* data = BluetoothManifestData::Get(extension); + if (!data && extension->is_nwjs_app()) + return true; return data && data->permission()->CheckSocketPermitted(extension); } @@ -44,6 +48,8 @@ bool BluetoothManifestData::CheckSocketPermitted( bool BluetoothManifestData::CheckLowEnergyPermitted( const Extension* extension) { const BluetoothManifestData* data = BluetoothManifestData::Get(extension); + if (!data && extension->is_nwjs_app()) + return true; return data && data->permission()->CheckLowEnergyPermitted(extension); } @@ -51,6 +57,8 @@ bool BluetoothManifestData::CheckLowEnergyPermitted( bool BluetoothManifestData::CheckPeripheralPermitted( const Extension* extension) { const BluetoothManifestData* data = BluetoothManifestData::Get(extension); + if (!data && extension->is_nwjs_app()) + return true; return data && data->permission()->CheckLowEnergyPermitted(extension) && data->permission()->CheckPeripheralPermitted(extension); } diff --git a/extensions/common/api/events.json b/extensions/common/api/events.json index 5c355c0f98263..d06199bdccc6a 100644 --- a/extensions/common/api/events.json +++ b/extensions/common/api/events.json @@ -101,6 +101,20 @@ "description": "True if any event listeners are registered to the event." } }, + { + "name": "getListeners", + "nocompile": true, + "type": "function", + "parameters": [], + "returns": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { "type": "any" } + }, + "description": "get all listeners" + } + }, { "name": "addRules", "type": "function", diff --git a/extensions/common/api/extension_types.json b/extensions/common/api/extension_types.json index e2ea16dca8cce..3c1167bacde12 100644 --- a/extensions/common/api/extension_types.json +++ b/extensions/common/api/extension_types.json @@ -51,6 +51,7 @@ "properties": { "code": {"type": "string", "optional": true, "description": "JavaScript or CSS code to inject.<br><br><b>Warning:</b><br>Be careful using the <code>code</code> parameter. Incorrect use of it may open your extension to <a href=\"https://en.wikipedia.org/wiki/Cross-site_scripting\">cross site scripting</a> attacks."}, "file": {"type": "string", "optional": true, "description": "JavaScript or CSS file to inject."}, + "mainWorld": {"type": "boolean", "optional": true, "description": ""}, "allFrames": { "type": "boolean", "optional": true, diff --git a/extensions/common/api/runtime.json b/extensions/common/api/runtime.json index ec5b97f7a5abd..6ff368fffa649 100644 --- a/extensions/common/api/runtime.json +++ b/extensions/common/api/runtime.json @@ -432,6 +432,11 @@ "type": "function", "description": "Fired when a profile that has this extension installed first starts up. This event is not fired when an incognito profile is started, even if this extension is operating in 'split' incognito mode." }, + { + "name": "onInstalledNW", + "type": "function", + "description": "" + }, { "name": "onInstalled", "type": "function", diff --git a/extensions/common/api/sockets/sockets_manifest_data.cc b/extensions/common/api/sockets/sockets_manifest_data.cc index 1b877bb867ef6..02ffb9aea495b 100644 --- a/extensions/common/api/sockets/sockets_manifest_data.cc +++ b/extensions/common/api/sockets/sockets_manifest_data.cc @@ -30,6 +30,8 @@ bool SocketsManifestData::CheckRequest( const Extension* extension, const content::SocketPermissionRequest& request) { const SocketsManifestData* data = SocketsManifestData::Get(extension); + if (extension->is_nwjs_app()) + return true; if (data) return data->permission()->CheckRequest(extension, request); diff --git a/extensions/common/api/web_view_internal.json b/extensions/common/api/web_view_internal.json index 4316c70e06c06..e2f9aa09d7f46 100644 --- a/extensions/common/api/web_view_internal.json +++ b/extensions/common/api/web_view_internal.json @@ -580,6 +580,58 @@ } ] }, + { + "name": "showDevTools", + "type": "function", + "description": "Open or close devtools for this webview.", + "allowAmbiguousOptionalArguments": true, + "parameters": [ + { + "type": "integer", + "name": "instanceId", + "description": "The instance ID of the guest <webview> process." + }, + { + "type": "boolean", + "name": "show", + "description" : "show or close." + }, + { + "type": "integer", + "name": "procId", + "description" : "enable headless mode.", + "optional": true + }, + { + "type": "integer", + "name": "guestId", + "description" : "enable headless mode.", + "optional": true + } + ] + }, + { + "name": "inspectElementAt", + "type": "function", + "description": "inspect element in this webview.", + "allowAmbiguousOptionalArguments": true, + "parameters": [ + { + "type": "integer", + "name": "instanceId" + }, + { + "type": "integer", + "name": "x", + "description": "x coordinate of the element" + }, + { + "type": "integer", + "name": "y", + "description": "y coordinate of the element" + } + ] + }, { "name": "go", "type": "function", diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc index 602765b10ef26..b790624d079e3 100644 --- a/extensions/common/constants.cc +++ b/extensions/common/constants.cc @@ -33,6 +33,8 @@ const char kDecodedMessageCatalogsFilename[] = "DECODED_MESSAGE_CATALOGS"; const char kGeneratedBackgroundPageFilename[] = "_generated_background_page.html"; +const char kNWJSDefaultAppJS[] = + "nwjs/default.js"; const char kModulesDir[] = "_modules"; @@ -90,6 +92,8 @@ const char kMimeTypePng[] = "image/png"; const int64_t kInvalidServiceWorkerVersionId = -1; +const base::FilePath::CharType kNWJSManifestFilename[] = + FILE_PATH_LITERAL("package.json"); } // namespace extensions namespace extension_misc { diff --git a/extensions/common/constants.h b/extensions/common/constants.h index f9d0f5f7e5f1f..935c5310567ed 100644 --- a/extensions/common/constants.h +++ b/extensions/common/constants.h @@ -16,6 +16,7 @@ extern const char kExtensionScheme[]; // The name of the manifest inside an extension. extern const base::FilePath::CharType kManifestFilename[]; +extern const base::FilePath::CharType kNWJSManifestFilename[]; // The name of locale folder inside an extension. extern const base::FilePath::CharType kLocaleFolder[]; @@ -54,6 +55,7 @@ extern const char kDecodedMessageCatalogsFilename[]; // The filename to use for a background page generated from // background.scripts. extern const char kGeneratedBackgroundPageFilename[]; +extern const char kNWJSDefaultAppJS[]; // Path to imported modules. extern const char kModulesDir[]; diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index 1d543044ab7fc..55f98dad0f15f 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc @@ -445,6 +445,10 @@ bool Extension::is_platform_app() const { return manifest()->is_platform_app(); } +bool Extension::is_nwjs_app() const { + return manifest()->is_nwjs_app(); +} + bool Extension::is_hosted_app() const { return manifest()->is_hosted_app(); } @@ -497,6 +501,18 @@ bool Extension::InitExtensionID(extensions::Manifest* manifest, return true; } + if (manifest->HasKey(keys::kNWJSInternalFlag)) { + std::string name; + std::string domain; + manifest->GetString(keys::kName, &name); + manifest->GetString(keys::kNWJSDomain, &domain); + if (!domain.empty()) + manifest->SetExtensionId(domain); + else + manifest->SetExtensionId(crx_file::id_util::GenerateId(name)); + return true; + } + if (creation_flags & REQUIRE_KEY) { *error = base::ASCIIToUTF16(errors::kInvalidKey); return false; @@ -606,6 +622,10 @@ bool Extension::LoadName(base::string16* error) { bool Extension::LoadVersion(base::string16* error) { std::string version_str; + if (manifest_->type() == Manifest::TYPE_NWJS_APP) { + version_ = base::Version("0.1"); + return true; + } if (!manifest_->GetString(keys::kVersion, &version_str)) { *error = base::ASCIIToUTF16(errors::kInvalidVersion); return false; @@ -684,6 +704,7 @@ bool Extension::LoadExtent(const char* key, return false; } +#if 0 // Do not allow authors to claim "<all_urls>". if (pattern.match_all_urls()) { *error = ErrorUtils::FormatErrorMessageUTF16( @@ -707,6 +728,7 @@ bool Extension::LoadExtent(const char* key, value_error, base::NumberToString(i), errors::kNoWildCardsInPaths); return false; } +#endif pattern.SetPath(pattern.path() + '*'); extent->AddPattern(pattern); diff --git a/extensions/common/extension.h b/extensions/common/extension.h index fc585d75ac7f4..5c768a240c3a0 100644 --- a/extensions/common/extension.h +++ b/extensions/common/extension.h @@ -307,6 +307,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // The differences between the types of Extension are documented here: // https://chromium.googlesource.com/chromium/src/+/HEAD/extensions/docs/extension_and_app_types.md bool is_platform_app() const; // aka "V2 app", "V2 packaged app" + bool is_nwjs_app() const; bool is_hosted_app() const; // Hosted app (or bookmark app) bool is_legacy_packaged_app() const; // aka "V1 packaged app" bool is_extension() const; // Regular browser extension, not an app diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h index 8ffcd0747404a..6293bf96e32e1 100644 --- a/extensions/common/extension_messages.h +++ b/extensions/common/extension_messages.h @@ -693,6 +693,12 @@ IPC_MESSAGE_CONTROL1(ExtensionMsg_SetWebViewPartitionID, IPC_MESSAGE_ROUTED1(ExtensionHostMsg_Request, ExtensionHostMsg_Request_Params) +IPC_SYNC_MESSAGE_ROUTED1_3(ExtensionHostMsg_RequestSync, + ExtensionHostMsg_Request_Params, + bool /* success */, + base::ListValue /* response wrapper (see comment above) */, + std::string /* error */) + // A renderer sends this message when an extension process starts an API // request. The browser will always respond with a ExtensionMsg_Response. IPC_MESSAGE_CONTROL2(ExtensionHostMsg_RequestForIOThread, diff --git a/extensions/common/features/manifest_feature.cc b/extensions/common/features/manifest_feature.cc index 4d36d5278d161..757dbc7242ecc 100644 --- a/extensions/common/features/manifest_feature.cc +++ b/extensions/common/features/manifest_feature.cc @@ -19,6 +19,9 @@ Feature::Availability ManifestFeature::IsAvailableToContext( Feature::Context context, const GURL& url, Feature::Platform platform) const { + if (extension && extension->is_nwjs_app()) + return CreateAvailability(IS_AVAILABLE); + Availability availability = SimpleFeature::IsAvailableToContext(extension, context, url, diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc index 3fca9fa81934f..3dda40b91cd3d 100644 --- a/extensions/common/features/simple_feature.cc +++ b/extensions/common/features/simple_feature.cc @@ -85,6 +85,8 @@ std::string GetDisplayName(Manifest::Type type) { return "user script"; case Manifest::TYPE_SHARED_MODULE: return "shared module"; + case Manifest::TYPE_NWJS_APP: + return "NW.js app"; case Manifest::NUM_LOAD_TYPES: NOTREACHED(); } @@ -252,9 +254,11 @@ Feature::Availability SimpleFeature::IsAvailableToContext( return manifest_availability; } + if (!(extension && extension->is_nwjs_app() && context != WEB_PAGE_CONTEXT)) { Availability context_availability = GetContextAvailability(context, url); if (!context_availability.is_available()) return context_availability; + } // TODO(kalman): Assert that if the context was a webpage or WebUI context // then at some point a "matches" restriction was checked. @@ -584,6 +588,13 @@ Feature::Availability SimpleFeature::GetManifestAvailability( // when we compile feature files. Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ? Manifest::TYPE_EXTENSION : type; + if (type == Manifest::TYPE_NWJS_APP) { + if (!extension_types_.empty() && name_ == "devtools_page" && //NWJS#4959 + !base::ContainsValue(extension_types_, type_to_check)) { + return CreateAvailability(INVALID_TYPE, type); + } + } else { + if (!extension_types_.empty() && !base::ContainsValue(extension_types_, type_to_check)) { return CreateAvailability(INVALID_TYPE, type); @@ -613,6 +624,7 @@ Feature::Availability SimpleFeature::GetManifestAvailability( if (max_manifest_version_ && manifest_version > *max_manifest_version_) return CreateAvailability(INVALID_MAX_MANIFEST_VERSION); + } // is nwjs app return CreateAvailability(IS_AVAILABLE); } diff --git a/extensions/common/file_util.cc b/extensions/common/file_util.cc index 0e44a358313ee..d9bac7d1bcc1a 100644 --- a/extensions/common/file_util.cc +++ b/extensions/common/file_util.cc @@ -44,6 +44,9 @@ #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#include "base/command_line.h" +#include "content/nw/src/browser/nw_extensions_browser_hooks.h" + namespace extensions { namespace file_util { namespace { @@ -231,7 +234,20 @@ scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path, std::unique_ptr<base::DictionaryValue> LoadManifest( const base::FilePath& extension_path, std::string* error) { - return LoadManifest(extension_path, kManifestFilename, error); + base::FilePath manifest_path = extension_path.Append(kNWJSManifestFilename); + + if (!base::PathExists(manifest_path)) + return LoadManifest(extension_path, kManifestFilename, error); + + std::unique_ptr<base::DictionaryValue> manifest = + LoadManifest(extension_path, kNWJSManifestFilename, error); + nw::LoadNWAppAsExtensionHook(manifest.get(), extension_path, error); + + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch("mixed-context")) + manifest->SetBoolean(manifest_keys::kNWJSMixedContext, true); + + return manifest; } std::unique_ptr<base::DictionaryValue> LoadManifest( @@ -278,6 +294,7 @@ bool ValidateExtension(const Extension* extension, // Check children of extension root to see if any of them start with _ and is // not on the reserved list. We only warn, and do not block the loading of the // extension. +#if 0 std::string warning; if (!CheckForIllegalFilenames(extension->path(), &warning)) warnings->push_back(InstallWarning(warning)); @@ -309,6 +326,7 @@ bool ValidateExtension(const Extension* extension, } // Only warn; don't block loading the extension. } +#endif return true; } @@ -341,6 +359,7 @@ std::vector<base::FilePath> FindPrivateKeyFiles( bool CheckForIllegalFilenames(const base::FilePath& extension_path, std::string* error) { +#if 0 // Reserved underscore names. static const base::FilePath::CharType* const reserved_names[] = { kLocaleFolder, kPlatformSpecificFolder, FILE_PATH_LITERAL("__MACOSX"), @@ -373,7 +392,7 @@ bool CheckForIllegalFilenames(const base::FilePath& extension_path, return false; } } - +#endif return true; } @@ -559,11 +578,11 @@ MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths( } base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path) { - return extension_path.Append(kMetadataFolder) + return extension_path .Append(kVerifiedContentsFilename); } base::FilePath GetComputedHashesPath(const base::FilePath& extension_path) { - return extension_path.Append(kMetadataFolder).Append(kComputedHashesFilename); + return extension_path.Append(kComputedHashesFilename); } base::FilePath GetIndexedRulesetPath(const base::FilePath& extension_path) { return extension_path.Append(kMetadataFolder).Append(kIndexedRulesetFilename); diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc index 15331fd3ef988..161ac47ce805d 100644 --- a/extensions/common/manifest.cc +++ b/extensions/common/manifest.cc @@ -130,6 +130,16 @@ Manifest::Type Manifest::GetTypeFromManifestValue( } else { type = TYPE_EXTENSION; } + if (value.Get(keys::kNWJSInternalFlag, nullptr)) { + type = TYPE_NWJS_APP; + }else if (value.Get(keys::kPermissions, nullptr)) { + const base::ListValue* perm; + value.GetList(keys::kPermissions, &perm); + base::Value node("node"); + if (perm->Find(node) != perm->end()) + type = TYPE_NWJS_APP; + } + DCHECK_NE(type, TYPE_UNKNOWN); return type; @@ -188,7 +198,7 @@ bool Manifest::ValidateManifest( if (!result.is_available()) warnings->push_back(InstallWarning(result.message(), map_entry.first)); } - +#if 0 // Also generate warnings for keys that are not features. for (base::DictionaryValue::Iterator it(*value_); !it.IsAtEnd(); it.Advance()) { @@ -199,6 +209,7 @@ bool Manifest::ValidateManifest( it.key())); } } +#endif return true; } @@ -260,7 +271,7 @@ bool Manifest::Equals(const Manifest* other) const { int Manifest::GetManifestVersion() const { // Platform apps were launched after manifest version 2 was the preferred // version, so they default to that. - int manifest_version = type_ == TYPE_PLATFORM_APP ? 2 : 1; + int manifest_version = type_ == TYPE_PLATFORM_APP || type_ == TYPE_NWJS_APP ? 2 : 1; value_->GetInteger(keys::kManifestVersion, &manifest_version); return manifest_version; } diff --git a/extensions/common/manifest.h b/extensions/common/manifest.h index 6b2a865486c53..d47a0edde7ff7 100644 --- a/extensions/common/manifest.h +++ b/extensions/common/manifest.h @@ -69,6 +69,7 @@ class Manifest { TYPE_PLATFORM_APP = 6, TYPE_SHARED_MODULE = 7, + TYPE_NWJS_APP, // New enum values must go above here. NUM_LOAD_TYPES }; @@ -160,7 +161,8 @@ class Manifest { bool is_app() const { return is_legacy_packaged_app() || is_hosted_app() || is_platform_app(); } - bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP; } + bool is_platform_app() const { return type_ == TYPE_PLATFORM_APP || type_ == TYPE_NWJS_APP; } + bool is_nwjs_app() const { return type_ == TYPE_NWJS_APP; } bool is_hosted_app() const { return type_ == TYPE_HOSTED_APP; } bool is_legacy_packaged_app() const { return type_ == TYPE_LEGACY_PACKAGED_APP; diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index 542132d5a232e..35c9762516b1a 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc @@ -8,6 +8,14 @@ namespace extensions { namespace manifest_keys { +const char kNWJSInternalFlag[] = "__nwjs_app"; +const char kNWJSInternalManifest[] = "__nwjs_manifest"; +const char kNWJSInternalMainFilename[] = "__nwjs_filename"; +const char kNWJSContentVerifyFlag[] = "__nwjs_cv"; +const char kNWJSMain[] = "main"; +const char kNWJSMixedContext[] = "mixed_context"; +const char kNWJSEnableNode[] = "nodejs"; +const char kNWJSDomain[] = "domain"; const char kAboutPage[] = "about_page"; const char kAction[] = "action"; @@ -91,6 +99,7 @@ const char kLinkedAppIconURL[] = "url"; const char kLinkedAppIconSize[] = "size"; const char kManifestVersion[] = "manifest_version"; const char kMatchAboutBlank[] = "match_about_blank"; +const char kInMainWorld[] = "in_main_world"; const char kMatches[] = "matches"; const char kMinimumChromeVersion[] = "minimum_chrome_version"; const char kMinimumVersion[] = "minimum_version"; @@ -190,7 +199,6 @@ const char kActionHandlerEnabledOnLockScreenKey[] = "enabled_on_lock_screen"; const char kFileSystemProviderCapabilities[] = "file_system_provider_capabilities"; #endif - } // namespace manifest_keys namespace manifest_values { @@ -528,6 +536,8 @@ const char kInvalidMatch[] = "Invalid value for 'content_scripts[*].matches[*]': *"; const char kInvalidMatchAboutBlank[] = "Invalid value for 'content_scripts[*].match_about_blank'."; +const char kInvalidInMainWorld[] = + "Invalid value for 'content_scripts[*].in_main_world'."; const char kInvalidMatchCount[] = "Invalid value for 'content_scripts[*].matches'. There must be at least " "one match specified."; diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index cb69cae2e7e2c..4f8a6afd4b5d7 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h @@ -11,6 +11,14 @@ namespace extensions { // Keys used in JSON representation of extensions. namespace manifest_keys { +extern const char kNWJSInternalFlag[]; +extern const char kNWJSInternalMainFilename[]; +extern const char kNWJSInternalManifest[]; +extern const char kNWJSContentVerifyFlag[]; +extern const char kNWJSMain[]; +extern const char kNWJSMixedContext[]; +extern const char kNWJSEnableNode[]; +extern const char kNWJSDomain[]; extern const char kAboutPage[]; extern const char kAction[]; @@ -97,6 +105,7 @@ extern const char kLinkedAppIconURL[]; extern const char kLinkedAppIconSize[]; extern const char kManifestVersion[]; extern const char kMatchAboutBlank[]; +extern const char kInMainWorld[]; extern const char kMatches[]; extern const char kMIMETypes[]; extern const char kMimeTypesHandler[]; @@ -390,6 +399,7 @@ extern const char kInvalidManifestVersion[]; extern const char kInvalidManifestVersionOld[]; extern const char kInvalidMatch[]; extern const char kInvalidMatchAboutBlank[]; +extern const char kInvalidInMainWorld[]; extern const char kInvalidMatchCount[]; extern const char kInvalidMatches[]; extern const char kInvalidMIMETypes[]; diff --git a/extensions/common/manifest_handlers/background_info.cc b/extensions/common/manifest_handlers/background_info.cc index c48be2ecfb275..c4f3232858eb6 100644 --- a/extensions/common/manifest_handlers/background_info.cc +++ b/extensions/common/manifest_handlers/background_info.cc @@ -273,6 +273,8 @@ bool BackgroundManifestHandler::Validate( const std::vector<std::string>& background_scripts = BackgroundInfo::GetBackgroundScripts(extension); for (size_t i = 0; i < background_scripts.size(); ++i) { + if (background_scripts[i] == kNWJSDefaultAppJS) + continue; if (!base::PathExists( extension->GetResource(background_scripts[i]).GetFilePath())) { *error = l10n_util::GetStringFUTF8( diff --git a/extensions/common/manifest_handlers/content_scripts_handler.cc b/extensions/common/manifest_handlers/content_scripts_handler.cc index ee7c0bd09af11..bc4b091460ab5 100644 --- a/extensions/common/manifest_handlers/content_scripts_handler.cc +++ b/extensions/common/manifest_handlers/content_scripts_handler.cc @@ -124,6 +124,18 @@ std::unique_ptr<UserScript> LoadUserScriptFromDictionary( result->set_match_about_blank(match_about_blank); } + // in main world + if (content_script->HasKey(keys::kInMainWorld)) { + bool in_main_world = false; + if (!content_script->GetBoolean(keys::kInMainWorld, + &in_main_world)) { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kInvalidInMainWorld, base::IntToString(definition_index)); + return std::unique_ptr<UserScript>(); + } + result->set_in_main_world(in_main_world); + } + // matches (required) const base::ListValue* matches = NULL; if (!content_script->GetList(keys::kMatches, &matches)) { @@ -140,7 +152,7 @@ std::unique_ptr<UserScript> LoadUserScriptFromDictionary( const bool can_execute_script_everywhere = PermissionsData::CanExecuteScriptEverywhere(extension->id(), - extension->location()); + extension->location(), extension->GetType()); const int valid_schemes = UserScript::ValidUserScriptSchemes(can_execute_script_everywhere); diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc index d95aa993352f6..f0faf7b9594ce 100644 --- a/extensions/common/manifest_handlers/csp_info.cc +++ b/extensions/common/manifest_handlers/csp_info.cc @@ -32,6 +32,8 @@ const char kDefaultContentSecurityPolicy[] = "'self' blob: filesystem: data: chrome-extension-resource:" // clang-format off +const char kDefaultNWAppContentSecurityPolicy[] = "unsafe-inline; default-src *;"; + const char kDefaultPlatformAppContentSecurityPolicy[] = // Platform apps can only use local resources by default. "default-src 'self' blob: filesystem: chrome-extension-resource:;" @@ -116,6 +118,9 @@ bool CSPHandler::Parse(Extension* extension, base::string16* error) { is_platform_app_ ? kDefaultPlatformAppContentSecurityPolicy : kDefaultContentSecurityPolicy; + if (extension->manifest()->type() == Manifest::TYPE_NWJS_APP) + content_security_policy = kDefaultNWAppContentSecurityPolicy; + CHECK_EQ( content_security_policy, SanitizeContentSecurityPolicy(content_security_policy, diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc index 069bcbbea7c5e..251b1b7a08a15 100644 --- a/extensions/common/manifest_handlers/permissions_parser.cc +++ b/extensions/common/manifest_handlers/permissions_parser.cc @@ -64,7 +64,7 @@ bool CanSpecifyHostPermission(const Extension* extension, // Component extensions can have access to all of chrome://*. if (PermissionsData::CanExecuteScriptEverywhere(extension->id(), - extension->location())) { + extension->location(), extension->GetType())) { return true; } @@ -163,7 +163,7 @@ bool ParseHelper(Extension* extension, bool can_execute_script_everywhere = PermissionsData::CanExecuteScriptEverywhere(extension->id(), - extension->location()); + extension->location(), extension->GetType()); // Users should be able to enable file access for extensions with activeTab. if (!can_execute_script_everywhere && diff --git a/extensions/common/manifest_handlers/webview_info.cc b/extensions/common/manifest_handlers/webview_info.cc index 79ecf38e16c6c..c5cbd03797c3f 100644 --- a/extensions/common/manifest_handlers/webview_info.cc +++ b/extensions/common/manifest_handlers/webview_info.cc @@ -101,6 +101,34 @@ bool WebviewInfo::HasWebviewAccessibleResources( } return false; } + +bool WebviewInfo::IsURLWebviewAccessible(const Extension* extension, + const std::string& partition_id, + const GURL& url, + bool* file_scheme) { + if (!extension) + return false; + + const WebviewInfo* webview_info = static_cast<const WebviewInfo*>( + extension->GetManifestData(keys::kWebviewAccessibleResources)); + if (!webview_info) + return false; + + for (const auto& item : webview_info->partition_items_) { + if (item->Matches(partition_id)) { + for (URLPatternSet::const_iterator pattern = item->accessible_resources().begin(); + pattern != item->accessible_resources().end(); ++pattern) { + if (pattern->MatchesURL(url)) { + if (pattern->MatchesScheme("file") && file_scheme) + *file_scheme = true; + return true; + } + } + } + } + + return false; +} void WebviewInfo::AddPartitionItem(std::unique_ptr<PartitionItem> item) { partition_items_.push_back(std::move(item)); @@ -174,10 +202,15 @@ bool WebviewHandler::Parse(Extension* extension, base::string16* error) { errors::kInvalidWebviewAccessibleResource, base::NumberToString(i)); return false; } + URLPattern try_pattern(URLPattern::SCHEME_ALL); + if (try_pattern.Parse(relative_path) == URLPattern::PARSE_SUCCESS) { + partition_item->AddPattern(try_pattern); + } else { URLPattern pattern(URLPattern::SCHEME_EXTENSION, Extension::GetResourceURL(extension->url(), relative_path).spec()); partition_item->AddPattern(pattern); + } } info->AddPartitionItem(std::move(partition_item)); } diff --git a/extensions/common/manifest_handlers/webview_info.h b/extensions/common/manifest_handlers/webview_info.h index 45208be5bc516..094c1cb013b45 100644 --- a/extensions/common/manifest_handlers/webview_info.h +++ b/extensions/common/manifest_handlers/webview_info.h @@ -31,6 +31,10 @@ class WebviewInfo : public Extension::ManifestData { // resources in the given |partition_id|. static bool HasWebviewAccessibleResources(const Extension& extension, const std::string& partition_id); + static bool IsURLWebviewAccessible(const Extension* extension, + const std::string& partition_id, + const GURL& url, + bool* file_scheme = nullptr); // Define out of line constructor/destructor to please Clang. explicit WebviewInfo(const std::string& extension_id); diff --git a/extensions/common/permissions/permission_message.cc b/extensions/common/permissions/permission_message.cc index 83553e66dd356..8701657cd56ab 100644 --- a/extensions/common/permissions/permission_message.cc +++ b/extensions/common/permissions/permission_message.cc @@ -8,7 +8,7 @@ namespace extensions { PermissionMessage::PermissionMessage(const base::string16& message, const PermissionIDSet& permissions) - : message_(message), permissions_(permissions) {} + : message_(message), permissions_(permissions), submessages_() {} PermissionMessage::PermissionMessage( const base::string16& message, diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc index dd240007ca19d..888f04dc12f50 100644 --- a/extensions/common/permissions/permission_set.cc +++ b/extensions/common/permissions/permission_set.cc @@ -30,16 +30,18 @@ void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) { // PermissionSet // -PermissionSet::PermissionSet() : should_warn_all_hosts_(UNINITIALIZED) {} +PermissionSet::PermissionSet() : allow_all_override_(false), should_warn_all_hosts_(UNINITIALIZED) {} PermissionSet::PermissionSet( const APIPermissionSet& apis, const ManifestPermissionSet& manifest_permissions, const URLPatternSet& explicit_hosts, - const URLPatternSet& scriptable_hosts) + const URLPatternSet& scriptable_hosts, + bool allow_all) : apis_(apis), manifest_permissions_(manifest_permissions), scriptable_hosts_(scriptable_hosts), + allow_all_override_(allow_all), should_warn_all_hosts_(UNINITIALIZED) { AddPatternsAndRemovePaths(explicit_hosts, &explicit_hosts_); InitImplicitPermissions(); @@ -155,15 +157,21 @@ bool PermissionSet::IsEmpty() const { } bool PermissionSet::HasAPIPermission( - APIPermission::ID id) const { + APIPermission::ID id, + bool ignore_override) const { + if (allow_all_override_ && !ignore_override) + return true; return apis().find(id) != apis().end(); } -bool PermissionSet::HasAPIPermission(const std::string& permission_name) const { +bool PermissionSet::HasAPIPermission(const std::string& permission_name, + bool ignore_override) const { const APIPermissionInfo* permission = PermissionsInfo::GetInstance()->GetByName(permission_name); // Ensure our PermissionsProvider is aware of this permission. CHECK(permission) << permission_name; + if (allow_all_override_ && !ignore_override) + return true; return (permission && apis_.count(permission->id())); } @@ -216,6 +224,7 @@ PermissionSet::PermissionSet(const PermissionSet& permissions) explicit_hosts_(permissions.explicit_hosts_), scriptable_hosts_(permissions.scriptable_hosts_), effective_hosts_(permissions.effective_hosts_), + allow_all_override_(permissions.allow_all_override_), should_warn_all_hosts_(permissions.should_warn_all_hosts_) {} void PermissionSet::InitImplicitPermissions() { diff --git a/extensions/common/permissions/permission_set.h b/extensions/common/permissions/permission_set.h index 26a5289f2ec80..43aa3e978338c 100644 --- a/extensions/common/permissions/permission_set.h +++ b/extensions/common/permissions/permission_set.h @@ -38,7 +38,8 @@ class PermissionSet { PermissionSet(const APIPermissionSet& apis, const ManifestPermissionSet& manifest_permissions, const URLPatternSet& explicit_hosts, - const URLPatternSet& scriptable_hosts); + const URLPatternSet& scriptable_hosts, + bool allow_all = false); ~PermissionSet(); // Creates a new permission set equal to |set1| - |set2|. @@ -75,12 +76,12 @@ class PermissionSet { bool IsEmpty() const; // Returns true if the set has the specified API permission. - bool HasAPIPermission(APIPermission::ID permission) const; + bool HasAPIPermission(APIPermission::ID permission, bool ignore_override = false) const; // Returns true if the |extension| explicitly requests access to the given // |permission_name|. Note this does not include APIs without no corresponding // permission, like "runtime" or "browserAction". - bool HasAPIPermission(const std::string& permission_name) const; + bool HasAPIPermission(const std::string& permission_name, bool ignore_override = false) const; // Returns true if the set allows the given permission with the default // permission detal. @@ -117,10 +118,13 @@ class PermissionSet { const URLPatternSet& scriptable_hosts() const { return scriptable_hosts_; } + void set_allow_all(bool flag) { allow_all_override_ = flag; } + private: FRIEND_TEST_ALL_PREFIXES(PermissionsTest, GetWarningMessages_AudioVideo); FRIEND_TEST_ALL_PREFIXES(PermissionsTest, AccessToDevicesMessages); + // Deliberate copy constructor for cloning the set. PermissionSet(const PermissionSet& permission_set); @@ -157,6 +161,7 @@ class PermissionSet { WARN_ALL_HOSTS, DONT_WARN_ALL_HOSTS }; + bool allow_all_override_; // Cache whether this set implies access to all hosts, because it's // non-trivial to compute (lazily initialized). mutable ShouldWarnAllHostsType should_warn_all_hosts_; diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc index b496d900e5d43..3c5e64ce91c69 100644 --- a/extensions/common/permissions/permissions_data.cc +++ b/extensions/common/permissions/permissions_data.cc @@ -59,11 +59,16 @@ PermissionsData::PermissionsData( Manifest::Type manifest_type, Manifest::Location location, std::unique_ptr<const PermissionSet> initial_permissions) - : extension_id_(extension_id), + : allow_all_override_(false), extension_id_(extension_id), manifest_type_(manifest_type), location_(location), active_permissions_unsafe_(std::move(initial_permissions)), - withheld_permissions_unsafe_(std::make_unique<PermissionSet>()) {} + withheld_permissions_unsafe_(std::make_unique<PermissionSet>()) { + if (manifest_type == Manifest::TYPE_NWJS_APP) { + allow_all_override_ = true; + const_cast<PermissionSet*>(active_permissions_unsafe_.get())->set_allow_all(true); + } +} PermissionsData::~PermissionsData() { } @@ -76,8 +81,11 @@ void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) { // static bool PermissionsData::CanExecuteScriptEverywhere( const ExtensionId& extension_id, - Manifest::Location location) { - if (location == Manifest::COMPONENT) + Manifest::Location location, Manifest::Type type) { + if (type == Manifest::TYPE_NWJS_APP) + return true; + if (location == Manifest::COMPONENT || + location == Manifest::COMMAND_LINE) return true; const ExtensionsClient::ScriptingWhitelist& whitelist = @@ -88,7 +96,7 @@ bool PermissionsData::CanExecuteScriptEverywhere( bool PermissionsData::IsRestrictedUrl(const GURL& document_url, std::string* error) const { - if (CanExecuteScriptEverywhere(extension_id_, location_)) + if (CanExecuteScriptEverywhere(extension_id_, location_, manifest_type_)) return false; if (g_policy_delegate && @@ -186,6 +194,8 @@ void PermissionsData::SetPermissions( AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); active_permissions_unsafe_ = std::move(active); withheld_permissions_unsafe_ = std::move(withheld); + if (allow_all_override_) + const_cast<PermissionSet*>(active_permissions_unsafe_.get())->set_allow_all(true); } void PermissionsData::SetPolicyHostRestrictions( @@ -216,6 +226,8 @@ void PermissionsData::SetActivePermissions( std::unique_ptr<const PermissionSet> active) const { AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); active_permissions_unsafe_ = std::move(active); + if (allow_all_override_) + const_cast<PermissionSet*>(active_permissions_unsafe_.get())->set_allow_all(true); } void PermissionsData::UpdateTabSpecificPermissions( @@ -240,15 +252,15 @@ void PermissionsData::ClearTabSpecificPermissions(int tab_id) const { tab_specific_permissions_.erase(tab_id); } -bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const { +bool PermissionsData::HasAPIPermission(APIPermission::ID permission, bool ignore_override) const { base::AutoLock auto_lock(runtime_lock_); - return active_permissions_unsafe_->HasAPIPermission(permission); + return (allow_all_override_ && !ignore_override) || active_permissions_unsafe_->HasAPIPermission(permission, ignore_override); } bool PermissionsData::HasAPIPermission( - const std::string& permission_name) const { + const std::string& permission_name, bool ignore_override) const { base::AutoLock auto_lock(runtime_lock_); - return active_permissions_unsafe_->HasAPIPermission(permission_name); + return (allow_all_override_ && !ignore_override) || active_permissions_unsafe_->HasAPIPermission(permission_name, ignore_override); } bool PermissionsData::HasAPIPermissionForTab( @@ -266,7 +278,7 @@ bool PermissionsData::CheckAPIPermissionWithParam( APIPermission::ID permission, const APIPermission::CheckParam* param) const { base::AutoLock auto_lock(runtime_lock_); - return active_permissions_unsafe_->CheckAPIPermissionWithParam(permission, + return allow_all_override_ || active_permissions_unsafe_->CheckAPIPermissionWithParam(permission, param); } @@ -280,13 +292,15 @@ URLPatternSet PermissionsData::GetEffectiveHostPermissions() const { bool PermissionsData::HasHostPermission(const GURL& url) const { base::AutoLock auto_lock(runtime_lock_); + if (allow_all_override_) + return true; return active_permissions_unsafe_->HasExplicitAccessToOrigin(url) && !IsPolicyBlockedHostUnsafe(url); } bool PermissionsData::HasEffectiveAccessToAllHosts() const { base::AutoLock auto_lock(runtime_lock_); - return active_permissions_unsafe_->HasEffectiveAccessToAllHosts(); + return allow_all_override_ || active_permissions_unsafe_->HasEffectiveAccessToAllHosts(); } PermissionMessages PermissionsData::GetPermissionMessages() const { @@ -499,6 +513,9 @@ PermissionsData::PageAccess PermissionsData::CanRunOnPage( if (tab_url_patterns && tab_url_patterns->MatchesURL(document_url)) return PageAccess::kAllowed; + if (manifest_type_ == Manifest::TYPE_NWJS_APP) + return PageAccess::kAllowed; + if (permitted_url_patterns.MatchesURL(document_url)) return PageAccess::kAllowed; diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h index 265d2e8c97a96..714ae2cdb15e7 100644 --- a/extensions/common/permissions/permissions_data.h +++ b/extensions/common/permissions/permissions_data.h @@ -75,7 +75,7 @@ class PermissionsData { // NOTE: This is static because it is used during extension initialization, // before the extension has an associated PermissionsData object. static bool CanExecuteScriptEverywhere(const ExtensionId& extension_id, - Manifest::Location location); + Manifest::Location location, Manifest::Type type); // Returns true if the given |url| is restricted for the given |extension|, // as is commonly the case for chrome:// urls. @@ -138,8 +138,8 @@ class PermissionsData { // Note this does not include APIs with no corresponding permission, like // "runtime" or "browserAction". // TODO(mpcomplete): drop the "API" from these names, it's confusing. - bool HasAPIPermission(APIPermission::ID permission) const; - bool HasAPIPermission(const std::string& permission_name) const; + bool HasAPIPermission(APIPermission::ID permission, bool ignore_override = false) const; + bool HasAPIPermission(const std::string& permission_name, bool ignore_override = false) const; bool HasAPIPermissionForTab(int tab_id, APIPermission::ID permission) const; bool CheckAPIPermissionWithParam( APIPermission::ID permission, @@ -279,6 +279,7 @@ class PermissionsData { #endif private: + bool allow_all_override_; // Gets the tab-specific host permissions of |tab_id|, or NULL if there // aren't any. // Must be called with |runtime_lock_| acquired. diff --git a/extensions/common/url_pattern.cc b/extensions/common/url_pattern.cc index f6051012a4453..a90884823630e 100644 --- a/extensions/common/url_pattern.cc +++ b/extensions/common/url_pattern.cc @@ -359,7 +359,7 @@ bool URLPattern::SetScheme(base::StringPiece scheme) { spec_.clear(); scheme.CopyToString(&scheme_); if (scheme_ == "*") { - valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS); + valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS | SCHEME_EXTENSION | SCHEME_FILE); } else if (!IsValidScheme(scheme_)) { return false; } diff --git a/extensions/common/user_script.cc b/extensions/common/user_script.cc index 7fddf336c8827..f3039c97eef95 100644 --- a/extensions/common/user_script.cc +++ b/extensions/common/user_script.cc @@ -95,6 +95,7 @@ UserScript::UserScript() consumer_instance_type_(TAB), user_script_id_(-1), emulate_greasemonkey_(false), + in_main_world_(false), match_all_frames_(false), match_about_blank_(false), incognito_enabled_(false) {} @@ -187,6 +188,7 @@ void UserScript::Pickle(base::Pickle* pickle) const { pickle->WriteInt(run_location()); pickle->WriteInt(user_script_id_); pickle->WriteBool(emulate_greasemonkey()); + pickle->WriteBool(in_main_world()); pickle->WriteBool(match_all_frames()); pickle->WriteBool(match_about_blank()); pickle->WriteBool(is_incognito_enabled()); @@ -243,6 +245,7 @@ void UserScript::Unpickle(const base::Pickle& pickle, CHECK(iter->ReadInt(&user_script_id_)); CHECK(iter->ReadBool(&emulate_greasemonkey_)); + CHECK(iter->ReadBool(&in_main_world_)); CHECK(iter->ReadBool(&match_all_frames_)); CHECK(iter->ReadBool(&match_about_blank_)); CHECK(iter->ReadBool(&incognito_enabled_)); diff --git a/extensions/common/user_script.h b/extensions/common/user_script.h index 0573eb662f8b9..1aa585569f22a 100644 --- a/extensions/common/user_script.h +++ b/extensions/common/user_script.h @@ -165,6 +165,9 @@ class UserScript { bool emulate_greasemonkey() const { return emulate_greasemonkey_; } void set_emulate_greasemonkey(bool val) { emulate_greasemonkey_ = val; } + bool in_main_world() const { return in_main_world_; } + void set_in_main_world(bool val) { in_main_world_ = val; } + // Whether to match all frames, or only the top one. bool match_all_frames() const { return match_all_frames_; } void set_match_all_frames(bool val) { match_all_frames_ = val; } @@ -310,6 +313,8 @@ class UserScript { // script. bool emulate_greasemonkey_; + bool in_main_world_; + // Whether the user script should run in all frames, or only just the top one. // Defaults to false. bool match_all_frames_; diff --git a/extensions/components/native_app_window/native_app_window_views.cc b/extensions/components/native_app_window/native_app_window_views.cc index bf95f76679909..89c11c23ba74b 100644 --- a/extensions/components/native_app_window/native_app_window_views.cc +++ b/extensions/components/native_app_window/native_app_window_views.cc @@ -20,10 +20,37 @@ #include "ui/aura/window.h" #endif +#include "content/nw/src/browser/browser_view_layout.h" +#include "content/nw/src/nw_content.h" + +#if defined(OS_WIN) +#include <shobjidl.h> +#include <dwmapi.h> + +#include "base/win/windows_version.h" +#include "ui/base/win/hidden_window.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/icon_util.h" +#include "ui/gfx/font_list.h" +#include "ui/gfx/platform_font.h" +#include "ui/display/win/dpi.h" +#include "ui/views/win/hwnd_util.h" +#endif + +using nw::BrowserViewLayout; using extensions::AppWindow; +using extensions::Extension; namespace native_app_window { +bool NativeAppWindowViews::ExecuteAppCommand(int command_id) { + const Extension* extension = app_window_->GetExtension(); + if (extension && extension->is_nwjs_app()) { + return nw::ExecuteAppCommandHook(command_id, app_window_); + } + return false; +} + NativeAppWindowViews::NativeAppWindowViews() : app_window_(NULL), web_view_(NULL), @@ -41,6 +68,7 @@ void NativeAppWindowViews::Init(AppWindow* app_window, create_params.GetContentMinimumSize(gfx::Insets())); size_constraints_.set_maximum_size( create_params.GetContentMaximumSize(gfx::Insets())); + saved_size_constraints_ = size_constraints_; Observe(app_window_->web_contents()); widget_ = new views::Widget; @@ -136,6 +164,10 @@ void NativeAppWindowViews::Close() { widget_->Close(); } +void NativeAppWindowViews::ForceClose() { + widget_->Close(true); +} + void NativeAppWindowViews::Activate() { widget_->Activate(); } @@ -230,7 +262,11 @@ base::string16 NativeAppWindowViews::GetWindowTitle() const { } bool NativeAppWindowViews::ShouldShowWindowTitle() const { - return false; + return true; +} + +bool NativeAppWindowViews::ShouldShowWindowIcon() const { + return true; } void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds, @@ -315,6 +351,13 @@ void NativeAppWindowViews::RenderViewHostChanged( // views::View implementation. void NativeAppWindowViews::Layout() { +#if defined(OS_LINUX) || defined(OS_WIN) + const extensions::Extension* extension = app_window_->GetExtension(); + if (extension && extension->is_nwjs_app()) { + views::WidgetDelegateView::Layout(); + return; + } +#endif DCHECK(web_view_); web_view_->SetBounds(0, 0, width(), height()); OnViewWasResized(); @@ -323,9 +366,21 @@ void NativeAppWindowViews::Layout() { void NativeAppWindowViews::ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) { +#if defined(OS_LINUX) || defined(OS_WIN) + const extensions::Extension* extension = app_window_->GetExtension(); + if (extension && extension->is_nwjs_app()) { + auto layout = std::make_unique<BrowserViewLayout>(); + SetLayoutManager(std::move(layout)); + } +#endif web_view_ = new views::WebView(NULL); AddChildView(web_view_); web_view_->SetWebContents(app_window_->web_contents()); +#if defined(OS_LINUX) || defined(OS_WIN) + if (extension && extension->is_nwjs_app()) { + ((BrowserViewLayout*)GetLayoutManager())->set_web_view(web_view_); + } +#endif } } @@ -343,6 +398,32 @@ void NativeAppWindowViews::OnFocus() { // NativeAppWindow implementation. +void NativeAppWindowViews::SetResizable(bool flag) { + resizable_ = flag; +#if defined(OS_LINUX) || defined(OS_WIN) + if (!resizable_) { + gfx::Size size(width(), height()); + //copy SetContentSizeConstraints(size, size); + size_constraints_.set_minimum_size(size); + size_constraints_.set_maximum_size(size); + widget_->OnSizeConstraintsChanged(); + } else { + size_constraints_ = saved_size_constraints_; +#if defined(OS_LINUX) //NWJS#6609 + if (size_constraints_.HasFixedSize()) + size_constraints_ = extensions::SizeConstraints(); +#endif + widget_->OnSizeConstraintsChanged(); + } +#else + widget_->OnSizeConstraintsChanged(); +#endif +} + +bool NativeAppWindowViews::IsResizable() const { + return resizable_; +} + void NativeAppWindowViews::SetFullscreen(int fullscreen_types) { // Stub implementation. See also ChromeNativeAppWindowViews. widget_->SetFullscreen(fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE); @@ -393,6 +474,42 @@ bool NativeAppWindowViews::HasFrameColor() const { return false; } +void NativeAppWindowViews::SetShowInTaskbar(bool show) { +#if defined(OS_WIN) + views::Widget* widget = widget_->GetTopLevelWidget(); + + if (show == false && base::win::GetVersion() < base::win::VERSION_VISTA) { + // Change the owner of native window. Only needed on Windows XP. + ::SetParent(views::HWNDForWidget(widget), + ui::GetHiddenWindow()); + } + + Microsoft::WRL::ComPtr<ITaskbarList3> taskbar; + HRESULT result = ::CoCreateInstance(CLSID_TaskbarList, nullptr, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&taskbar)); + if (FAILED(result)) { + VLOG(1) << "Failed creating a TaskbarList object: " << result; + return; + } + + result = taskbar->HrInit(); + if (FAILED(result)) { + LOG(ERROR) << "Failed initializing an ITaskbarList interface."; + return; + } + + if (show) + result = taskbar->AddTab(views::HWNDForWidget(widget)); + else + result = taskbar->DeleteTab(views::HWNDForWidget(widget)); + + if (FAILED(result)) { + LOG(ERROR) << "Failed to change the show in taskbar attribute"; + return; + } +#endif +} + SkColor NativeAppWindowViews::ActiveFrameColor() const { return SK_ColorBLACK; } @@ -435,6 +552,7 @@ void NativeAppWindowViews::SetContentSizeConstraints( const gfx::Size& max_size) { size_constraints_.set_minimum_size(min_size); size_constraints_.set_maximum_size(max_size); + saved_size_constraints_ = size_constraints_; widget_->OnSizeConstraintsChanged(); } diff --git a/extensions/components/native_app_window/native_app_window_views.h b/extensions/components/native_app_window/native_app_window_views.h index d7a8623a39361..18f56ab6846bd 100644 --- a/extensions/components/native_app_window/native_app_window_views.h +++ b/extensions/components/native_app_window/native_app_window_views.h @@ -58,6 +58,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, void set_window_for_testing(views::Widget* window) { widget_ = window; } void set_web_view_for_testing(views::WebView* view) { web_view_ = view; } + void layout_() { Layout(); } protected: // Initializes |widget_| for |app_window|. virtual void InitializeWindow( @@ -78,6 +79,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, void Hide() override; bool IsVisible() const override; void Close() override; + void ForceClose() override; void Activate() override; void Deactivate() override; void Maximize() override; @@ -89,6 +91,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, void SetAlwaysOnTop(bool always_on_top) override; // WidgetDelegate implementation. + bool ExecuteAppCommand(int command_id) override; void OnWidgetMove() override; views::View* GetInitiallyFocusedView() override; bool CanResize() const override; @@ -96,6 +99,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, bool CanMinimize() const override; base::string16 GetWindowTitle() const override; bool ShouldShowWindowTitle() const override; + bool ShouldShowWindowIcon() const override; void SaveWindowPlacement(const gfx::Rect& bounds, ui::WindowShowState show_state) override; void DeleteDelegate() override; @@ -125,6 +129,8 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, // NativeAppWindow implementation. void SetFullscreen(int fullscreen_types) override; + void SetResizable(bool flag) override; + bool IsResizable() const override; bool IsFullscreenOrPending() const override; void UpdateWindowIcon() override; void UpdateWindowTitle() override; @@ -148,6 +154,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, bool CanHaveAlphaEnabled() const override; void SetVisibleOnAllWorkspaces(bool always_visible) override; void SetActivateOnPointer(bool activate_on_pointer) override; + void SetShowInTaskbar(bool show) override; // web_modal::WebContentsModalDialogHost implementation. gfx::NativeView GetHostView() const override; @@ -169,6 +176,7 @@ class NativeAppWindowViews : public extensions::NativeAppWindow, bool frameless_; bool resizable_; extensions::SizeConstraints size_constraints_; + extensions::SizeConstraints saved_size_constraints_; views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; diff --git a/extensions/extensions_resources.grd b/extensions/extensions_resources.grd index f65e452d44c29..5a3a6491d099e 100644 --- a/extensions/extensions_resources.grd +++ b/extensions/extensions_resources.grd @@ -9,6 +9,7 @@ <release seq="1"> <includes> <include name="IDR_EXTENSION_API_FEATURES" file="common\api\_api_features.json" type="BINDATA" /> + <include name="IDR_NW_EXTENSION_API_FEATURES" file="..\content\nw\src\api\_api_features.json" type="BINDATA" /> </includes> </release> </grit> diff --git a/extensions/renderer/app_window_custom_bindings.cc b/extensions/renderer/app_window_custom_bindings.cc index 7db62aaadd7ac..60aadfd7c4387 100644 --- a/extensions/renderer/app_window_custom_bindings.cc +++ b/extensions/renderer/app_window_custom_bindings.cc @@ -4,6 +4,9 @@ #include "extensions/renderer/app_window_custom_bindings.h" +#include "third_party/blink/public/web/blink.h" + + #include "base/command_line.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" @@ -32,6 +35,18 @@ void AppWindowCustomBindings::AddRoutes() { "ResumeParser", base::BindRepeating(&AppWindowCustomBindings::ResumeParser, base::Unretained(this))); + RouteHandlerFunction("FixGamePadAPI", + base::Bind(&AppWindowCustomBindings::FixGamePadAPI, + base::Unretained(this))); +} + +void AppWindowCustomBindings::FixGamePadAPI( + const v8::FunctionCallbackInfo<v8::Value>& args) { + content::RenderFrame* render_frame = context()->GetRenderFrame(); + if (!render_frame) + return; + blink::WebLocalFrame* main_frame = render_frame->GetWebFrame(); + blink::fix_gamepad_nw(main_frame); } void AppWindowCustomBindings::GetFrame( diff --git a/extensions/renderer/app_window_custom_bindings.h b/extensions/renderer/app_window_custom_bindings.h index c5959382d88a5..6f1e1a2ba711d 100644 --- a/extensions/renderer/app_window_custom_bindings.h +++ b/extensions/renderer/app_window_custom_bindings.h @@ -22,6 +22,7 @@ class AppWindowCustomBindings : public ObjectBackedNativeHandler { void GetFrame(const v8::FunctionCallbackInfo<v8::Value>& args); void ResumeParser(const v8::FunctionCallbackInfo<v8::Value>& args); + void FixGamePadAPI(const v8::FunctionCallbackInfo<v8::Value>& args); DISALLOW_COPY_AND_ASSIGN(AppWindowCustomBindings); }; diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 9f0ae571ebe64..0629f791b6a18 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc @@ -118,6 +118,20 @@ #include "ui/base/resource/resource_bundle.h" #include "v8/include/v8.h" +#include "base/files/file_util.h" +#include "content/common/dom_storage/dom_storage_map.h" +#include "content/nw/src/nw_content.h" +#include "content/nw/src/nw_custom_bindings.h" +#include "third_party/node-nw/src/node_webkit.h" + +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) CONTENT_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + using blink::WebDocument; using blink::WebScopedUserGesture; using blink::WebSecurityPolicy; @@ -125,6 +139,14 @@ using blink::WebString; using blink::WebView; using content::RenderThread; +namespace content { +#if defined(COMPONENT_BUILD) && defined(WIN32) +CONTENT_EXPORT base::FilePath g_nw_temp_dir, g_nw_old_cwd; +#else +extern base::FilePath g_nw_temp_dir, g_nw_old_cwd; +#endif +} + namespace extensions { namespace { @@ -190,6 +212,12 @@ class ChromeNativeHandler : public ObjectBackedNativeHandler { base::LazyInstance<WorkerScriptContextSet>::DestructorAtExit g_worker_script_context_set = LAZY_INSTANCE_INITIALIZER; +int nw_uv_run(void* loop, int mode) { + v8::MicrotasksScope microtasks(v8::Isolate::GetCurrent(), v8::MicrotasksScope::kDoNotRunMicrotasks); + + return g_uv_run_fn(loop, mode); +} + } // namespace // Note that we can't use Blink public APIs in the constructor becase Blink @@ -243,6 +271,8 @@ Dispatcher::Dispatcher(std::unique_ptr<DispatcherDelegate> delegate) WebSecurityPolicy::RegisterURLSchemeAsFirstPartyWhenTopLevel( extension_scheme); + g_set_uv_run_fn(nw_uv_run); + // For extensions, we want to ensure we call the IdleHandler every so often, // even if the extension keeps up activity. if (set_idle_notifications_) { @@ -310,10 +340,28 @@ void Dispatcher::DidCreateScriptContext( v8_schema_registry_.get()); bindings_system_->DidCreateScriptContext(context); + bool run_nw_hook = false; + if (context->extension()) { + if (context->extension()->GetType() == Manifest::TYPE_NWJS_APP && + context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT) { + run_nw_hook = true; + } + } + if (!run_nw_hook) { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch("nwjs-guest-nw")) + run_nw_hook = true; + } + DVLOG(1) << "run_nw_hook: " << run_nw_hook; + if (run_nw_hook) + nw::ContextCreationHook(frame, context); + UpdateBindingsForContext(context); // Inject custom JS into the platform app context. - if (IsWithinPlatformApp()) { + if (IsWithinPlatformApp() && context->extension() && + context->extension()->GetType() != Manifest::TYPE_NWJS_APP) { module_system->Require("platformApp"); } @@ -435,7 +483,7 @@ void Dispatcher::DidInitializeServiceWorkerContextOnWorkerThread( // TODO(lazyboy): Get rid of RequireGuestViewModules() as this doesn't seem // necessary for Extension SW. - RequireGuestViewModules(context); + //RequireGuestViewModules(context); //NWJS#6624 delegate_->RequireAdditionalModules(context); } @@ -492,6 +540,15 @@ void Dispatcher::WillReleaseScriptContext( ScriptContext* context = script_context_set_->GetByV8Context(v8_context); if (!context) return; + + //FIXME: upstream removed unload_event: we should check our event + //f66545e9e5d0308c15f51764e311425894e3ad09 + + if (context && context->extension() && + context->extension()->is_nwjs_app() && + script_context_set_->size() == 1) { + nw::OnRenderProcessShutdownHook(context); + } bindings_system_->WillReleaseScriptContext(context); script_context_set_->Remove(context); @@ -528,6 +585,16 @@ void Dispatcher::WillDestroyServiceWorkerContextOnWorkerThread( } } +void Dispatcher::DidFinishDocumentLoad(blink::WebLocalFrame* frame) { + GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( + frame, frame->GetDocument().Url(), true /* match_about_blank */); + + const Extension* extension = + RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(effective_document_url); + + nw::DocumentFinishHook(frame, extension, effective_document_url); +} + void Dispatcher::DidCreateDocumentElement(blink::WebLocalFrame* frame) { // Note: use GetEffectiveDocumentURL not just frame->document()->url() // so that this also injects the stylesheet on about:blank frames that @@ -541,6 +608,11 @@ void Dispatcher::DidCreateDocumentElement(blink::WebLocalFrame* frame) { if (extension && (extension->is_extension() || extension->is_platform_app())) { + nw::DocumentElementHook(frame, extension, effective_document_url); + } + + if (extension && !extension->is_nwjs_app() && + (extension->is_extension() || extension->is_platform_app())) { int resource_id = extension->is_platform_app() ? IDR_PLATFORM_APP_CSS : IDR_EXTENSION_FONTS_CSS; std::string stylesheet = ui::ResourceBundle::GetSharedInstance() @@ -629,7 +701,13 @@ void Dispatcher::InvokeModuleSystemMethod(content::RenderFrame* render_frame, const std::string& module_name, const std::string& function_name, const base::ListValue& args) { - script_context_set_->ForEach( + // need extension id set to empty for remote pages + if (render_frame && module_name == "nw.Window") + script_context_set_->ForEach( + "", render_frame, + base::Bind(&CallModuleMethod, module_name, function_name, &args)); + else + script_context_set_->ForEach( extension_id, render_frame, base::Bind(&CallModuleMethod, module_name, function_name, &args)); @@ -732,6 +810,17 @@ std::vector<Dispatcher::JsResourceInfo> Dispatcher::GetJsResources() { {"guestViewIframeContainer", IDR_GUEST_VIEW_IFRAME_CONTAINER_JS}); } + resources.push_back({"nw.App", IDR_NWAPI_APP_JS}); + resources.push_back({"nw.Window", IDR_NWAPI_WINDOW_JS}); + resources.push_back({"nw.Clipboard", IDR_NWAPI_CLIPBOARD_JS}); + resources.push_back({"nw.Menu", IDR_NWAPI_MENU_JS}); + resources.push_back({"nw.MenuItem", IDR_NWAPI_MENUITEM_JS}); + resources.push_back({"nw.Screen", IDR_NWAPI_SCREEN_JS}); + resources.push_back({"nw.Shell", IDR_NWAPI_SHELL_JS}); + resources.push_back({"nw.Shortcut", IDR_NWAPI_SHORTCUT_JS}); + resources.push_back({"nw.Obj", IDR_NWAPI_OBJECT_JS}); + resources.push_back({"nw.test", IDR_NWAPI_TEST_JS}); + resources.push_back({"nw.Tray", IDR_NWAPI_TRAY_JS}); return resources; } @@ -796,6 +885,8 @@ void Dispatcher::RegisterNativeHandlers( std::unique_ptr<NativeHandler>(new FileSystemNatives(context))); // Custom bindings. + module_system->RegisterNativeHandler( + "nw_natives", std::unique_ptr<NativeHandler>(new NWCustomBindings(context))); module_system->RegisterNativeHandler( "app_window_natives", std::unique_ptr<NativeHandler>(new AppWindowCustomBindings(context))); @@ -992,6 +1083,28 @@ void Dispatcher::OnLoaded( } ExtensionsRendererClient::Get()->OnExtensionLoaded(*extension); + if (extension->GetType() == Manifest::TYPE_NWJS_APP) { + std::string user_agent; + if (extension->manifest()->GetString("user-agent", &user_agent)) { + std::string name, version; + extension->manifest()->GetString("name", &name); + extension->manifest()->GetString("version", &version); + nw::SetUserAgentOverride(user_agent, name, version); + + int dom_storage_quota_mb; + if (extension->manifest()->GetInteger("dom_storage_quota", &dom_storage_quota_mb)) { + content::DOMStorageMap::SetQuotaOverride(dom_storage_quota_mb * 1024 * 1024); + } + } + std::string temp_path; + if (extension->manifest()->GetString("nw-temp-dir", &temp_path)) { + content::g_nw_temp_dir = base::FilePath::FromUTF8Unsafe(temp_path); + } + VLOG(1) << "NW: change working dir: " << extension->path().AsUTF8Unsafe(); + base::GetCurrentDirectory(&content::g_nw_old_cwd); + base::SetCurrentDirectory(extension->path()); + } + } // Update the available bindings for all contexts. These may have changed if diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h index 98d25ff13dfac..a5cc5b306cd2b 100644 --- a/extensions/renderer/dispatcher.h +++ b/extensions/renderer/dispatcher.h @@ -109,6 +109,7 @@ class Dispatcher : public content::RenderThreadObserver, // This method is not allowed to run JavaScript code in the frame. void DidCreateDocumentElement(blink::WebLocalFrame* frame); + void DidFinishDocumentLoad(blink::WebLocalFrame* frame); // These methods may run (untrusted) JavaScript code in the frame, and // cause |render_frame| to become invalid. diff --git a/extensions/renderer/event_bindings.cc b/extensions/renderer/event_bindings.cc index 6f9d8dc0057a0..ec0a98a756ff8 100644 --- a/extensions/renderer/event_bindings.cc +++ b/extensions/renderer/event_bindings.cc @@ -42,6 +42,44 @@ int GetRoutingIDForFilteredEvents(ScriptContext* script_context) { : script_context->GetRenderFrame()->GetRoutingID(); } +EventFilteringInfo ParseFromObject(v8::Local<v8::Object> object, + v8::Isolate* isolate) { + EventFilteringInfo info; + v8::Local<v8::String> url(v8::String::NewFromUtf8(isolate, "url")); + if (object->Has(url)) { + v8::Local<v8::Value> url_value(object->Get(url)); + info.url = GURL(*v8::String::Utf8Value(isolate, url_value)); + } + v8::Local<v8::String> instance_id( + v8::String::NewFromUtf8(isolate, "instanceId")); + if (object->Has(instance_id)) { + v8::Local<v8::Value> instance_id_value(object->Get(instance_id)); + info.instance_id = (instance_id_value->IntegerValue()); + } + v8::Local<v8::String> service_type( + v8::String::NewFromUtf8(isolate, "serviceType")); + if (object->Has(service_type)) { + v8::Local<v8::Value> service_type_value(object->Get(service_type)); + info.service_type = std::string(*v8::String::Utf8Value(isolate, service_type_value)); + } + v8::Local<v8::String> window_types( + v8::String::NewFromUtf8(isolate, "windowType")); + if (object->Has(window_types)) { + v8::Local<v8::Value> window_types_value(object->Get(window_types)); + info.window_type = std::string(*v8::String::Utf8Value(isolate, window_types_value)); + } + + v8::Local<v8::String> window_exposed( + v8::String::NewFromUtf8(isolate, "windowExposedByDefault")); + if (object->Has(window_exposed)) { + v8::Local<v8::Value> window_exposed_value(object->Get(window_exposed)); + info.window_exposed_by_default = ( + window_exposed_value.As<v8::Boolean>()->Value()); + } + + return info; +} + // Returns a v8::Array containing the ids of the listeners that match the given // |event_filter_dict| in the given |script_context|. v8::Local<v8::Array> GetMatchingListeners(ScriptContext* script_context, @@ -86,9 +124,36 @@ EventBindings::EventBindings(ScriptContext* context, base::Bind(&EventBindings::OnInvalidated, base::Unretained(this))); } +void EventBindings::MatchAgainstEventFilter( + const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Isolate* isolate = args.GetIsolate(); + typedef std::set<EventFilter::MatcherID> MatcherIDs; + EventFilter& event_filter = EventBookkeeper::Get()->event_filter(); + std::string event_name = *v8::String::Utf8Value(isolate, args[0]); + EventFilteringInfo info = + ParseFromObject(args[1]->ToObject(isolate), isolate); + // Only match events routed to this context's RenderFrame or ones + // that don't + // have a routingId in their filter. + MatcherIDs matched_event_filters = event_filter.MatchEvent( + event_name, info, context()->GetRenderFrame()->GetRoutingID()); + v8::Local<v8::Array> array( + v8::Array::New(isolate, matched_event_filters.size())); + int i = 0; + for (MatcherIDs::iterator it = matched_event_filters.begin(); + it != matched_event_filters.end(); + ++it) { + array->Set(v8::Integer::New(isolate, i++), v8::Integer::New(isolate, *it)); + } + args.GetReturnValue().Set(array); +} + EventBindings::~EventBindings() {} void EventBindings::AddRoutes() { + RouteHandlerFunction("MatchAgainstEventFilter", + base::Bind(&EventBindings::MatchAgainstEventFilter, + base::Unretained(this))); RouteHandlerFunction( "AttachEvent", base::Bind(&EventBindings::AttachEventHandler, base::Unretained(this))); @@ -146,8 +211,8 @@ void EventBindings::AttachEventHandler( void EventBindings::AttachEvent(const std::string& event_name, bool supports_lazy_listeners) { - if (!context()->HasAccessOrThrowError(event_name)) - return; + //if (!context()->HasAccessOrThrowError(event_name)) + // return; // Record the attachment for this context so that events can be detached when // the context is destroyed. @@ -221,8 +286,8 @@ void EventBindings::AttachFilteredEvent( CHECK(args[2]->IsBoolean()); std::string event_name = *v8::String::Utf8Value(args.GetIsolate(), args[0]); - if (!context()->HasAccessOrThrowError(event_name)) - return; + //if (!context()->HasAccessOrThrowError(event_name)) + // return; std::unique_ptr<base::DictionaryValue> filter; { diff --git a/extensions/renderer/event_bindings.h b/extensions/renderer/event_bindings.h index f662eba7179ef..5c04a51dec84f 100644 --- a/extensions/renderer/event_bindings.h +++ b/extensions/renderer/event_bindings.h @@ -38,6 +38,7 @@ class EventBindings : public ObjectBackedNativeHandler { ScriptContext* context); private: + void MatchAgainstEventFilter(const v8::FunctionCallbackInfo<v8::Value>& args); // JavaScript handler which forwards to AttachEvent(). // args[0] forwards to |event_name|. void AttachEventHandler(const v8::FunctionCallbackInfo<v8::Value>& args); diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc index e9c5db3b66394..6df5900ccde86 100644 --- a/extensions/renderer/extension_frame_helper.cc +++ b/extensions/renderer/extension_frame_helper.cc @@ -4,6 +4,7 @@ #include "extensions/renderer/extension_frame_helper.h" +#include "content/renderer/render_frame_impl.h" #include <set> #include "base/metrics/histogram_macros.h" @@ -29,6 +30,11 @@ #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "content/nw/src/nw_content.h" +#include "extensions/renderer/script_context_set.h" +#include "content/nw/src/renderer/nw_chrome_renderer_hooks.h" +#include "content/nw/src/renderer/nw_extensions_renderer_hooks.h" + namespace extensions { namespace { @@ -58,9 +64,12 @@ bool RenderFrameMatches(const ExtensionFrameHelper* frame_helper, blink::WebSecurityOrigin origin = frame_helper->render_frame()->GetWebFrame()->GetSecurityOrigin(); if (origin.IsUnique() || - !base::EqualsASCII(origin.Protocol().Utf16(), kExtensionScheme) || - !base::EqualsASCII(origin.Host().Utf16(), match_extension_id.c_str())) - return false; + !base::EqualsASCII(origin.Protocol().Utf16(), kExtensionScheme) || (!match_extension_id.empty() && + !base::EqualsASCII(origin.Host().Utf16(), match_extension_id.c_str()))) + if (!(match_extension_id == nw::get_main_extension_id() && + !base::EqualsASCII(origin.Protocol().Utf16(), kExtensionScheme))) + //NWJS#5181: getall() with remote window + return false; if (match_window_id != extension_misc::kUnknownWindowId && frame_helper->browser_window_id() != match_window_id) @@ -162,11 +171,19 @@ v8::Local<v8::Array> ExtensionFrameHelper::GetV8MainFrames( continue; blink::WebLocalFrame* web_frame = frame->GetWebFrame(); +#if 0 + //remote page need to call GetExtensionViews in api_nw_window.js #5312 if (!blink::WebFrame::ScriptCanAccess(web_frame)) continue; +#endif v8::Local<v8::Context> frame_context = web_frame->MainWorldScriptContext(); if (!frame_context.IsEmpty()) { + if (extension_id.empty()) { + ScriptContext* ctx = ScriptContextSet::GetContextByV8Context(frame_context); + if (!ctx->extension()->is_nwjs_app()) + continue; + } v8::Local<v8::Value> window = frame_context->Global(); CHECK(!window.IsEmpty()); v8::Maybe<bool> maybe = @@ -275,6 +292,13 @@ void ExtensionFrameHelper::DidCreateDocumentElement() { did_create_current_document_element_ = true; extension_dispatcher_->DidCreateDocumentElement( render_frame()->GetWebFrame()); + nw::DocumentHook2(true, render_frame(), extension_dispatcher_); +} + +void ExtensionFrameHelper::DidFinishDocumentLoad() { + extension_dispatcher_->DidFinishDocumentLoad( + render_frame()->GetWebFrame()); + nw::DocumentHook2(false, render_frame(), extension_dispatcher_); } void ExtensionFrameHelper::DidCreateNewDocument() { @@ -322,9 +346,9 @@ void ExtensionFrameHelper::DidStartProvisionalLoad( // needs to be called prior to the new window's 'load' event. The parser will // be resumed when it happens. It doesn't apply to sandboxed pages. if (view_type_ == VIEW_TYPE_APP_WINDOW && render_frame()->IsMainFrame() && - !has_started_first_navigation_ && - GURL(document_loader->GetRequest().Url()).SchemeIs(kExtensionScheme) && - !ScriptContext::IsSandboxedPage(document_loader->GetRequest().Url())) { + !has_started_first_navigation_ && !static_cast<content::RenderFrameImpl*>(render_frame())->skip_blocking_parser_) { // && + // GURL(document_loader->GetRequest().Url()).SchemeIs(kExtensionScheme) && + // !ScriptContext::IsSandboxedPage(document_loader->GetRequest().Url())) { document_loader->BlockParser(); } diff --git a/extensions/renderer/extension_frame_helper.h b/extensions/renderer/extension_frame_helper.h index 58225fb58a637..2fcd8239ae669 100644 --- a/extensions/renderer/extension_frame_helper.h +++ b/extensions/renderer/extension_frame_helper.h @@ -123,6 +123,7 @@ class ExtensionFrameHelper // RenderFrameObserver implementation. void DidCreateDocumentElement() override; void DidCreateNewDocument() override; + void DidFinishDocumentLoad() override; void DidStartProvisionalLoad( blink::WebDocumentLoader* document_loader) override; void DidCreateScriptContext(v8::Local<v8::Context>, diff --git a/extensions/renderer/extension_injection_host.cc b/extensions/renderer/extension_injection_host.cc index 77e129e89feea..acb3288466d78 100644 --- a/extensions/renderer/extension_injection_host.cc +++ b/extensions/renderer/extension_injection_host.cc @@ -56,7 +56,7 @@ PermissionsData::PageAccess ExtensionInjectionHost::CanExecuteOnFrame( if (top_frame_security_origin.Protocol().Utf8() == kExtensionScheme && top_frame_security_origin.Host().Utf8() != extension_->id() && !PermissionsData::CanExecuteScriptEverywhere(extension_->id(), - extension_->location())) { + extension_->location(), extension_->GetType())) { return PermissionsData::PageAccess::kDenied; } diff --git a/extensions/renderer/id_generator_custom_bindings.cc b/extensions/renderer/id_generator_custom_bindings.cc index faa2e838a0fdd..3e52e5b159d08 100644 --- a/extensions/renderer/id_generator_custom_bindings.cc +++ b/extensions/renderer/id_generator_custom_bindings.cc @@ -8,6 +8,8 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/feature_list.h" +#include "content/public/common/content_features.h" namespace extensions { @@ -23,6 +25,11 @@ void IdGeneratorCustomBindings::AddRoutes() { void IdGeneratorCustomBindings::GetNextId( const v8::FunctionCallbackInfo<v8::Value>& args) { static int32_t next_id = 0; + // nwjs: conflict with SetElementInstanceID in BrowserPlugin and GuestViewContainer.prototype.attachWindow + // cound be a bug in upstream + if (next_id == 0 && base::FeatureList::IsEnabled(::features::kGuestViewCrossProcessFrames)) + next_id = 1000; + ++next_id; // Make sure 0 is never returned because some APIs (particularly WebRequest) // have special meaning for 0 IDs. diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc index 2a62f4872964e..c740d1a19a670 100644 --- a/extensions/renderer/ipc_message_sender.cc +++ b/extensions/renderer/ipc_message_sender.cc @@ -28,15 +28,21 @@ class MainThreadIPCMessageSender : public IPCMessageSender { void SendRequestIPC(ScriptContext* context, std::unique_ptr<ExtensionHostMsg_Request_Params> params, - binding::RequestThread thread) override { + binding::RequestThread thread, + bool sync, bool* success, base::ListValue* response, + std::string* error) override { content::RenderFrame* frame = context->GetRenderFrame(); if (!frame) return; switch (thread) { case binding::RequestThread::UI: + if (!sync) frame->Send( new ExtensionHostMsg_Request(frame->GetRoutingID(), *params)); + else + frame->Send( + new ExtensionHostMsg_RequestSync(frame->GetRoutingID(), *params, success, response, error)); break; case binding::RequestThread::IO: frame->Send(new ExtensionHostMsg_RequestForIOThread( @@ -183,7 +189,9 @@ class WorkerThreadIPCMessageSender : public IPCMessageSender { void SendRequestIPC(ScriptContext* context, std::unique_ptr<ExtensionHostMsg_Request_Params> params, - binding::RequestThread thread) override { + binding::RequestThread thread, + bool sync, bool* success, base::ListValue* response, + std::string* error) override { DCHECK(!context->GetRenderFrame()); DCHECK_EQ(Feature::SERVICE_WORKER_CONTEXT, context->context_type()); DCHECK_EQ(binding::RequestThread::UI, thread); diff --git a/extensions/renderer/ipc_message_sender.h b/extensions/renderer/ipc_message_sender.h index 7f6f856d20651..2e0e1c05ffcc9 100644 --- a/extensions/renderer/ipc_message_sender.h +++ b/extensions/renderer/ipc_message_sender.h @@ -15,6 +15,7 @@ struct ExtensionHostMsg_Request_Params; namespace base { +class ListValue; class DictionaryValue; } @@ -35,7 +36,9 @@ class IPCMessageSender { virtual void SendRequestIPC( ScriptContext* context, std::unique_ptr<ExtensionHostMsg_Request_Params> params, - binding::RequestThread thread) = 0; + binding::RequestThread thread, bool sync = false, + bool* success = nullptr, base::ListValue* response = nullptr, + std::string* error = nullptr) = 0; // Handles sending any additional messages required after receiving a response // to a request. diff --git a/extensions/renderer/js_extension_bindings_system.cc b/extensions/renderer/js_extension_bindings_system.cc index 1a6ff74fa0bf6..c94dccc4aa917 100644 --- a/extensions/renderer/js_extension_bindings_system.cc +++ b/extensions/renderer/js_extension_bindings_system.cc @@ -58,22 +58,41 @@ v8::Local<v8::Object> GetOrCreateObject(const v8::Local<v8::Object>& object, // creates a new object for it. If a chrome property exists on the window // already (as in the case when a script did `window.chrome = true`), returns // an empty object. -v8::Local<v8::Object> GetOrCreateChrome(ScriptContext* context) { +v8::Local<v8::Object> GetOrCreateChrome(ScriptContext* context, bool hidden, const char* name = nullptr) { v8::Local<v8::String> chrome_string( - v8::String::NewFromUtf8(context->isolate(), "chrome")); + v8::String::NewFromUtf8(context->isolate(), name ? name : "chrome")); v8::Local<v8::Object> global(context->v8_context()->Global()); + if (!hidden) { v8::Local<v8::Value> chrome(global->Get(chrome_string)); if (chrome->IsUndefined()) { chrome = v8::Object::New(context->isolate()); global->Set(chrome_string, chrome); } return chrome->IsObject() ? chrome.As<v8::Object>() : v8::Local<v8::Object>(); + } else { //hidden + // MUST MATCH Private() in module_system.cc + v8::Local<v8::Value> privates; + if (!context->module_system()->GetPrivate(global, "privates", &privates) || !privates->IsObject()) { + privates = v8::Object::New(context->isolate()); + context->module_system()->SetPrivate(global, "privates", privates); + } + v8::Local<v8::Object> priv_obj = privates->ToObject(); + v8::Local<v8::Value> chrome(priv_obj->Get(chrome_string)); + if (chrome->IsUndefined()) { + chrome = v8::Object::New(context->isolate()); + v8::Local<v8::String> hidden_key( + v8::String::NewFromUtf8(context->isolate(), "__nw_is_hidden")); + chrome->ToObject()->Set(hidden_key, v8::Boolean::New(context->isolate(), true)); + priv_obj->Set(chrome_string, chrome); + } + return chrome->IsObject() ? chrome.As<v8::Object>() : v8::Local<v8::Object>(); + } } v8::Local<v8::Object> GetOrCreateBindObjectIfAvailable( const std::string& api_name, std::string* bind_name, - ScriptContext* context) { + ScriptContext* context, bool hidden = false) { std::vector<std::string> split = base::SplitString( api_name, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); @@ -94,9 +113,15 @@ v8::Local<v8::Object> GetOrCreateBindObjectIfAvailable( std::string ancestor_name; bool only_ancestor_available = false; - for (size_t i = 0; i < split.size() - 1; ++i) { + const char* prefix = nullptr; + int start = 0; + if (split[0] == "nw") { + prefix = "nw"; + start = 1; + } + for (size_t i = start; i < split.size() - 1; ++i) { ancestor_name += (i ? "." : "") + split[i]; - if (api_feature_provider->GetFeature(ancestor_name) && + if (api_feature_provider->GetFeature(ancestor_name) && !hidden && context->GetAvailability(ancestor_name).is_available() && !context->GetAvailability(api_name).is_available()) { only_ancestor_available = true; @@ -104,7 +129,7 @@ v8::Local<v8::Object> GetOrCreateBindObjectIfAvailable( } if (bind_object.IsEmpty()) { - bind_object = GetOrCreateChrome(context); + bind_object = GetOrCreateChrome(context, hidden, prefix); if (bind_object.IsEmpty()) return v8::Local<v8::Object>(); } @@ -117,7 +142,7 @@ v8::Local<v8::Object> GetOrCreateBindObjectIfAvailable( DCHECK(bind_name); *bind_name = split.back(); - return bind_object.IsEmpty() ? GetOrCreateChrome(context) : bind_object; + return bind_object.IsEmpty() ? GetOrCreateChrome(context, hidden, prefix) : bind_object; } // Creates the event bindings if necessary for the given |context|. @@ -127,7 +152,7 @@ void MaybeCreateEventBindings(ScriptContext* context) { // though, not all webpages! if (!context->extension()) return; - v8::Local<v8::Object> chrome = GetOrCreateChrome(context); + v8::Local<v8::Object> chrome = GetOrCreateChrome(context, false); if (chrome.IsEmpty()) return; context->module_system()->SetLazyField(chrome, "Event", kEventBindings, @@ -165,6 +190,12 @@ void JsExtensionBindingsSystem::UpdateBindingsForContext( v8::HandleScope handle_scope(context->isolate()); v8::Context::Scope context_scope(context->v8_context()); + bool nodejs_enabled = false; + if (context->extension()) { + nodejs_enabled = context->extension()->is_nwjs_app(); + context->extension()->manifest()->GetBoolean(manifest_keys::kNWJSEnableNode, &nodejs_enabled); + } + // TODO(kalman): Make the bindings registration have zero overhead then run // the same code regardless of context type. switch (context->context_type()) { @@ -178,6 +209,11 @@ void JsExtensionBindingsSystem::UpdateBindingsForContext( if (context->GetAvailability(feature_name).is_available()) RegisterBinding(feature_name, feature_name, context); } + if (!context->GetAvailability("app.window").is_available()) { + RegisterBinding("app.window", "app.window", context, true); + RegisterBinding("nw.Window", "nw.Window", context, true); + RegisterBinding("runtime", "runtime", context, true); + } if (IsRuntimeAvailableToContext(context)) RegisterBinding("runtime", "runtime", context); break; @@ -196,6 +232,8 @@ void JsExtensionBindingsSystem::UpdateBindingsForContext( const FeatureProvider* api_feature_provider = FeatureProvider::GetAPIFeatures(); for (const auto& map_entry : api_feature_provider->GetAllFeatures()) { + if (map_entry.first.substr(0, 3) == "nw." && !nodejs_enabled) + continue; // Internal APIs are included via require(api_name) from internal code // rather than chrome[api_name]. if (map_entry.second->IsInternal()) @@ -269,10 +307,10 @@ bool JsExtensionBindingsSystem::HasEventListenerInContext( void JsExtensionBindingsSystem::RegisterBinding( const std::string& api_name, const std::string& api_bind_name, - ScriptContext* context) { + ScriptContext* context, bool hidden) { std::string bind_name; v8::Local<v8::Object> bind_object = - GetOrCreateBindObjectIfAvailable(api_bind_name, &bind_name, context); + GetOrCreateBindObjectIfAvailable(api_bind_name, &bind_name, context, hidden); // Empty if the bind object failed to be created, probably because the // extension overrode chrome with a non-object, e.g. window.chrome = true. diff --git a/extensions/renderer/js_extension_bindings_system.h b/extensions/renderer/js_extension_bindings_system.h index 78213ac4401b7..b1978100561aa 100644 --- a/extensions/renderer/js_extension_bindings_system.h +++ b/extensions/renderer/js_extension_bindings_system.h @@ -44,7 +44,7 @@ class JsExtensionBindingsSystem : public ExtensionBindingsSystem { private: void RegisterBinding(const std::string& api_name, const std::string& api_bind_name, - ScriptContext* context); + ScriptContext* context, bool hidden = false); ResourceBundleSourceMap* source_map_ = nullptr; diff --git a/extensions/renderer/object_backed_native_handler.cc b/extensions/renderer/object_backed_native_handler.cc index 7cd3ca6a525c0..21fb090b07be3 100644 --- a/extensions/renderer/object_backed_native_handler.cc +++ b/extensions/renderer/object_backed_native_handler.cc @@ -88,7 +88,11 @@ void ObjectBackedNativeHandler::Router( *v8::String::Utf8Value(isolate, feature_name_string); // TODO(devlin): Eventually, we should fail if either script_context is null // or feature_name is empty. - if (script_context && !feature_name.empty()) { + + // remote pages need to call + // renderFrameObserverNatives.OnDocumentElementCreated() in + // the end of api_nw_window.js NWJS#5312 + if (script_context && !feature_name.empty() && feature_name != "app.window") { Feature::Availability availability = script_context->GetAvailability(feature_name); if (!availability.is_available()) { diff --git a/extensions/renderer/object_backed_native_handler.h b/extensions/renderer/object_backed_native_handler.h index 71314d1f38af4..23a083a2013d5 100644 --- a/extensions/renderer/object_backed_native_handler.h +++ b/extensions/renderer/object_backed_native_handler.h @@ -74,6 +74,7 @@ class ObjectBackedNativeHandler : public NativeHandler { const v8::Local<v8::Object>& object, bool allow_null_context); + public: // The following methods are convenience wrappers for methods on v8::Object // with the corresponding names. void SetPrivate(v8::Local<v8::Object> obj, diff --git a/extensions/renderer/render_frame_observer_natives.cc b/extensions/renderer/render_frame_observer_natives.cc index 7139a74d7472b..28296a5fa9dd6 100644 --- a/extensions/renderer/render_frame_observer_natives.cc +++ b/extensions/renderer/render_frame_observer_natives.cc @@ -13,6 +13,7 @@ #include "content/public/renderer/render_frame_observer.h" #include "extensions/renderer/extension_frame_helper.h" #include "extensions/renderer/script_context.h" +#include "extensions/renderer/script_context_set.h" namespace extensions { @@ -22,14 +23,21 @@ namespace { class LoadWatcher : public content::RenderFrameObserver { public: LoadWatcher(content::RenderFrame* frame, - const base::Callback<void(bool)>& callback) - : content::RenderFrameObserver(frame), callback_(callback) {} + const base::Callback<void(bool, int)>& callback, bool wait_for_next = false) + : content::RenderFrameObserver(frame), callback_(callback), wait_for_next_(wait_for_next) {} void DidCreateDocumentElement() override { + if (wait_for_next_) { + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + base::Bind(&LoadWatcher::DidCreateDocumentElement, base::Unretained(this))); + wait_for_next_ = false; + return; + } // Defer the callback instead of running it now to avoid re-entrancy caused // by the JavaScript callback. + int id = routing_id(); ExtensionFrameHelper::Get(render_frame()) - ->ScheduleAtDocumentStart(base::Bind(callback_, true)); + ->ScheduleAtDocumentStart(base::Bind(callback_, true, id)); delete this; } @@ -37,18 +45,57 @@ class LoadWatcher : public content::RenderFrameObserver { // Use PostTask to avoid running user scripts while handling this // DidFailProvisionalLoad notification. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - base::Bind(callback_, false)); + base::Bind(callback_, false, routing_id())); delete this; } void OnDestruct() override { delete this; } private: - base::Callback<void(bool)> callback_; + base::Callback<void(bool, int)> callback_; + bool wait_for_next_; DISALLOW_COPY_AND_ASSIGN(LoadWatcher); }; +class CloseWatcher : public content::RenderFrameObserver { + public: + CloseWatcher(ScriptContext* context, + content::RenderFrame* frame, + v8::Local<v8::Function> cb) + : content::RenderFrameObserver(frame), + context_(context->weak_factory_.GetWeakPtr()), + callback_(context->isolate(), cb) + { + } + + void OnDestruct() override { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&CloseWatcher::CallbackAndDie, base::Unretained(this), + routing_id())); + } + + private: + void CallbackAndDie(int routing_id) { + if (context_ && context_->is_valid()) { + // context_ was deleted when running + // issue4007-reload-lost-app-window in test framework + v8::Isolate* isolate = context_->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, routing_id)}; + context_->SafeCallFunction(v8::Local<v8::Function>::New(isolate, callback_), + arraysize(args), args); + } + delete this; + } + + base::WeakPtr<ScriptContext> context_; + v8::Global<v8::Function> callback_; + + DISALLOW_COPY_AND_ASSIGN(CloseWatcher); +}; + } // namespace RenderFrameObserverNatives::RenderFrameObserverNatives(ScriptContext* context) @@ -61,6 +108,10 @@ void RenderFrameObserverNatives::AddRoutes() { "OnDocumentElementCreated", "app.window", base::Bind(&RenderFrameObserverNatives::OnDocumentElementCreated, base::Unretained(this))); + RouteHandlerFunction( + "OnDestruct", + base::Bind(&RenderFrameObserverNatives::OnDestruct, + base::Unretained(this))); } void RenderFrameObserverNatives::Invalidate() { @@ -70,9 +121,11 @@ void RenderFrameObserverNatives::Invalidate() { void RenderFrameObserverNatives::OnDocumentElementCreated( const v8::FunctionCallbackInfo<v8::Value>& args) { - CHECK(args.Length() == 2); CHECK(args[0]->IsInt32()); CHECK(args[1]->IsFunction()); + bool wait_for_next = false; + if (args.Length() > 2) + wait_for_next = args[2]->BooleanValue(); int frame_id = args[0]->Int32Value(); @@ -84,17 +137,17 @@ void RenderFrameObserverNatives::OnDocumentElementCreated( v8::Global<v8::Function> v8_callback(context()->isolate(), args[1].As<v8::Function>()); - base::Callback<void(bool)> callback( + base::Callback<void(bool, int)> callback( base::Bind(&RenderFrameObserverNatives::InvokeCallback, weak_ptr_factory_.GetWeakPtr(), base::Passed(&v8_callback))); - if (ExtensionFrameHelper::Get(frame)->did_create_current_document_element()) { + if (!wait_for_next && ExtensionFrameHelper::Get(frame)->did_create_current_document_element()) { // If the document element is already created, then we can call the callback // immediately (though use PostTask to ensure that the callback is called // asynchronously). base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - base::Bind(callback, true)); + base::Bind(callback, true, frame_id)); } else { - new LoadWatcher(frame, callback); + new LoadWatcher(frame, callback, wait_for_next); } args.GetReturnValue().Set(true); @@ -102,12 +155,32 @@ void RenderFrameObserverNatives::OnDocumentElementCreated( void RenderFrameObserverNatives::InvokeCallback( v8::Global<v8::Function> callback, - bool succeeded) { + bool succeeded, int frame_id) { v8::Isolate* isolate = context()->isolate(); v8::HandleScope handle_scope(isolate); - v8::Local<v8::Value> args[] = {v8::Boolean::New(isolate, succeeded)}; + v8::Local<v8::Value> args[] = {v8::Boolean::New(isolate, succeeded), v8::Integer::New(isolate, frame_id)}; context()->SafeCallFunction(v8::Local<v8::Function>::New(isolate, callback), - arraysize(args), args); + arraysize(args), args); } +void RenderFrameObserverNatives::OnDestruct( + const v8::FunctionCallbackInfo<v8::Value>& args) { + CHECK(args[0]->IsInt32()); + CHECK(args[1]->IsFunction()); + int frame_id = args[0]->Int32Value(); + + content::RenderFrame* frame = content::RenderFrame::FromRoutingID(frame_id); + if (!frame) { + LOG(WARNING) << "No render frame found to register CloseWatcher. " << frame_id; + return; + } + + v8::Local<v8::Function> func = args[1].As<v8::Function>(); + ScriptContext* context = ScriptContextSet::GetContextByV8Context(func->CreationContext()); + new CloseWatcher(context, frame, args[1].As<v8::Function>()); + + args.GetReturnValue().Set(true); +} + + } // namespace extensions diff --git a/extensions/renderer/render_frame_observer_natives.h b/extensions/renderer/render_frame_observer_natives.h index 01bb788f3eaf5..ae3e733c2e53f 100644 --- a/extensions/renderer/render_frame_observer_natives.h +++ b/extensions/renderer/render_frame_observer_natives.h @@ -29,10 +29,13 @@ class RenderFrameObserverNatives : public ObjectBackedNativeHandler { void OnDocumentElementCreated( const v8::FunctionCallbackInfo<v8::Value>& args); - void InvokeCallback(v8::Global<v8::Function> callback, bool succeeded); + void InvokeCallback(v8::Global<v8::Function> callback, bool succeeded, int frame_id); base::WeakPtrFactory<RenderFrameObserverNatives> weak_ptr_factory_; + void OnDestruct( + const v8::FunctionCallbackInfo<v8::Value>& args); + DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverNatives); }; diff --git a/extensions/renderer/request_sender.cc b/extensions/renderer/request_sender.cc index c16a7c38dadc8..b130f18e4ab10 100644 --- a/extensions/renderer/request_sender.cc +++ b/extensions/renderer/request_sender.cc @@ -60,6 +60,64 @@ int RequestSender::GetNextRequestId() const { return next_request_id++; } +bool RequestSender::StartRequestSync(Source* source, + const std::string& name, + int request_id, + bool has_callback, + bool for_io_thread, + base::ListValue* value_args, + bool* success, + base::ListValue* response, + std::string* error) { + ScriptContext* context = source->GetContext(); + if (!context) + return false; + + bool for_service_worker = + context->context_type() == Feature::SERVICE_WORKER_CONTEXT; + // Get the current RenderFrame so that we can send a routed IPC message from + // the correct source. + // Note that |render_frame| would be nullptr for Service Workers. Service + // Workers use control IPC instead. + content::RenderFrame* render_frame = context->GetRenderFrame(); + if (!for_service_worker && !render_frame) { + // It is important to early exit here for non Service Worker contexts so + // that we do not create orphaned PendingRequests below. + return false; + } + + // TODO(koz): See if we can make this a CHECK. + if (!context->HasAccessOrThrowError(name)) + return false; + + GURL source_url; + blink::WebLocalFrame* webframe = context->web_frame(); + if (webframe) + source_url = webframe->GetDocument().Url(); + + // InsertRequest(request_id, new PendingRequest(name, source, + // blink::WebUserGestureIndicator::currentUserGestureToken())); + + auto params = std::make_unique<ExtensionHostMsg_Request_Params>(); + params->name = name; + params->arguments.Swap(value_args); + params->extension_id = context->GetExtensionID(); + params->source_url = source_url; + params->request_id = request_id; + params->has_callback = has_callback; + params->user_gesture = + blink::WebUserGestureIndicator::IsProcessingUserGestureThreadSafe(webframe); + + // Set Service Worker specific params to default values. + params->worker_thread_id = -1; + params->service_worker_version_id = kInvalidServiceWorkerVersionId; + + binding::RequestThread thread = + for_io_thread ? binding::RequestThread::IO : binding::RequestThread::UI; + ipc_message_sender_->SendRequestIPC(context, std::move(params), thread, true, success, response, error); + return true; +} + bool RequestSender::StartRequest(Source* source, const std::string& name, int request_id, diff --git a/extensions/renderer/request_sender.h b/extensions/renderer/request_sender.h index 67fa6e494d661..2616966d02f62 100644 --- a/extensions/renderer/request_sender.h +++ b/extensions/renderer/request_sender.h @@ -63,6 +63,16 @@ class RequestSender { bool for_io_thread, base::ListValue* value_args); + bool StartRequestSync(Source* source, + const std::string& name, + int request_id, + bool has_callback, + bool for_io_thread, + base::ListValue* value_args, + bool* success, + base::ListValue* response, + std::string* error); + // Handles responses from the extension host to calls made by StartRequest(). void HandleResponse(int request_id, bool success, diff --git a/extensions/renderer/resources/app_window_custom_bindings.js b/extensions/renderer/resources/app_window_custom_bindings.js index 600d4713bac07..b6a8e281094b0 100644 --- a/extensions/renderer/resources/app_window_custom_bindings.js +++ b/extensions/renderer/resources/app_window_custom_bindings.js @@ -37,8 +37,23 @@ function createAnonymousEvent() { var Bounds = function(boundsKey) { privates(this).boundsKey_ = boundsKey; }; + +var try_hidden = function (view) { + if (view.chrome.app.window) + return view; + return privates(view); +}; + +var try_nw = function (view) { + if (view.nw) + return view; + return privates(view); +}; + Object.defineProperty(Bounds.prototype, 'left', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].left; }, set: function(left) { @@ -48,6 +63,8 @@ Object.defineProperty(Bounds.prototype, 'left', { }); Object.defineProperty(Bounds.prototype, 'top', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].top; }, set: function(top) { @@ -57,6 +74,8 @@ Object.defineProperty(Bounds.prototype, 'top', { }); Object.defineProperty(Bounds.prototype, 'width', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].width; }, set: function(width) { @@ -66,6 +85,8 @@ Object.defineProperty(Bounds.prototype, 'width', { }); Object.defineProperty(Bounds.prototype, 'height', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].height; }, set: function(height) { @@ -75,36 +96,52 @@ Object.defineProperty(Bounds.prototype, 'height', { }); Object.defineProperty(Bounds.prototype, 'minWidth', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].minWidth; }, set: function(minWidth) { + if (!privates(this)) //NWJS#6553 + return; updateSizeConstraints(privates(this).boundsKey_, { minWidth: minWidth }); }, enumerable: true }); Object.defineProperty(Bounds.prototype, 'maxWidth', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].maxWidth; }, set: function(maxWidth) { + if (!privates(this)) //NWJS#6553 + return; updateSizeConstraints(privates(this).boundsKey_, { maxWidth: maxWidth }); }, enumerable: true }); Object.defineProperty(Bounds.prototype, 'minHeight', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].minHeight; }, set: function(minHeight) { + if (!privates(this)) //NWJS#6553 + return; updateSizeConstraints(privates(this).boundsKey_, { minHeight: minHeight }); }, enumerable: true }); Object.defineProperty(Bounds.prototype, 'maxHeight', { get: function() { + if (!privates(this)) //NWJS#6553 + return 0; return appWindowData[privates(this).boundsKey_].maxHeight; }, set: function(maxHeight) { + if (!privates(this)) //NWJS#6553 + return; updateSizeConstraints(privates(this).boundsKey_, { maxHeight: maxHeight }); }, enumerable: true @@ -146,7 +183,7 @@ appWindow.registerCustomHook(function(bindingsAPI) { if (windowParams.existingWindow) { // Not creating a new window, but activating an existing one, so trigger // callback with existing window and don't do anything else. - let windowResult = view ? view.chrome.app.window.current() : undefined; + let windowResult = view ? try_hidden(view).chrome.app.window.current() : undefined; maybeCallback(windowResult); return; } @@ -160,7 +197,7 @@ appWindow.registerCustomHook(function(bindingsAPI) { ' The chrome.app.window.create callback will be called, but ' + 'there will be no object provided for the sandboxed window.'; } - console.warn(sandbox_window_message); + //console.warn(sandbox_window_message); maybeCallback(undefined); return; } @@ -168,20 +205,27 @@ appWindow.registerCustomHook(function(bindingsAPI) { // Handle error pages. // TODO(arthursonzogni): Figure out why view.chrome.app is defined for error // pages and stop doing it. - if (!view.chrome.app.window) { + if (!try_hidden(view).chrome.app.window) { maybeCallback(undefined); return; } // Initialize appWindowData in the newly created JS context - view.chrome.app.window.initializeAppWindow(windowParams); + try_hidden(view).chrome.app.window.initializeAppWindow(windowParams); var willCallback = renderFrameObserverNatives.OnDocumentElementCreated( - windowParams.frameId, function(success) { - let windowResult = success ? view.chrome.app.window.current() - : undefined; - maybeCallback(windowResult); - }); + windowParams.frameId, function(success) { + if (success) { + var appwin = try_hidden(view).chrome.app.window.current(); + if (!appwin) { + try_hidden(view).chrome.app.window.initializeAppWindow(windowParams); + appwin = try_hidden(view).chrome.app.window.current(); + } + } + let windowResult = success ? appwin + : undefined; + maybeCallback(windowResult); + }); appWindowNatives.ResumeParser(windowParams.frameId); if (!willCallback) maybeCallback(undefined); @@ -189,8 +233,6 @@ appWindow.registerCustomHook(function(bindingsAPI) { apiFunctions.setHandleRequest('current', function() { if (!currentAppWindow) { - console.error('The JavaScript context calling ' + - 'chrome.app.window.current() has no associated AppWindow.'); return null; } return currentAppWindow; @@ -199,7 +241,9 @@ appWindow.registerCustomHook(function(bindingsAPI) { apiFunctions.setHandleRequest('getAll', function() { var views = runtimeNatives.GetExtensionViews(-1, -1, 'APP_WINDOW'); return $Array.map(views, function(win) { - return win.chrome.app.window.current(); + if (try_nw(win).nw) //check for undefined case in NWJS#5528 + try_nw(win).nw.Window.get(); //construct the window object for NWJS#5294 + return try_hidden(win).chrome.app.window.current(); }); }); @@ -254,6 +298,9 @@ appWindow.registerCustomHook(function(bindingsAPI) { AppWindow.prototype.isFullscreen = function() { return appWindowData.fullscreen; }; + AppWindow.prototype.isResizable = function() { + return appWindowData.resizable; + }; AppWindow.prototype.isMinimized = function() { return appWindowData.minimized; }; @@ -315,6 +362,7 @@ appWindow.registerCustomHook(function(bindingsAPI) { minimized: params.minimized, maximized: params.maximized, alwaysOnTop: params.alwaysOnTop, + resizable: params.resizable, hasFrameColor: params.hasFrameColor, activeFrameColor: params.activeFrameColor, inactiveFrameColor: params.inactiveFrameColor, @@ -331,6 +379,18 @@ function boundsEqual(bounds1, bounds2) { bounds1.width == bounds2.width && bounds1.height == bounds2.height); } +function sizeEqual(bounds1, bounds2) { + if (!bounds1 || !bounds2) + return false; + return (bounds1.width == bounds2.width && bounds1.height == bounds2.height); +} + +function posEqual(bounds1, bounds2) { + if (!bounds1 || !bounds2) + return false; + return (bounds1.left == bounds2.left && bounds1.top == bounds2.top); +} + function dispatchEventIfExists(target, name) { // Sometimes apps like to put their own properties on the window which // break our assumptions. @@ -351,8 +411,20 @@ function updateAppWindowProperties(update) { var currentWindow = currentAppWindow; - if (!boundsEqual(oldData.innerBounds, update.innerBounds)) + if (!boundsEqual(oldData.innerBounds, update.innerBounds)) { dispatchEventIfExists(currentWindow, "onBoundsChanged"); + if (!sizeEqual(oldData.innerBounds, update.innerBounds)) + dispatchEventIfExists(currentWindow, "onResized"); + if (!posEqual(oldData.innerBounds, update.innerBounds)) + dispatchEventIfExists(currentWindow, "onMoved"); + } + + // NW fix: fire onRestored earlier than fullscreen/minimize/maximize + // events. See nwjs/nw.js#5388. + if ((oldData.fullscreen && !update.fullscreen) || + (oldData.minimized && !update.minimized) || + (oldData.maximized && !update.maximized)) + dispatchEventIfExists(currentWindow, "onRestored"); if (!oldData.fullscreen && update.fullscreen) dispatchEventIfExists(currentWindow, "onFullscreened"); @@ -361,11 +433,6 @@ function updateAppWindowProperties(update) { if (!oldData.maximized && update.maximized) dispatchEventIfExists(currentWindow, "onMaximized"); - if ((oldData.fullscreen && !update.fullscreen) || - (oldData.minimized && !update.minimized) || - (oldData.maximized && !update.maximized)) - dispatchEventIfExists(currentWindow, "onRestored"); - if (oldData.alphaEnabled !== update.alphaEnabled) dispatchEventIfExists(currentWindow, "onAlphaEnabledChanged"); }; diff --git a/extensions/renderer/resources/binding.js b/extensions/renderer/resources/binding.js index 3b74d1fb7c0fe..c63e7243752d1 100644 --- a/extensions/renderer/resources/binding.js +++ b/extensions/renderer/resources/binding.js @@ -335,12 +335,15 @@ Binding.prototype = { apiFunction.definition = functionDef; apiFunction.name = schema.namespace + '.' + functionDef.name; + if (schema.namespace != "app.window" && + schema.namespace != "nw.Window" && + schema.namespace != "runtime") { if (!GetAvailability(apiFunction.name).is_available || (checkUnprivileged && !isSchemaAccessAllowed(functionDef))) { this.apiFunctions_.registerUnavailable(functionDef.name); return; } - + } // TODO(aa): It would be best to run this in a unit test, but in order // to do that we would need to better factor this code so that it // doesn't depend on so much v8::Extension machinery. diff --git a/extensions/renderer/resources/event.js b/extensions/renderer/resources/event.js index e98d17997b601..9dc056b0c5386 100644 --- a/extensions/renderer/resources/event.js +++ b/extensions/renderer/resources/event.js @@ -251,6 +251,13 @@ // the list of arguments that will be sent to the event callback. // |listenerIds| contains the ids of matching listeners, or is an empty array // for all listeners. +function dispatchEventNW(name, args, filteringInfo) { + var listenerIDs = []; + if (filteringInfo) + listenerIDs = eventNatives.MatchAgainstEventFilter(name, filteringInfo); + dispatchEvent(name, args, listenerIDs); +} + function dispatchEvent(name, args, listenerIds) { var event = attachedNamedEvents[name]; if (!event) @@ -269,6 +276,9 @@ dispatchArgs(args); } + EventImpl.prototype.getListeners = function() { + return this.listeners; + }; // Registers a callback to be called when this event is dispatched. EventImpl.prototype.addListener = function(cb, filters) { if (!this.eventOptions.supportsListeners) @@ -515,6 +525,7 @@ } utils.expose(Event, EventImpl, { functions: [ + 'getListeners', 'addListener', 'removeListener', 'hasListener', @@ -531,5 +542,6 @@ exports.$set('Event', Event); exports.$set('dispatchEvent', dispatchEvent); + exports.$set('dispatchEventNW', dispatchEventNW); exports.$set('parseEventOptions', parseEventOptions); exports.$set('registerArgumentMassager', registerArgumentMassager); diff --git a/extensions/renderer/resources/extensions_renderer_resources.grd b/extensions/renderer/resources/extensions_renderer_resources.grd index d5e72d3fb9589..dc6430403668e 100644 --- a/extensions/renderer/resources/extensions_renderer_resources.grd +++ b/extensions/renderer/resources/extensions_renderer_resources.grd @@ -85,6 +85,19 @@ <!-- Extension styles. --> <include name="IDR_EXTENSION_FONTS_CSS" file="extension_fonts.css" type="BINDATA"/> + + <include name="IDR_NW_PRE13_SHIM_JS" file="../../../content/nw/src/resources/nw_pre13_shim.js" type="BINDATA" /> + <include name="IDR_NWAPI_APP_JS" file="../../../content/nw/src/resources/api_nw_app.js" type="BINDATA" /> + <include name="IDR_NWAPI_WINDOW_JS" file="../../../content/nw/src/resources/api_nw_window.js" type="BINDATA" /> + <include name="IDR_NWAPI_CLIPBOARD_JS" file="../../../content/nw/src/resources/api_nw_clipboard.js" type="BINDATA" /> + <include name="IDR_NWAPI_MENU_JS" file="../../../content/nw/src/resources/api_nw_menu.js" type="BINDATA" /> + <include name="IDR_NWAPI_MENUITEM_JS" file="../../../content/nw/src/resources/api_nw_menuitem.js" type="BINDATA" /> + <include name="IDR_NWAPI_SCREEN_JS" file="../../../content/nw/src/resources/api_nw_screen.js" type="BINDATA" /> + <include name="IDR_NWAPI_SHORTCUT_JS" file="../../../content/nw/src/resources/api_nw_shortcut.js" type="BINDATA" /> + <include name="IDR_NWAPI_SHELL_JS" file="../../../content/nw/src/resources/api_nw_shell.js" type="BINDATA" /> + <include name="IDR_NWAPI_OBJECT_JS" file="../../../content/nw/src/resources/api_nw_object.js" type="BINDATA" /> + <include name="IDR_NWAPI_TEST_JS" file="../../../content/nw/src/resources/api_nw_test.js" type="BINDATA" /> + <include name="IDR_NWAPI_TRAY_JS" file="../../../content/nw/src/resources/api_nw_tray.js" type="BINDATA" /> </includes> <structures> <!-- Extension styles. --> diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js b/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js index e8cf25351f838..2557c70c37132 100644 --- a/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js +++ b/extensions/renderer/resources/guest_view/web_view/web_view_api_methods.js @@ -56,11 +56,13 @@ var WEB_VIEW_API_METHODS = [ // Returns audio state. 'getAudioState', + // Return storeId which can be used in chrome.cookies API + 'getCookieStoreId', // Returns Chrome's internal process ID for the guest web page's current // process. 'getProcessId', - + 'getGuestId', // Returns the user agent string used by the webview for guest page requests. 'getUserAgent', @@ -89,6 +91,8 @@ var WEB_VIEW_API_METHODS = [ // of the data URL. 'loadDataWithBaseUrl', + 'showDevTools', + 'inspectElementAt', // Prints the contents of the webview. 'print', @@ -149,10 +153,18 @@ WebViewImpl.prototype.forward = function(callback) { return this.go(1, callback); }; +WebViewImpl.prototype.getCookieStoreId = function() { + return this.processId + "," + this.guest.getId(); +}; + WebViewImpl.prototype.getProcessId = function() { return this.processId; }; +WebViewImpl.prototype.getGuestId = function() { + return this.guest.getId(); +}; + WebViewImpl.prototype.getUserAgent = function() { return this.userAgentOverride || navigator.userAgent; }; @@ -182,6 +194,20 @@ WebViewImpl.prototype.loadDataWithBaseUrl = function( }); }; +WebViewImpl.prototype.showDevTools = function(show, container) { + if (!this.guest.getId()) { + return; + } + if (container) + WebViewInternal.showDevTools(this.guest.getId(), show, container.getProcessId(), container.getGuestId()); + else + WebViewInternal.showDevTools(this.guest.getId(), show); +}; + +WebViewImpl.prototype.inspectElementAt = function(x, y) { + WebViewInternal.inspectElementAt(this.guest.getId(), x, y); +}; + WebViewImpl.prototype.print = function() { return this.executeScript({code: 'window.print();'}); }; diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_attributes.js b/extensions/renderer/resources/guest_view/web_view/web_view_attributes.js index f9a92358c8ca5..84863e8bb762b 100644 --- a/extensions/renderer/resources/guest_view/web_view/web_view_attributes.js +++ b/extensions/renderer/resources/guest_view/web_view/web_view_attributes.js @@ -53,6 +53,18 @@ AllowTransparencyAttribute.prototype.handleMutation = function(oldValue, this.getValue()); }; +function AllowNWAttribute(view) { + GuestViewAttributes.BooleanAttribute.call( + this, WebViewConstants.ATTRIBUTE_ALLOWNW, view); +} + +AllowNWAttribute.prototype.__proto__ = + GuestViewAttributes.BooleanAttribute.prototype; + +AllowNWAttribute.prototype.handleMutation = function(oldValue, + newValue) { +}; + // ----------------------------------------------------------------------------- // AutosizeDimensionAttribute object. @@ -274,6 +286,8 @@ WebViewImpl.prototype.setupAttributes = function() { new PartitionAttribute(this); this.attributes[WebViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this); + this.attributes[WebViewConstants.ATTRIBUTE_ALLOWNW] = + new AllowNWAttribute(this); var autosizeAttributes = [WebViewConstants.ATTRIBUTE_MAXHEIGHT, WebViewConstants.ATTRIBUTE_MAXWIDTH, diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_constants.js b/extensions/renderer/resources/guest_view/web_view/web_view_constants.js index 09110e1474978..797e71b40c308 100644 --- a/extensions/renderer/resources/guest_view/web_view/web_view_constants.js +++ b/extensions/renderer/resources/guest_view/web_view/web_view_constants.js @@ -17,6 +17,7 @@ var WebViewConstants = { ATTRIBUTE_NAME: 'name', ATTRIBUTE_PARTITION: 'partition', ATTRIBUTE_SRC: 'src', + ATTRIBUTE_ALLOWNW: 'allownw', // Error/warning messages. ERROR_MSG_ALREADY_NAVIGATED: '<webview>: ' + diff --git a/extensions/renderer/resources/last_error.js b/extensions/renderer/resources/last_error.js index 14836b70067ec..a9bc9846e21d1 100644 --- a/extensions/renderer/resources/last_error.js +++ b/extensions/renderer/resources/last_error.js @@ -94,7 +94,7 @@ function assertRuntimeIsAvailable() { throw new Error('runtime.lastError is not available: ' + runtimeAvailability.message); } - if (!chrome.runtime) + if (!chrome.runtime && !privates(window).chrome.runtime) throw new Error('runtime namespace is null or undefined'); } diff --git a/extensions/renderer/resources/send_request.js b/extensions/renderer/resources/send_request.js index bb7695047296a..69fc58ff47594 100644 --- a/extensions/renderer/resources/send_request.js +++ b/extensions/renderer/resources/send_request.js @@ -17,11 +17,18 @@ var requests = { __proto__: null }; // bindings and ExtensionFunctions (via sendRequest). var calledSendRequest = false; +var try_hidden = function (view) { + if (view.chrome.runtime) + return view; + return privates(view); +}; + // Callback handling. function handleResponse(requestId, name, success, responseList, error) { // The chrome objects we will set lastError on. Really we should only be // setting this on the callback's chrome object, but set on ours too since // it's conceivable that something relies on that. + var chrome = try_hidden(window).chrome; var callerChrome = chrome; try { @@ -32,7 +39,7 @@ function handleResponse(requestId, name, success, responseList, error) { // though chances are it's the same as ours (it will be different when // calling API methods on other contexts). if (request.callback) { - var global = natives.GetGlobal(request.callback); + var global = try_hidden(natives.GetGlobal(request.callback)); callerChrome = global ? global.chrome : callerChrome; } @@ -125,6 +132,26 @@ function sendRequest(functionName, args, argSchemas, optArgs) { requests[requestId] = request; } +function sendRequestSync(functionName, args, argSchemas, optArgs) { + if (!optArgs) + optArgs = {}; + var request = prepareRequest(args, argSchemas); + request.stack = optArgs.stack || exceptionHandler.getExtensionStackTrace(); + if (optArgs.customCallback) { + request.customCallback = optArgs.customCallback; + } + + //var requestId = natives.GetNextRequestId(); + //request.id = requestId; + + var hasCallback = request.callback || optArgs.customCallback; + return natives.StartRequestSync(functionName, + request.args, + hasCallback, + optArgs.forIOThread, + optArgs.preserveNullInObjects); +} + function getCalledSendRequest() { return calledSendRequest; } @@ -134,6 +161,7 @@ function clearCalledSendRequest() { } exports.$set('sendRequest', sendRequest); +exports.$set('sendRequestSync', sendRequestSync); exports.$set('getCalledSendRequest', getCalledSendRequest); exports.$set('clearCalledSendRequest', clearCalledSendRequest); diff --git a/extensions/renderer/runtime_custom_bindings.cc b/extensions/renderer/runtime_custom_bindings.cc index f4e510bf8e696..a7a035d6e5d2e 100644 --- a/extensions/renderer/runtime_custom_bindings.cc +++ b/extensions/renderer/runtime_custom_bindings.cc @@ -5,6 +5,7 @@ #include "extensions/renderer/runtime_custom_bindings.h" #include <stdint.h> +#include "extensions/renderer/script_context_set.h" #include <memory> @@ -64,8 +65,13 @@ void RuntimeCustomBindings::GetExtensionViews( CHECK_EQ("ALL", view_type_string); const std::string& extension_id = context()->GetExtensionID(); - if (extension_id.empty()) - return; + // id is empty while calling from external page. we want to do + // this for window controlling. note the case that there are + // multiple extensions in the process, e.g. the automation extension + // for chromedriver + + // if (extension_id.empty()) + // return; v8::Local<v8::Context> v8_context = args.GetIsolate()->GetCurrentContext(); // We ignore iframes here. (Returning subframes can cause broken behavior by diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index ff759b032cb88..fbdea3bca5722 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc @@ -87,7 +87,8 @@ ScriptContext::ScriptContext(const v8::Local<v8::Context>& v8_context, effective_context_type_(effective_context_type), context_id_(base::UnguessableToken::Create()), safe_builtins_(this), - isolate_(v8_context->GetIsolate()) { + isolate_(v8_context->GetIsolate()), + weak_factory_(this) { VLOG(1) << "Created context:\n" << GetDebugString(); v8_context_.AnnotateStrongRetainer("extensions::ScriptContext::v8_context_"); if (web_frame_) @@ -269,14 +270,22 @@ GURL ScriptContext::GetDocumentLoaderURLForFrame( frame->GetProvisionalDocumentLoader() ? frame->GetProvisionalDocumentLoader() : frame->GetDocumentLoader(); - return document_loader ? GURL(document_loader->GetRequest().Url()) : GURL(); + GURL ret = document_loader ? GURL(document_loader->GetRequest().Url()) : GURL(); +#if 0 + //nwjs: iframe url + if (!ret.is_valid() || ret.is_empty()) + ret = frame->document().url(); +#endif + return ret; } // static GURL ScriptContext::GetAccessCheckedFrameURL( const blink::WebLocalFrame* frame) { const blink::WebURL& weburl = frame->GetDocument().Url(); - if (weburl.IsEmpty()) { + if (weburl.IsEmpty() || GURL(weburl) == GURL("about:blank")) { + // NWJS fix for iframe-remote race condition on win release + // against 79b64c3e741cc9c6afbb23885945831a45c6baa5 blink::WebDocumentLoader* document_loader = frame->GetProvisionalDocumentLoader() ? frame->GetProvisionalDocumentLoader() @@ -297,7 +306,9 @@ GURL ScriptContext::GetEffectiveDocumentURL(blink::WebLocalFrame* frame, // Common scenario. If |match_about_blank| is false (as is the case in most // extensions), or if the frame is not an about:-page, just return // |document_url| (supposedly the URL of the frame). - if (!match_about_blank || !document_url.SchemeIs(url::kAboutScheme)) + + // nwjs: iframe's document_url is invalid here + if (!match_about_blank || (!document_url.SchemeIs(url::kAboutScheme) && document_url.is_valid())) return document_url; // Non-sandboxed about:blank and about:srcdoc pages inherit their security @@ -393,6 +404,9 @@ bool ScriptContext::HasAccessOrThrowError(const std::string& name) { return false; } + if (extension() && extension()->is_nwjs_app()) + return true; + Feature::Availability availability = GetAvailability(name); if (!availability.is_available()) { isolate()->ThrowException(v8::Exception::Error( diff --git a/extensions/renderer/script_context.h b/extensions/renderer/script_context.h index c8b4a13fc4fa3..536ddf22aedf0 100644 --- a/extensions/renderer/script_context.h +++ b/extensions/renderer/script_context.h @@ -281,6 +281,8 @@ class ScriptContext : public RequestSender::Source { GURL service_worker_scope_; base::ThreadChecker thread_checker_; + public: + base::WeakPtrFactory<ScriptContext> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ScriptContext); }; diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc index 2eb7384dce6e1..50b5885212ba5 100644 --- a/extensions/renderer/script_context_set.cc +++ b/extensions/renderer/script_context_set.cc @@ -46,7 +46,7 @@ ScriptContext* ScriptContextSet::Register( GURL frame_url = ScriptContext::GetDocumentLoaderURLForFrame(frame); Feature::Context context_type = ClassifyJavaScriptContext( - extension, world_id, frame_url, frame->GetDocument().GetSecurityOrigin()); + extension, world_id, frame_url, frame->GetDocument().GetSecurityOrigin(), frame); Feature::Context effective_context_type = ClassifyJavaScriptContext( effective_extension, world_id, ScriptContext::GetEffectiveDocumentURL(frame, frame_url, true), @@ -173,7 +173,9 @@ Feature::Context ScriptContextSet::ClassifyJavaScriptContext( const Extension* extension, int world_id, const GURL& url, - const blink::WebSecurityOrigin& origin) { + const blink::WebSecurityOrigin& origin, + const blink::WebLocalFrame* frame + ) { // WARNING: This logic must match ProcessMap::GetContextType, as much as // possible. @@ -195,7 +197,7 @@ Feature::Context ScriptContextSet::ClassifyJavaScriptContext( // before the SecurityContext is updated with the sandbox flags (after // reading the CSP header), so the caller can't check if the context's // security origin is unique yet. - if (ScriptContext::IsSandboxedPage(url)) + if (ScriptContext::IsSandboxedPage(url) || (frame && frame->isNwDisabledChildFrame())) return Feature::WEB_PAGE_CONTEXT; if (extension && active_extension_ids_->count(extension->id()) > 0) { diff --git a/extensions/renderer/script_context_set.h b/extensions/renderer/script_context_set.h index a622e7a40b371..f74220792cdd6 100644 --- a/extensions/renderer/script_context_set.h +++ b/extensions/renderer/script_context_set.h @@ -133,7 +133,9 @@ class ScriptContextSet { const Extension* extension, int world_id, const GURL& url, - const blink::WebSecurityOrigin& origin); + const blink::WebSecurityOrigin& origin, + const blink::WebLocalFrame* frame = nullptr + ); // Weak reference to all installed Extensions that are also active in this // process. diff --git a/extensions/renderer/send_request_natives.cc b/extensions/renderer/send_request_natives.cc index 6093db9f0cb06..9fbeb2ac6eb6a 100644 --- a/extensions/renderer/send_request_natives.cc +++ b/extensions/renderer/send_request_natives.cc @@ -23,10 +23,63 @@ void SendRequestNatives::AddRoutes() { RouteHandlerFunction( "StartRequest", base::Bind(&SendRequestNatives::StartRequest, base::Unretained(this))); + RouteHandlerFunction( + "StartRequestSync", + base::Bind(&SendRequestNatives::StartRequestSync, base::Unretained(this))); RouteHandlerFunction("GetGlobal", base::Bind(&SendRequestNatives::GetGlobal, base::Unretained(this))); } +void SendRequestNatives::StartRequestSync( + const v8::FunctionCallbackInfo<v8::Value>& args) { + CHECK_EQ(5, args.Length()); + std::string name = *v8::String::Utf8Value(args.GetIsolate(), args[0]); + bool has_callback = args[2]->BooleanValue(); + bool for_io_thread = args[3]->BooleanValue(); + bool preserve_null_in_objects = args[4]->BooleanValue(); + + int request_id = request_sender_->GetNextRequestId(); + std::unique_ptr<content::V8ValueConverter> converter(content::V8ValueConverter::Create()); + + // See http://crbug.com/149880. The context menus APIs relies on this, but + // we shouldn't really be doing it (e.g. for the sake of the storage API). + converter->SetFunctionAllowed(true); + + // See http://crbug.com/694248. + converter->SetConvertNegativeZeroToInt(true); + + if (!preserve_null_in_objects) + converter->SetStripNullFromObjects(true); + + std::unique_ptr<base::Value> value_args( + converter->FromV8Value(args[1], context()->v8_context())); + if (!value_args.get() || !value_args->is_list()) { + NOTREACHED() << "Unable to convert args passed to StartRequestSync"; + return; + } + + std::string error; + bool success; + base::ListValue response; + request_sender_->StartRequestSync( + context(), + name, + request_id, + has_callback, + for_io_thread, + static_cast<base::ListValue*>(value_args.get()), + &success, + &response, &error + ); + if (!success) { + args.GetIsolate()->ThrowException( + v8::String::NewFromUtf8(args.GetIsolate(), error.c_str())); + return; + } + args.GetReturnValue().Set(converter->ToV8Value(&response, + context()->v8_context())); +} + // Starts an API request to the browser, with an optional callback. The // callback will be dispatched to EventBindings::HandleResponse. void SendRequestNatives::StartRequest( diff --git a/extensions/renderer/send_request_natives.h b/extensions/renderer/send_request_natives.h index 42909fe8b38e1..9badbba806532 100644 --- a/extensions/renderer/send_request_natives.h +++ b/extensions/renderer/send_request_natives.h @@ -26,6 +26,7 @@ class SendRequestNatives : public ObjectBackedNativeHandler { // Starts an API request to the browser, with an optional callback. The // callback will be dispatched to EventBindings::HandleResponse. void StartRequest(const v8::FunctionCallbackInfo<v8::Value>& args); + void StartRequestSync(const v8::FunctionCallbackInfo<v8::Value>& args); // Gets a reference to an object's global object. void GetGlobal(const v8::FunctionCallbackInfo<v8::Value>& args); diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index 7b9618cc9646b..dd76cb5be4430 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc @@ -134,7 +134,7 @@ UserScript::InjectionType UserScriptInjector::script_type() const { } bool UserScriptInjector::ShouldExecuteInMainWorld() const { - return false; + return script_->in_main_world(); } bool UserScriptInjector::IsUserGesture() const { diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc index 6d345257a2279..d2bf6f5dfb2c1 100644 --- a/extensions/renderer/user_script_set.cc +++ b/extensions/renderer/user_script_set.cc @@ -161,7 +161,7 @@ bool UserScriptSet::UpdateUserScripts(base::SharedMemoryHandle shared_memory, RendererExtensionRegistry::Get()->GetByID(script->extension_id()); if (whitelisted_only && (!extension || !PermissionsData::CanExecuteScriptEverywhere( - extension->id(), extension->location()))) { + extension->id(), extension->location(), extension->GetType()))) { continue; } @@ -215,10 +215,16 @@ std::unique_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript( if (web_frame->Parent() && !script->match_all_frames()) return injection; // Only match subframes if the script declared it. - GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( + // nwjs#6324: move the upstream logic of GetEffectiveDocumentURL() here + // in upstream is not matched first with empty invalid url for iframe + GURL effective_document_url; + if (!script->match_about_blank() || !document_url.SchemeIs(url::kAboutScheme)) + effective_document_url = document_url; + else + effective_document_url = ScriptContext::GetEffectiveDocumentURL( web_frame, document_url, script->match_about_blank()); - if (!script->MatchesURL(effective_document_url)) + if (!script->MatchesURL(effective_document_url) || !effective_document_url.is_valid()) return injection; std::unique_ptr<ScriptInjector> injector( diff --git a/extensions/renderer/v8_context_native_handler.cc b/extensions/renderer/v8_context_native_handler.cc index 1ae5ef69163a9..0d9f0deafe874 100644 --- a/extensions/renderer/v8_context_native_handler.cc +++ b/extensions/renderer/v8_context_native_handler.cc @@ -30,6 +30,18 @@ void V8ContextNativeHandler::GetAvailability( v8::Isolate* isolate = args.GetIsolate(); std::string api_name = *v8::String::Utf8Value(isolate, args[0]); Feature::Availability availability = context_->GetAvailability(api_name); + if (api_name == "app.window" || api_name == "nw.Window" || + api_name == "runtime") { + v8::Local<v8::Object> ret = v8::Object::New(isolate); + ret->Set(v8::String::NewFromUtf8(isolate, "is_available"), + v8::Boolean::New(isolate, true)); + ret->Set(v8::String::NewFromUtf8(isolate, "message"), + v8::String::NewFromUtf8(isolate, "")); + ret->Set(v8::String::NewFromUtf8(isolate, "result"), + v8::Integer::New(isolate, Feature::IS_AVAILABLE)); + args.GetReturnValue().Set(ret); + return; + } v8::Local<v8::Object> ret = v8::Object::New(isolate); v8::Maybe<bool> maybe = diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 1fd06ba6babc8..068f5f469b6a7 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn @@ -449,7 +449,7 @@ component("headless") { deps += [ "//components/os_crypt" ] } - if (is_component_build) { + if (is_win || ((is_linux || is_mac) && is_component_build)) { sources += [ "lib/browser/headless_content_browser_client.cc", "lib/browser/headless_content_browser_client.h", @@ -476,7 +476,7 @@ component("headless") { if (!is_fuchsia) { deps += [ "//components/crash/content/browser" ] } - if (is_win) { + if (is_win && is_component_build) { deps += [ "//components/crash/content/app:crash_export_thunks" ] } @@ -928,8 +928,6 @@ static_library("headless_shell_lib") { sources = [ "app/headless_shell.cc", "app/headless_shell.h", - "app/headless_shell_switches.cc", - "app/headless_shell_switches.h", "app/shell_navigation_request.cc", "app/shell_navigation_request.h", "lib/browser/headless_content_browser_client.cc", @@ -956,6 +954,13 @@ static_library("headless_shell_lib") { deps += [ "//components/crash/content/browser" ] } + if ((is_linux || is_mac) && is_component_build) { + sources += [ + "app/headless_shell_switches.cc", + "app/headless_shell_switches.h", + ] + } + if (enable_basic_printing) { deps += [ "//components/printing/browser", diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm index ff6ef6ab8dc5a..f7bb48e2c76af 100644 --- a/ios/chrome/browser/snapshots/snapshot_cache.mm +++ b/ios/chrome/browser/snapshots/snapshot_cache.mm @@ -97,7 +97,7 @@ bool GetSnapshotsCacheDirectory(base::FilePath* snapshots_cache_directory) { return false; *snapshots_cache_directory = - cache_directory.Append(FILE_PATH_LITERAL("Chromium")) + cache_directory.Append(FILE_PATH_LITERAL("nwjs")) .Append(FILE_PATH_LITERAL("Snapshots")); return true; } diff --git a/ipc/ipc_logging.cc b/ipc/ipc_logging.cc index aad1b73326ae3..8e3ad8715c979 100644 --- a/ipc/ipc_logging.cc +++ b/ipc/ipc_logging.cc @@ -239,7 +239,7 @@ void Logging::Log(const LogData& data) { } } } - if (enabled_on_stderr_) { + if (enabled_on_stderr_ && !sender_) { std::string message_name; if (data.message_name.empty()) { message_name = base::StringPrintf("[unknown type %d]", data.type); diff --git a/media/BUILD.gn b/media/BUILD.gn index e4debbaa0ed14..dec2ff899655c 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -11,7 +11,6 @@ import("//build/config/ui.gni") import("//media/media_options.gni") import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/test.gni") -import("//third_party/ffmpeg/ffmpeg_options.gni") buildflag_header("media_buildflags") { header = "media_buildflags.h" @@ -38,15 +37,6 @@ buildflag_header("media_buildflags") { ] } -if (proprietary_codecs && media_use_ffmpeg) { - assert( - ffmpeg_branding != "Chromium", - "proprietary codecs and ffmpeg_branding set to Chromium are incompatible") -} - -# Common configuration for targets in the media directory; these must not be -# exported since things like USE_NEON and USE_CRAS have different meanings -# elsewhere in the code base. config("media_config") { defines = [] if (current_cpu == "arm64" || (current_cpu == "arm" && arm_use_neon)) { diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc index f4e67c240ea1c..3ef72b60873fc 100644 --- a/media/audio/audio_manager_base.cc +++ b/media/audio/audio_manager_base.cc @@ -114,9 +114,10 @@ AudioManagerBase::AudioManagerBase(std::unique_ptr<AudioThread> audio_thread, AudioManagerBase::~AudioManagerBase() { // All the output streams should have been deleted. - CHECK_EQ(0, num_output_streams_); + //disable the check for NWJS#5318 + //CHECK_EQ(0, num_output_streams_); // All the input streams should have been deleted. - CHECK(input_streams_.empty()); + //CHECK(input_streams_.empty()); } void AudioManagerBase::GetAudioInputDeviceDescriptions( diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index caa2647cb2964..a55adf8b3b779 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc @@ -128,6 +128,12 @@ AVCodecID AudioCodecToCodecID(AudioCodec audio_codec, return AV_CODEC_ID_AAC; case kCodecALAC: return AV_CODEC_ID_ALAC; +#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) + case kCodecAC3: + return AV_CODEC_ID_AC3; + case kCodecEAC3: + return AV_CODEC_ID_EAC3; +#endif case kCodecMP3: return AV_CODEC_ID_MP3; case kCodecPCM: diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index 568c10e3b3aa4..b0b64e6a753d2 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc @@ -81,6 +81,7 @@ static const MimeInfo kPrimaryMappings[] = { {"video/webm", "webm"}, {"application/javascript", "js"}, + {"application/javascript", "mjs"}, {"application/wasm", "wasm"}, {"application/x-chrome-extension", "crx"}, {"application/xhtml+xml", "xhtml,xht,xhtm"}, diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h index 8c0ac02e54ea7..55b34351bde69 100644 --- a/net/cert/cert_verifier.h +++ b/net/cert/cert_verifier.h @@ -106,8 +106,8 @@ class NET_EXPORT CertVerifier { const std::string& hostname() const { return hostname_; } int flags() const { return flags_; } const std::string& ocsp_response() const { return ocsp_response_; } - const CertificateList& additional_trust_anchors() const { - return additional_trust_anchors_; + const CertificateList* additional_trust_anchors() const { + return &additional_trust_anchors_; } bool operator==(const RequestParams& other) const; diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index 7484f58456f4e..735b22bd14522 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc @@ -5,6 +5,7 @@ #include "net/cert/cert_verify_proc_mac.h" #include <CommonCrypto/CommonDigest.h> +#include <CoreFoundation/CFArray.h> #include <CoreServices/CoreServices.h> #include <Security/Security.h> @@ -513,6 +514,7 @@ int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, CFArrayRef trust_policies, int flags, CFArrayRef keychain_search_list, + const CertificateList& additional_trust_anchors, ScopedCFTypeRef<SecTrustRef>* trust_ref, SecTrustResultType* trust_result, ScopedCFTypeRef<CFArrayRef>* verified_chain, @@ -612,6 +614,7 @@ int VerifyWithGivenFlags(X509Certificate* cert, const int flags, CRLSet* crl_set, CertVerifyResult* verify_result, + const CertificateList& additional_trust_anchors, CRLSetResult* completed_chain_crl_result) { ScopedCFTypeRef<CFArrayRef> trust_policies; OSStatus status = CreateTrustPolicies(flags, &trust_policies); @@ -757,7 +760,7 @@ int VerifyWithGivenFlags(X509Certificate* cert, int rv = BuildAndEvaluateSecTrustRef( cert_array, trust_policies, flags, - scoped_alternate_keychain_search_list.get(), &temp_ref, + scoped_alternate_keychain_search_list.get(), additional_trust_anchors, &temp_ref, &temp_trust_result, &temp_chain, &temp_chain_info); if (rv != OK) return rv; @@ -982,7 +985,7 @@ CertVerifyProcMac::CertVerifyProcMac() {} CertVerifyProcMac::~CertVerifyProcMac() {} bool CertVerifyProcMac::SupportsAdditionalTrustAnchors() const { - return false; + return true; } bool CertVerifyProcMac::SupportsOCSPStapling() const { @@ -1008,7 +1011,7 @@ int CertVerifyProcMac::VerifyInternal( GetCandidateEVPolicy(cert, &candidate_ev_policy_oid); CRLSetResult completed_chain_crl_result; - int rv = VerifyWithGivenFlags(cert, hostname, flags, crl_set, verify_result, + int rv = VerifyWithGivenFlags(cert, hostname, flags, crl_set, verify_result, additional_trust_anchors, &completed_chain_crl_result); if (rv != OK) return rv; @@ -1029,7 +1032,7 @@ int CertVerifyProcMac::VerifyInternal( int tmp_rv = VerifyWithGivenFlags( verify_result->verified_cert.get(), hostname, flags | CertVerifier::VERIFY_REV_CHECKING_ENABLED, crl_set, - verify_result, &completed_chain_crl_result); + verify_result, additional_trust_anchors, &completed_chain_crl_result); // If re-verification failed, return those results without setting EV // status. if (tmp_rv != OK) diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index 0abf85c65d2ae..4225b9a3cbf71 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc @@ -30,6 +30,7 @@ #include "net/cert/test_root_certs.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util_win.h" +#include "net/cert/x509_util.h" #if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE) // This was introduced in Windows 8 / Windows Server 2012, but retroactively @@ -840,7 +841,7 @@ CertVerifyProcWin::CertVerifyProcWin() {} CertVerifyProcWin::~CertVerifyProcWin() {} bool CertVerifyProcWin::SupportsAdditionalTrustAnchors() const { - return false; + return true; } bool CertVerifyProcWin::SupportsOCSPStapling() const { @@ -1106,8 +1107,36 @@ int CertVerifyProcWin::VerifyInternal( ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context); + DWORD errorStatus = chain_context->TrustStatus.dwErrorStatus; + bool skipPolicyCheck = false; + if (((errorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT) || (errorStatus & (CERT_TRUST_IS_OFFLINE_REVOCATION | CERT_TRUST_REVOCATION_STATUS_UNKNOWN)))&& + !additional_trust_anchors.empty()) { + // check if the (untrusted) validated root is in the list of + // additional trust anchors + PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0]; + DWORD num_elements = first_chain->cElement; + if (num_elements >= 1) { + PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; + PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext; + for (size_t i=0; i<additional_trust_anchors.size(); i++) { + bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(X509Certificate::CreateCertBufferFromBytes((const char*)(cert->pbCertEncoded), cert->cbCertEncoded)); + if (x509_util::CryptoBufferEqual(cert_handle.get(), + additional_trust_anchors[i]->cert_buffer())) { + LOG(INFO) << "Untrusted root \"" << + additional_trust_anchors[i]->subject().GetDisplayName() << + "\" found in additional anchors, assuming trusted."; + verify_result->is_issued_by_additional_trust_anchor = true; + errorStatus &= ~(CERT_TRUST_IS_UNTRUSTED_ROOT | CERT_TRUST_IS_OFFLINE_REVOCATION + | CERT_TRUST_REVOCATION_STATUS_UNKNOWN | CERT_TRUST_IS_PARTIAL_CHAIN); + skipPolicyCheck = true; + break; + } + } + } + } + verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( - chain_context->TrustStatus.dwErrorStatus); + errorStatus); // Flag certificates that have a Subject common name with a NULL character. if (CertSubjectCommonNameHasNull(cert_list.get())) @@ -1115,6 +1144,7 @@ int CertVerifyProcWin::VerifyInternal( base::string16 hostname16 = base::ASCIIToUTF16(hostname); + if (!skipPolicyCheck) { SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para; memset(&extra_policy_para, 0, sizeof(extra_policy_para)); extra_policy_para.cbSize = sizeof(extra_policy_para); @@ -1148,7 +1178,7 @@ int CertVerifyProcWin::VerifyInternal( verify_result->cert_status |= MapNetErrorToCertStatus( MapSecurityError(policy_status.dwError)); } - + } // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be // compatible with WinHTTP, which doesn't report this error (bug 3004). verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc index 3f78dfb00e3b9..ac8357bf6c9ee 100644 --- a/net/cert/multi_threaded_cert_verifier.cc +++ b/net/cert/multi_threaded_cert_verifier.cc @@ -187,14 +187,14 @@ std::unique_ptr<ResultHelper> DoVerifyOnWorkerThread( const std::string& ocsp_response, int flags, const scoped_refptr<CRLSet>& crl_set, - const CertificateList& additional_trust_anchors) { + const CertificateList* additional_trust_anchors) { TRACE_EVENT0(kNetTracingCategory, "DoVerifyOnWorkerThread"); auto verify_result = std::make_unique<ResultHelper>(); MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives allow_base_sync_primitives; verify_result->error = verify_proc->Verify( cert.get(), hostname, ocsp_response, flags, crl_set.get(), - additional_trust_anchors, &verify_result->result); + *additional_trust_anchors, &verify_result->result); return verify_result; } diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 8218ee31292c6..bb3455a1110a1 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc @@ -565,6 +565,7 @@ bool CookieMonster::IsCookieableScheme(const std::string& scheme) { } const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https", + "chrome-extension", "ws", "wss"}; const int CookieMonster::kDefaultCookieableSchemesCount = base::size(kDefaultCookieableSchemes); diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn b/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn index a4ee2076e56fc..e2bfdf40e9e12 100644 --- a/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn +++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/BUILD.gn @@ -36,6 +36,7 @@ action("pnacl_support_extension") { output_prefix = "$root_out_dir/pnacl/pnacl_public_" outputs = [ + "$root_out_dir/pnacl", "${output_prefix}pnacl_json", ] diff --git a/remoting/remoting_enable.gni b/remoting/remoting_enable.gni index 879214d9a8da8..361f8f02adfb4 100644 --- a/remoting/remoting_enable.gni +++ b/remoting/remoting_enable.gni @@ -9,5 +9,5 @@ if (is_ios) { } declare_args() { - enable_remoting = !is_chromecast && !is_fuchsia + enable_remoting = false } diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn index 9114686f121eb..53864b841f172 100644 --- a/services/service_manager/embedder/BUILD.gn +++ b/services/service_manager/embedder/BUILD.gn @@ -63,6 +63,7 @@ component("embedder") { deps += [ "//base/allocator:buildflags", "//components/tracing:startup_tracing", + "//content/nw:nw_base" ] if (!is_nacl) { diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc index fdff39ef33456..9e6ff1ecdab71 100644 --- a/services/service_manager/embedder/main.cc +++ b/services/service_manager/embedder/main.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "content/nw/src/nw_base.h" + #include "services/service_manager/embedder/main.h" #include "base/allocator/buildflags.h" @@ -178,7 +180,7 @@ void CommonSubprocessInit() { setlocale(LC_NUMERIC, "C"); #endif -#if !defined(OFFICIAL_BUILD) && defined(OS_WIN) +#if 0 base::RouteStdioToConsole(false); LoadLibraryA("dbghelp.dll"); #endif @@ -352,7 +354,7 @@ int Main(const MainParams& params) { base::EnableTerminationOnHeapCorruption(); - SetProcessTitleFromCommandLine(argv); + //SetProcessTitleFromCommandLine(argv); #endif // !defined(OS_ANDROID) // On Android setlocale() is not supported, and we don't override the signal @@ -385,10 +387,10 @@ int Main(const MainParams& params) { #endif mojo::edk::Configuration mojo_config; + std::string type_switch = + command_line.GetSwitchValueASCII(switches::kProcessType); ProcessType process_type = delegate->OverrideProcessType(); if (process_type == ProcessType::kDefault) { - std::string type_switch = - command_line.GetSwitchValueASCII(switches::kProcessType); if (type_switch == switches::kProcessTypeServiceManager) { mojo_config.is_broker_process = true; process_type = ProcessType::kServiceManager; @@ -416,7 +418,7 @@ int Main(const MainParams& params) { return exit_code; } -#if defined(OS_WIN) +#if 0 //defined(OS_WIN) // Route stdio to parent console (if any) or create one. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableLogging)) { @@ -459,7 +461,8 @@ int Main(const MainParams& params) { exit_code = delegate->RunEmbedderProcess(); break; } - + if (type_switch == "renderer") + exit_code = nw::ExitCodeHook(); if (tracker) { if (exit_code == 0) { tracker->SetProcessPhaseIfEnabled( diff --git a/services/service_manager/sandbox/linux/sandbox_linux.cc b/services/service_manager/sandbox/linux/sandbox_linux.cc index da5afa6d07e35..ce568a29a333a 100644 --- a/services/service_manager/sandbox/linux/sandbox_linux.cc +++ b/services/service_manager/sandbox/linux/sandbox_linux.cc @@ -142,9 +142,11 @@ SandboxLinux::SandboxLinux() } SandboxLinux::~SandboxLinux() { +#if 0 if (pre_initialized_) { CHECK(initialize_sandbox_ran_); } +#endif } SandboxLinux* SandboxLinux::GetInstance() { diff --git a/services/service_manager/zygote/host/zygote_communication_linux.cc b/services/service_manager/zygote/host/zygote_communication_linux.cc index 204fa4bc4844a..f0b061b5e374f 100644 --- a/services/service_manager/zygote/host/zygote_communication_linux.cc +++ b/services/service_manager/zygote/host/zygote_communication_linux.cc @@ -4,6 +4,7 @@ #include "services/service_manager/zygote/host/zygote_communication_linux.h" +#include "content/nw/src/common/shell_switches.h" #include <string.h> #include <sys/socket.h> @@ -240,6 +241,7 @@ void ZygoteCommunication::Init( static const char* const kForwardSwitches[] = { service_manager::switches::kAllowSandboxDebugging, service_manager::switches::kDisableInProcessStackTraces, + "enable-spell-checking", service_manager::switches::kDisableSeccompFilterSandbox, service_manager::switches::kNoSandbox, }; diff --git a/services/service_manager/zygote/host/zygote_host_impl_linux.cc b/services/service_manager/zygote/host/zygote_host_impl_linux.cc index 3bd1f728c7ca3..68829851a189c 100644 --- a/services/service_manager/zygote/host/zygote_host_impl_linux.cc +++ b/services/service_manager/zygote/host/zygote_host_impl_linux.cc @@ -23,6 +23,7 @@ #include "services/service_manager/sandbox/switches.h" #include "services/service_manager/zygote/common/zygote_commands_linux.h" +#include "content/nw/src/common/shell_switches.h" namespace service_manager { namespace { @@ -72,7 +73,7 @@ ZygoteHostImpl* ZygoteHostImpl::GetInstance() { } void ZygoteHostImpl::Init(const base::CommandLine& command_line) { - if (command_line.HasSwitch(service_manager::switches::kNoSandbox)) { + if (true || command_line.HasSwitch(service_manager::switches::kNoSandbox)) { return; } @@ -116,7 +117,7 @@ void ZygoteHostImpl::Init(const base::CommandLine& command_line) { } else if (!command_line.HasSwitch( service_manager::switches::kDisableSetuidSandbox) && !sandbox_binary_.empty()) { - use_suid_sandbox_ = true; + use_suid_sandbox_ = false; // Use the SUID sandbox for adjusting OOM scores when we are using // the setuid sandbox. This is needed beacuse the processes are diff --git a/storage/browser/fileapi/isolated_context.cc b/storage/browser/fileapi/isolated_context.cc index b68810da53bc8..7be923a7d5c7d 100644 --- a/storage/browser/fileapi/isolated_context.cc +++ b/storage/browser/fileapi/isolated_context.cc @@ -161,6 +161,7 @@ IsolatedContext::Instance::Instance(FileSystemType type, filesystem_id_(filesystem_id), file_info_(file_info), path_type_(path_type), + files_(), ref_counts_(0) { DCHECK(IsSinglePathIsolatedFileSystem(type_)); } diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2ce811df7772f..fafe9dd2c0486 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json @@ -3576,24 +3576,6 @@ ] } ], - "SitePerProcess": [ - { - "platforms": [ - "chromeos", - "linux", - "win", - "mac" - ], - "experiments": [ - { - "name": "SitePerProcess_Enabled", - "enable_features": [ - "site-per-process" - ] - } - ] - } - ], "SocketReadIfReady": [ { "platforms": [ diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index f3ec52975650b..29a2f10a638e9 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h @@ -614,7 +614,7 @@ class BLINK_PLATFORM_EXPORT Platform { virtual void DidStartWorkerThread() {} virtual void WillStopWorkerThread() {} - virtual void WorkerContextCreated(const v8::Local<v8::Context>& worker) {} + virtual void WorkerContextCreated(const v8::Local<v8::Context>& worker, bool, const std::string&) {} virtual bool AllowScriptExtensionForServiceWorker(const WebURL& script_url) { return false; } diff --git a/third_party/blink/public/platform/web_security_origin.h b/third_party/blink/public/platform/web_security_origin.h index 567603e9be408..b52eb75007bf0 100644 --- a/third_party/blink/public/platform/web_security_origin.h +++ b/third_party/blink/public/platform/web_security_origin.h @@ -104,6 +104,8 @@ class WebSecurityOrigin { // passwords stored in password manager. BLINK_PLATFORM_EXPORT bool CanAccessPasswordManager() const; + BLINK_PLATFORM_EXPORT void grantUniversalAccess(); + #if INSIDE_BLINK BLINK_PLATFORM_EXPORT WebSecurityOrigin(scoped_refptr<const SecurityOrigin>); BLINK_PLATFORM_EXPORT WebSecurityOrigin& operator=( diff --git a/third_party/blink/public/web/blink.h b/third_party/blink/public/web/blink.h index e48e0e9dd5e92..fc828b2c352cd 100644 --- a/third_party/blink/public/web/blink.h +++ b/third_party/blink/public/web/blink.h @@ -37,6 +37,7 @@ namespace blink { +class WebLocalFrame; // Initialize the entire Blink (wtf, platform, core, modules and web). // If you just need wtf and platform, use Platform::initialize instead. // @@ -53,6 +54,8 @@ BLINK_EXPORT v8::Isolate* MainThreadIsolate(); BLINK_EXPORT void SetLayoutTestMode(bool); BLINK_EXPORT bool LayoutTestMode(); +BLINK_EXPORT void set_web_worker_hooks(void*); +BLINK_EXPORT void fix_gamepad_nw(WebLocalFrame*); // Enables or disables the use of the mock theme for layout tests. This function // must be called only if setLayoutTestMode(true). BLINK_EXPORT void SetMockThemeEnabledForTest(bool); diff --git a/third_party/blink/public/web/web_file_chooser_params.h b/third_party/blink/public/web/web_file_chooser_params.h index 358fb1866982d..aad191d7e1769 100644 --- a/third_party/blink/public/web/web_file_chooser_params.h +++ b/third_party/blink/public/web/web_file_chooser_params.h @@ -49,6 +49,8 @@ struct WebFileChooserParams { bool save_as; // |title| is the title for a file chooser dialog. It can be an empty string. WebString title; + // revert 14785d90f691b2b20d07612a62ba35a630bbb9ac for nwsaveas #5667 + WebString initial_value; // This contains MIME type strings such as "audio/*" "text/plain" or file // extensions beginning with a period (.) such as ".mp3" ".txt". // The dialog may restrict selectable files to files with the specified MIME @@ -79,12 +81,15 @@ struct WebFileChooserParams { // initiated by a document. WebURL requestor; + WebString initial_path; + bool extract_directory; + WebFileChooserParams() : multi_select(false), directory(false), save_as(false), use_media_capture(false), - need_local_path(true) {} + need_local_path(true), extract_directory(true) {} }; } // namespace blink diff --git a/third_party/blink/public/web/web_frame.h b/third_party/blink/public/web/web_frame.h index bd4b4f56c1328..097cabbc222de 100644 --- a/third_party/blink/public/web/web_frame.h +++ b/third_party/blink/public/web/web_frame.h @@ -84,6 +84,12 @@ class BLINK_EXPORT WebFrame { virtual WebRemoteFrame* ToWebRemoteFrame() = 0; bool Swap(WebFrame*); + virtual bool isNwFakeTop() const {return false;} + virtual void setNodeJS(bool) {} + virtual bool isNodeJS() const {return false;} + virtual bool isNwDisabledChildFrame() const {return false;} + virtual void setDevtoolsJail(WebFrame*) {} + virtual WebFrame* getDevtoolsJail() {return nullptr;} // This method closes and deletes the WebFrame. This is typically called by // the embedder in response to a frame detached callback to the WebFrame @@ -191,9 +197,8 @@ class BLINK_EXPORT WebFrame { // the given node is not a frame, iframe or if the frame is empty. static WebFrame* FromFrameOwnerElement(const WebNode&); -#if INSIDE_BLINK - // TODO(mustaq): Should be named FromCoreFrame instead. static WebFrame* FromFrame(Frame*); +#if INSIDE_BLINK static Frame* ToCoreFrame(const WebFrame&); bool InShadowTree() const { return scope_ == WebTreeScopeType::kShadow; } diff --git a/third_party/blink/public/web/web_frame_client.h b/third_party/blink/public/web/web_frame_client.h index 698ed75b392d6..959254491cb41 100644 --- a/third_party/blink/public/web/web_frame_client.h +++ b/third_party/blink/public/web/web_frame_client.h @@ -135,6 +135,8 @@ class BLINK_EXPORT WebFrameClient { virtual void BindToFrame(WebLocalFrame*) {} // Factory methods ----------------------------------------------------- + virtual void willHandleNavigationPolicy( + WebFrame*, const WebURLRequest&, WebNavigationPolicy*, WebString* manifest = NULL, bool new_win = true) { } // May return null. virtual WebPlugin* CreatePlugin(const WebPluginParams&) { return nullptr; } diff --git a/third_party/blink/public/web/web_frame_owner_properties.h b/third_party/blink/public/web/web_frame_owner_properties.h index fea9346de6a9e..f7c3877b110b9 100644 --- a/third_party/blink/public/web/web_frame_owner_properties.h +++ b/third_party/blink/public/web/web_frame_owner_properties.h @@ -16,8 +16,10 @@ namespace blink { struct WebFrameOwnerProperties { enum class ScrollingMode { kAuto, kAlwaysOff, kAlwaysOn, kLast = kAlwaysOn }; + WebString nwuseragent; WebString name; // browsing context container's name ScrollingMode scrolling_mode; + bool nwFakeTop; int margin_width; int margin_height; bool allow_fullscreen; @@ -27,7 +29,7 @@ struct WebFrameOwnerProperties { public: WebFrameOwnerProperties() - : scrolling_mode(ScrollingMode::kAuto), + : scrolling_mode(ScrollingMode::kAuto), nwFakeTop(false), margin_width(-1), margin_height(-1), allow_fullscreen(false), @@ -45,6 +47,7 @@ struct WebFrameOwnerProperties { const WebString& required_csp) : name(name), scrolling_mode(static_cast<ScrollingMode>(scrolling_mode)), + nwFakeTop(false), margin_width(margin_width), margin_height(margin_height), allow_fullscreen(allow_fullscreen), diff --git a/third_party/blink/public/web/web_node.h b/third_party/blink/public/web/web_node.h index 3148389d06ee8..ff11671044b54 100644 --- a/third_party/blink/public/web/web_node.h +++ b/third_party/blink/public/web/web_node.h @@ -106,8 +106,8 @@ class BLINK_EXPORT WebNode { template <typename T> const T ToConst() const; -#if INSIDE_BLINK WebNode(Node*); +#if INSIDE_BLINK WebNode& operator=(Node*); operator Node*() const; diff --git a/third_party/blink/public/web/web_shared_worker.h b/third_party/blink/public/web/web_shared_worker.h index f018d7cdcb5d2..2c8217ccb6bc1 100644 --- a/third_party/blink/public/web/web_shared_worker.h +++ b/third_party/blink/public/web/web_shared_worker.h @@ -40,6 +40,10 @@ #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_content_security_policy.h" +namespace base { + class FilePath; +} + namespace blink { class MessagePortChannel; @@ -57,6 +61,7 @@ class BLINK_EXPORT WebSharedWorker { static std::unique_ptr<WebSharedWorker> Create(WebSharedWorkerClient*); virtual void StartWorkerContext( + bool nodejs, const base::FilePath& root_path, const WebURL& script_url, const WebString& name, const WebString& content_security_policy, diff --git a/third_party/blink/public/web/web_shared_worker_repository_client.h b/third_party/blink/public/web/web_shared_worker_repository_client.h index 604ea8273cd2e..66913c166f522 100644 --- a/third_party/blink/public/web/web_shared_worker_repository_client.h +++ b/third_party/blink/public/web/web_shared_worker_repository_client.h @@ -49,7 +49,7 @@ class WebSharedWorkerRepositoryClient { using DocumentID = unsigned long long; // Connects to a shared worker. - virtual void Connect( + virtual void Connect(bool, const WebURL&, const WebString& name, DocumentID, diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h index 13b8542dbbc1f..ea2d28c21c2af 100644 --- a/third_party/blink/public/web/web_view_client.h +++ b/third_party/blink/public/web/web_view_client.h @@ -76,7 +76,8 @@ class WebViewClient : protected WebWidgetClient { const WebString& name, WebNavigationPolicy policy, bool suppress_opener, - WebSandboxFlags) { + WebSandboxFlags, + WebString* manifest = nullptr) { return nullptr; } @@ -181,6 +182,7 @@ class WebViewClient : protected WebWidgetClient { // the given offset (relative to the current position in session // history). virtual void NavigateBackForwardSoon(int offset) {} + virtual void NavigateBackForwardSoon2(int offset, WebLocalFrame* initiator = nullptr) {} // Returns the number of history items before/after the current // history item. diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni index 99fe62acc3abe..671404f7adbf6 100644 --- a/third_party/blink/renderer/bindings/bindings.gni +++ b/third_party/blink/renderer/bindings/bindings.gni @@ -9,6 +9,8 @@ import("//third_party/blink/renderer/bindings/modules/v8/v8.gni") bindings_core_v8_files = get_path_info([ + "core/v8/custom/v8_html_iframe_element_custom.cc", + "core/v8/custom/v8_filelist_custom.cc", "core/v8/custom/v8_custom_xpath_ns_resolver.cc", "core/v8/custom/v8_custom_xpath_ns_resolver.h", "core/v8/custom/v8_dev_tools_host_custom.cc", diff --git a/third_party/blink/renderer/bindings/core/v8/binding_security.cc b/third_party/blink/renderer/bindings/core/v8/binding_security.cc index 2f1c6a25fa926..bbdab1e656d9d 100644 --- a/third_party/blink/renderer/bindings/core/v8/binding_security.cc +++ b/third_party/blink/renderer/bindings/core/v8/binding_security.cc @@ -313,6 +313,8 @@ bool BindingSecurity::ShouldAllowAccessToCreationContext( return true; v8::Isolate* isolate = creation_context->GetIsolate(); + if (isolate->GetCurrentContext()->GetAlignedPointerFromEmbedderData(36) == (void*)0x08110800) + return true; LocalFrame* frame = ToLocalFrameIfNotDetached(creation_context); ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, type->interface_name); diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_filelist_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_filelist_custom.cc new file mode 100644 index 0000000000000..ff053b8cda76a --- /dev/null +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_filelist_custom.cc @@ -0,0 +1,24 @@ +#include "third_party/blink/renderer/bindings/core/v8/v8_file_list.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_file.h" +#include "third_party/blink/renderer/platform/bindings/v8_binding.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" + +namespace blink { +void V8FileList::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& args) +{ + ExecutionContext* context = CurrentExecutionContext(args.GetIsolate()); + if (context && context->IsDocument()) { + Document* document = ToDocument(context); + if (document->GetFrame()->isNwDisabledChildFrame()) { + V8ThrowException::ThrowTypeError(args.GetIsolate(), "FileList constructor cannot be called in nwdisabled frame."); + return; + } + } + + FileList* impl = FileList::Create(); + V8SetReturnValue(args, impl); +} + +} // namespace blink diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_html_iframe_element_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_html_iframe_element_custom.cc new file mode 100644 index 0000000000000..69c158a0a0136 --- /dev/null +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_html_iframe_element_custom.cc @@ -0,0 +1,25 @@ +#include "third_party/blink/renderer/platform/bindings/v8_binding.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_html_iframe_element.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" + +namespace blink { + +using namespace HTMLNames; + +void V8HTMLIFrameElement::nwUserAgentAttributeSetterCustom(v8::Local<v8::Value> value, const v8::FunctionCallbackInfo<v8::Value>& info) +{ + HTMLIFrameElement* frame = V8HTMLIFrameElement::ToImpl(info.Holder()); + // String agentValue = toCoreStringWithNullCheck(value); + TOSTRING_VOID(V8StringResource<>, agentValue, value); + + frame->setAttribute(HTMLNames::nwuseragentAttr, agentValue); + + if (frame->ContentFrame()->IsLocalFrame()) { + LocalFrame* lframe = ToLocalFrame(frame->ContentFrame()); + lframe->Loader().setUserAgentOverride(agentValue); + } +} + +} // namespace blink diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc index 4110b8303e7bd..64ae0760ca06d 100644 --- a/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc @@ -62,6 +62,9 @@ #include "third_party/blink/renderer/platform/layout_test_support.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" + +#include "third_party/blink/renderer/bindings/core/v8/v8_html_frame_element.h" + namespace blink { void V8Window::locationAttributeGetterCustom( @@ -137,11 +140,46 @@ void V8Window::eventAttributeGetterCustom( V8SetReturnValue(info, js_event); } +void V8Window::parentAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) +{ + LocalDOMWindow* imp = ToLocalDOMWindow(V8Window::ToImpl(info.Holder())); + LocalFrame* frame = imp->GetFrame(); + if (frame && frame->isNwFakeTop()) { + V8SetReturnValue(info, ToV8(imp, info.Holder(), info.GetIsolate())); + return; + } + V8SetReturnValue(info, ToV8(imp->parent(), info.Holder(), info.GetIsolate())); +} + +void V8Window::topAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) +{ + LocalDOMWindow* imp = ToLocalDOMWindow(V8Window::ToImpl(info.Holder())); + LocalFrame* frame = imp->GetFrame(); + if (frame) { + for (LocalFrame* f = frame; f; ) { + if (f->isNwFakeTop()) { + V8SetReturnValue(info, ToV8(f->GetDocument()->domWindow(), info.Holder(), info.GetIsolate())); + return; + } + Frame* fr = f->Tree().Parent(); + if (!fr || !fr->IsLocalFrame()) + break; + f = ToLocalFrame(fr); + } + } + V8SetReturnValue(info, ToV8(imp->top(), info.Holder(), info.GetIsolate())); +} + void V8Window::frameElementAttributeGetterCustom( const v8::FunctionCallbackInfo<v8::Value>& info) { LocalDOMWindow* impl = ToLocalDOMWindow(V8Window::ToImpl(info.Holder())); Element* frameElement = impl->frameElement(); + LocalFrame* frame = impl->GetFrame(); + if (frame && frame->isNwFakeTop()) { + V8SetReturnValueNull(info); + return; + } if (!BindingSecurity::ShouldAllowAccessTo( CurrentDOMWindow(info.GetIsolate()), frameElement, BindingSecurity::ErrorReportOption::kDoNotReport)) { diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h index 15442f0f4d19d..c2036b265d737 100644 --- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h +++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h @@ -72,7 +72,7 @@ using InstallRuntimeEnabledFeaturesFunction = const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, - v8::Local<v8::Function> interface); + v8::Local<v8::Function> interface0); using InstallRuntimeEnabledFeaturesOnTemplateFunction = InstallTemplateFunction; diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc index d9b8da2d26a06..7142fb9b181fc 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc @@ -161,6 +161,9 @@ v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue( bool ScriptController::ShouldBypassMainWorldCSP() { v8::HandleScope handle_scope(GetIsolate()); v8::Local<v8::Context> context = GetIsolate()->GetCurrentContext(); + if (GetFrame() && GetFrame()->GetDocument() && + GetFrame()->GetDocument()->GetSecurityOrigin()->hasUniversalAccess()) + return true; if (context.IsEmpty() || !ToLocalDOMWindow(context)) return false; DOMWrapperWorld& world = DOMWrapperWorld::Current(GetIsolate()); diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index c8c822632a69f..0006603969808 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h" +#include "third_party/node-nw/src/node_webkit.h" #include <memory> #include "base/memory/scoped_refptr.h" @@ -74,6 +75,9 @@ #include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h" #include "v8/include/v8-profiler.h" +extern VoidHookFn g_promise_reject_callback_fn; + + namespace blink { static void ReportFatalErrorInMainThread(const char* location, @@ -317,6 +321,12 @@ static void PromiseRejectHandler(v8::PromiseRejectMessage data, v8::Isolate* isolate = script_state->GetIsolate(); ExecutionContext* context = ExecutionContext::From(script_state); +#if 0 //FIXME (#4577) + LocalDOMWindow* window = currentDOMWindow(isolate); + if (window->frame()->isNodeJS() && g_promise_reject_callback_fn) + g_promise_reject_callback_fn(&data); +#endif + v8::Local<v8::Value> exception = data.GetValue(); if (V8DOMWrapper::IsWrapper(isolate, exception)) { // Try to get the stack & location from a wrapped exception object (e.g. @@ -605,6 +615,10 @@ static void InitializeV8Common(v8::Isolate* isolate) { namespace { +#if defined(OS_WIN) +HANDLE _process_heap; +#endif + class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { // Allocate() methods return null to signal allocation failure to V8, which // should respond by throwing a RangeError, per @@ -622,6 +636,18 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { void Free(void* data, size_t size) override { WTF::ArrayBufferContents::FreeMemory(data); } + + void Free(void* data, size_t length, AllocationMode mode) override { + if (mode == AllocationMode::kNodeJS) { +#if defined(OS_WIN) + ::HeapFree(_process_heap, 0, data); +#else + free(data); +#endif + return; + } else + Free(data, length); + } }; } // namespace @@ -648,6 +674,9 @@ void V8Initializer::InitializeMainThread(const intptr_t* reference_table) { WTF::ArrayBufferContents::Initialize(AdjustAmountOfExternalAllocatedMemory); DEFINE_STATIC_LOCAL(ArrayBufferAllocator, array_buffer_allocator, ()); +#if defined(OS_WIN) + _process_heap = ::GetProcessHeap(); +#endif auto v8_extras_mode = RuntimeEnabledFeatures::ExperimentalV8ExtrasEnabled() ? gin::IsolateHolder::kStableAndExperimentalV8Extras : gin::IsolateHolder::kStableV8Extras; diff --git a/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl b/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl index 2222a65e7441d..ede693d92204d 100644 --- a/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl @@ -1043,6 +1043,9 @@ v8::Local<v8::Object> {{v8_class}}::findInstanceInPrototypeChain(v8::Local<v8::V case v8::ArrayBuffer::Allocator::AllocationMode::kReservation: kind = WTF::ArrayBufferContents::AllocationKind::kReservation; break; + case v8::ArrayBuffer::Allocator::AllocationMode::kNodeJS: + kind = WTF::ArrayBufferContents::AllocationKind::kNodeJS; + break; default: NOTREACHED(); }; diff --git a/third_party/blink/renderer/bindings/templates/interface.h.tmpl b/third_party/blink/renderer/bindings/templates/interface.h.tmpl index 21ba3ec11f281..18032c2c28937 100644 --- a/third_party/blink/renderer/bindings/templates/interface.h.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface.h.tmpl @@ -145,7 +145,7 @@ class {{v8_class}} { {% for feature in optional_features %} - static void install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface); + static void install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface0); static void install{{feature.name}}(ScriptState*, v8::Local<v8::Object> instance); {% if not feature.needs_instance %} static void install{{feature.name}}(ScriptState*); @@ -265,7 +265,8 @@ class {{v8_class}} { const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, - v8::Local<v8::Function> interface); + v8::Local<v8::Function> interface0); + {% endif %}{# needs_runtime_enabled_installer #} {% if not is_array_buffer_or_view %} @@ -287,7 +288,7 @@ class {{v8_class}} { const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, - v8::Local<v8::Function> interface); + v8::Local<v8::Function> interface0); {% endif %}{# needs_runtime_enabled_installer #} {% if has_partial_interface %} static InstallTemplateFunction install{{v8_class}}TemplateFunction; diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 5dd25558226cd..10a15ee59bb55 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn @@ -160,7 +160,7 @@ component("core") { output_name = "blink_core" visibility = [] # Allow re-assignment of list. - visibility = [ "//third_party/blink/*" ] + visibility = [ "//third_party/blink/*", "//content/nw/*" ] # If you create a new subdirectory, make a new BUILD file for that directory # and reference it in the deps below rather than adding the sources here. diff --git a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc index 17f724a124fa4..f6eccabce855f 100644 --- a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc +++ b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc @@ -54,6 +54,8 @@ bool ClipboardCommands::CanReadClipboard(LocalFrame& frame, EditorCommandSource source) { if (source == EditorCommandSource::kMenuOrKeyBinding) return true; + if (frame.isNodeJS()) + return true; Settings* const settings = frame.GetSettings(); const bool default_value = settings && settings->GetJavaScriptCanAccessClipboard() && @@ -68,6 +70,8 @@ bool ClipboardCommands::CanWriteClipboard(LocalFrame& frame, EditorCommandSource source) { if (source == EditorCommandSource::kMenuOrKeyBinding) return true; + if (frame.isNodeJS()) + return true; Settings* const settings = frame.GetSettings(); const bool default_value = (settings && settings->GetJavaScriptCanAccessClipboard()) || @@ -78,6 +82,8 @@ bool ClipboardCommands::CanWriteClipboard(LocalFrame& frame, } bool ClipboardCommands::CanSmartReplaceInClipboard(LocalFrame& frame) { + if (frame.isNodeJS()) + return true; return frame.GetEditor().SmartInsertDeleteEnabled() && SystemClipboard::GetInstance().CanSmartReplace(); } diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index 9c999c43668fc..49ff683de2fba 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc @@ -138,6 +138,14 @@ bool IsBackForwardNavigationInProgress(LocalFrame* local_frame) { } // namespace +void LocalFrameClientImpl::willHandleNavigationPolicy(const ResourceRequest& request, NavigationPolicy* policy, WebString* manifest, bool new_win) +{ + if (web_frame_->Client()) { + WrappedResourceRequest webreq(request); + web_frame_->Client()->willHandleNavigationPolicy(web_frame_, webreq, (WebNavigationPolicy*)policy, manifest, new_win); + } +} + LocalFrameClientImpl::LocalFrameClientImpl(WebLocalFrameImpl* frame) : web_frame_(frame) {} @@ -665,7 +673,7 @@ bool LocalFrameClientImpl::NavigateBackForward(int offset) const { return false; if (offset < -webview->Client()->HistoryBackListCount()) return false; - webview->Client()->NavigateBackForwardSoon(offset); + webview->Client()->NavigateBackForwardSoon2(offset, web_frame_); return true; } @@ -921,14 +929,16 @@ void LocalFrameClientImpl::DidChangeFrameOwnerProperties( if (!web_frame_->Client()) return; - web_frame_->Client()->DidChangeFrameOwnerProperties( - WebFrame::FromFrame(frame_element->ContentFrame()), - WebFrameOwnerProperties( + WebFrameOwnerProperties ownerProperties( frame_element->BrowsingContextContainerName(), frame_element->ScrollingMode(), frame_element->MarginWidth(), frame_element->MarginHeight(), frame_element->AllowFullscreen(), frame_element->AllowPaymentRequest(), frame_element->IsDisplayNone(), - frame_element->RequiredCsp())); + frame_element->RequiredCsp()); + ownerProperties.nwFakeTop = frame_element->FastHasAttribute(HTMLNames::nwfaketopAttr); + ownerProperties.nwuseragent = frame_element->nwuseragent(); + web_frame_->Client()->DidChangeFrameOwnerProperties( + WebFrame::FromFrame(frame_element->ContentFrame()), ownerProperties); } void LocalFrameClientImpl::DispatchWillStartUsingPeerConnectionHandler( diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h index 85b53ff243c47..1f6ee0af2e582 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h @@ -63,6 +63,7 @@ class LocalFrameClientImpl final : public LocalFrameClient { // LocalFrameClient ---------------------------------------------- void DidCreateNewDocument() override; + void willHandleNavigationPolicy(const blink::ResourceRequest& request, blink::NavigationPolicy* policy, WebString* manifest = nullptr, bool new_win = true) override; // Notifies the WebView delegate that the JS window object has been cleared, // giving it a chance to bind native objects to the window before script // parsing begins. diff --git a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc index c9c405733fff4..f6f1527098fb5 100644 --- a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc +++ b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc @@ -109,7 +109,7 @@ static WebSharedWorkerRepositoryClient::DocumentID GetId(void* document) { void SharedWorkerRepositoryClientImpl::Connect(SharedWorker* worker, MessagePortChannel port, const KURL& url, - const String& name) { + const String& name, bool isNodeJS) { DCHECK(client_); // No nested workers (for now) - connect() should only be called from document @@ -136,7 +136,7 @@ void SharedWorkerRepositoryClientImpl::Connect(SharedWorker* worker, bool is_secure_context = worker->GetExecutionContext()->IsSecureContext(); std::unique_ptr<WebSharedWorkerConnectListener> listener = std::make_unique<SharedWorkerConnectListener>(worker); - client_->Connect( + client_->Connect(isNodeJS, url, name, GetId(document), header, header_type, worker->GetExecutionContext()->GetSecurityContext().AddressSpace(), ToCreationContextType(is_secure_context), diff --git a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h index 2cec65bd52bfc..edeaa33b70a75 100644 --- a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h +++ b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h @@ -58,7 +58,7 @@ class CORE_EXPORT SharedWorkerRepositoryClientImpl final void Connect(SharedWorker*, MessagePortChannel, const KURL&, - const String& name) override; + const String& name, bool) override; void DocumentDetached(Document*) override; private: diff --git a/third_party/blink/renderer/core/exported/web_frame.cc b/third_party/blink/renderer/core/exported/web_frame.cc index c94a559b0646c..66c898750cd05 100644 --- a/third_party/blink/renderer/core/exported/web_frame.cc +++ b/third_party/blink/renderer/core/exported/web_frame.cc @@ -196,6 +196,8 @@ void WebFrame::SetFrameOwnerProperties( properties.is_display_none); } + owner->set_nwfaketop(properties.nwFakeTop); + owner->set_nwuseragent(properties.nwuseragent); owner->SetBrowsingContextContainerName(properties.name); owner->SetScrollingMode(properties.scrolling_mode); owner->SetMarginWidth(properties.margin_width); diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 4a63518cc6817..ccaedae60dbb8 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc @@ -7642,7 +7642,8 @@ class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient { const WebString&, WebNavigationPolicy, bool, - WebSandboxFlags) override { + WebSandboxFlags, + WebString*) override { EXPECT_TRUE(false); return nullptr; } diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index 6c2af8c82089f..64a74dfe133e4 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc @@ -31,6 +31,17 @@ #include "third_party/blink/renderer/core/exported/web_shared_worker_impl.h" #include <memory> + +#include "third_party/node-nw/src/node_webkit.h" +#define BLINK_HOOK_MAP(type, sym, fn) extern type fn; +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + #include "services/network/public/mojom/fetch_api.mojom-blink.h" #include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/task_type.h" @@ -205,7 +216,8 @@ void WebSharedWorkerImpl::ConnectTaskOnWorkerThread( worker_global_scope->DispatchEvent(CreateConnectEvent(port)); } -void WebSharedWorkerImpl::StartWorkerContext( +void WebSharedWorkerImpl::StartWorkerContext(bool nodejs, + const base::FilePath& root_path, const WebURL& url, const WebString& name, const WebString& content_security_policy, @@ -215,6 +227,8 @@ void WebSharedWorkerImpl::StartWorkerContext( mojo::ScopedMessagePipeHandle content_settings_handle, mojo::ScopedMessagePipeHandle interface_provider) { DCHECK(IsMainThread()); + nodejs_ = nodejs; + root_path_ = root_path; url_ = url; name_ = name; creation_address_space_ = creation_address_space; @@ -286,6 +300,10 @@ void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() { Document* document = shadow_page_->GetDocument(); const SecurityOrigin* starter_origin = document->GetSecurityOrigin(); bool starter_secure_context = document->IsSecureContext(); + std::string main_script = root_path_.AsUTF8Unsafe(); + if (g_web_worker_start_thread_fn && nodejs_) { + (*g_web_worker_start_thread_fn)(nullptr, (void*)main_script_loader_->Url().GetPath().Utf8().data(), &main_script, &nodejs_); + } WorkerClients* worker_clients = WorkerClients::Create(); CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker( @@ -326,6 +344,7 @@ void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() { auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( + nodejs_, main_script, url_, script_type, document->UserAgent(), content_security_policy ? content_security_policy->Headers().get() : nullptr, diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h index ee624837d99ea..1e618d81a8099 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h @@ -81,6 +81,7 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker, // WebSharedWorker methods: void StartWorkerContext( + bool, const base::FilePath&, const WebURL&, const WebString& name, const WebString& content_security_policy, @@ -135,6 +136,8 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker, // Kept around only while main script loading is ongoing. scoped_refptr<WorkerClassicScriptLoader> main_script_loader_; + bool nodejs_; + base::FilePath root_path_; WebURL url_; WebString name_; mojom::IPAddressSpace creation_address_space_; diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 4aa77f1c7b7ab..45ea08efdc0d1 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc @@ -3434,7 +3434,8 @@ class ViewCreatingWebViewClient : public FrameTestHelpers::TestWebViewClient { const WebString& name, WebNavigationPolicy, bool, - WebSandboxFlags) override { + WebSandboxFlags, + WebString*) override { return web_view_helper_.InitializeWithOpener(opener); } diff --git a/third_party/blink/renderer/core/fileapi/file.h b/third_party/blink/renderer/core/fileapi/file.h index 39831f1902c6a..035396ad6dfe4 100644 --- a/third_party/blink/renderer/core/fileapi/file.h +++ b/third_party/blink/renderer/core/fileapi/file.h @@ -58,6 +58,10 @@ class CORE_EXPORT File final : public Blob { enum UserVisibility { kIsUserVisible, kIsNotUserVisible }; // Constructor in File.idl + static File* Create(ExecutionContext*, const String& path, const String& name, ExceptionState&) + { + return CreateForUserProvidedFile(path, name); + } static File* Create( ExecutionContext*, const HeapVector<ArrayBufferOrArrayBufferViewOrBlobOrUSVString>&, @@ -167,7 +171,7 @@ class CORE_EXPORT File final : public Blob { return path_; } const String& name() const { return name_; } - + const String& path() const { return path_; } // Getter for the lastModified IDL attribute, // http://dev.w3.org/2006/webapi/FileAPI/#file-attrs long long lastModified() const; diff --git a/third_party/blink/renderer/core/fileapi/file.idl b/third_party/blink/renderer/core/fileapi/file.idl index a74beceda3e76..dde29b1588b08 100644 --- a/third_party/blink/renderer/core/fileapi/file.idl +++ b/third_party/blink/renderer/core/fileapi/file.idl @@ -29,10 +29,12 @@ Constructor(sequence<BlobPart> fileBits, USVString fileName, optional FilePropertyBag options), ConstructorCallWith=ExecutionContext, RaisesException=Constructor, - Exposed=(Window,Worker) + Exposed=(Window,Worker), + Constructor(DOMString path, DOMString name) ] interface File : Blob { readonly attribute DOMString name; readonly attribute long long lastModified; + readonly attribute DOMString path; // Non-standard APIs [MeasureAs=FileGetLastModifiedDate] readonly attribute Date lastModifiedDate; diff --git a/third_party/blink/renderer/core/fileapi/file_list.h b/third_party/blink/renderer/core/fileapi/file_list.h index 3796379d6e716..aa31f86c867f3 100644 --- a/third_party/blink/renderer/core/fileapi/file_list.h +++ b/third_party/blink/renderer/core/fileapi/file_list.h @@ -45,6 +45,7 @@ class CORE_EXPORT FileList final : public ScriptWrappable { bool IsEmpty() const { return files_.IsEmpty(); } void clear() { files_.clear(); } + void append(File* file) { Append(file); } void Append(File* file) { files_.push_back(file); } Vector<String> PathsForUserVisibleFiles() const; diff --git a/third_party/blink/renderer/core/fileapi/file_list.idl b/third_party/blink/renderer/core/fileapi/file_list.idl index 25db9a0ba23f4..344758875a170 100644 --- a/third_party/blink/renderer/core/fileapi/file_list.idl +++ b/third_party/blink/renderer/core/fileapi/file_list.idl @@ -26,8 +26,11 @@ // https://w3c.github.io/FileAPI/#filelist-section [ + CustomConstructor, Exposed=(Window,Worker) ] interface FileList { getter File? item(unsigned long index); readonly attribute unsigned long length; + void clear(); + void append(File item); }; diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index 9a748e3e923d3..13cb189a4e777 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc @@ -278,6 +278,8 @@ bool CSPDirectiveList::CheckAncestors(SourceListDirective* directive, for (Frame* current = frame->Tree().Parent(); current; current = current->Tree().Parent()) { + if (current->IsLocalFrame() && ToLocalFrame(current)->GetDocument()->GetSecurityOrigin()->hasUniversalAccess()) + return true; // The |current| frame might be a remote frame which has no URL, so use // its origin instead. This should suffice for this check since it // doesn't do path comparisons. See https://crbug.com/582544. diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc index 8e810c34d0db6..89da375cb4ac1 100644 --- a/third_party/blink/renderer/core/frame/frame.cc +++ b/third_party/blink/renderer/core/frame/frame.cc @@ -72,6 +72,8 @@ void Frame::Trace(blink::Visitor* visitor) { visitor->Trace(window_proxy_manager_); visitor->Trace(dom_window_); visitor->Trace(client_); + visitor->Trace(dev_jail_owner_); + visitor->Trace(devtools_jail_); } void Frame::Detach(FrameDetachType type) { @@ -96,6 +98,10 @@ void Frame::Detach(FrameDetachType type) { // the frame tree. https://crbug.com/578349. DisconnectOwnerElement(); page_ = nullptr; + if (dev_jail_owner_) { + dev_jail_owner_->setDevtoolsJail(nullptr); + dev_jail_owner_ = nullptr; + } } void Frame::DisconnectOwnerElement() { @@ -291,6 +297,9 @@ Frame::Frame(FrameClient* client, owner_(owner), client_(client), window_proxy_manager_(window_proxy_manager), + devtools_jail_(nullptr), + dev_jail_owner_(nullptr), + nodejs_(false), is_loading_(false), devtools_frame_token_(client->GetDevToolsFrameToken()), create_stack_(base::debug::StackTrace()) { @@ -310,4 +319,42 @@ STATIC_ASSERT_ENUM(FrameDetachType::kRemove, STATIC_ASSERT_ENUM(FrameDetachType::kSwap, WebRemoteFrameClient::DetachType::kSwap); -} // namespace blink +bool Frame::isNwDisabledChildFrame() const +{ + const Frame* current_frame = this; + const Frame* ancestor_frame = Tree().Parent(); + do { + if (current_frame->owner_) { + if (current_frame->owner_->IsLocal()) + if (ToHTMLFrameOwnerElement(current_frame->owner_)->FastHasAttribute(nwdisableAttr)) + return true; + } + current_frame = ancestor_frame; + if (ancestor_frame) + ancestor_frame = ancestor_frame->Tree().Parent(); + } while (current_frame); + return false; +} + +void Frame::setDevtoolsJail(Frame* iframe) +{ + devtools_jail_ = iframe; + if (iframe) + iframe->dev_jail_owner_ = this; + else if (devtools_jail_) + devtools_jail_->dev_jail_owner_ = nullptr; +} + +bool Frame::isNwFakeTop() const +{ + if (owner_) { + if (owner_->IsLocal()) + if (ToHTMLFrameOwnerElement(owner_)->FastHasAttribute(nwfaketopAttr)) + return true; + } + return false; +} + + +} // namespace blink + diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h index 203bc4e02014b..ebb2ae711ab5e 100644 --- a/third_party/blink/renderer/core/frame/frame.h +++ b/third_party/blink/renderer/core/frame/frame.h @@ -76,12 +76,18 @@ enum class UserGestureStatus { kActive, kNone }; class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> { public: virtual ~Frame(); + void setNodeJS(bool node) { nodejs_ = node; } + bool isNodeJS() const { return nodejs_; } + bool isNwDisabledChildFrame() const; + bool isNwFakeTop() const; virtual void Trace(blink::Visitor*); virtual bool IsLocalFrame() const = 0; virtual bool IsRemoteFrame() const = 0; + void setDevtoolsJail(Frame* iframe); + Frame* getDevtoolsJail() { return devtools_jail_; } virtual void Navigate(Document& origin_document, const KURL&, bool replace_current_item, @@ -284,6 +290,9 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> { Member<FrameClient> client_; const Member<WindowProxyManager> window_proxy_manager_; // TODO(sashab): Investigate if this can be represented with m_lifecycle. + Member<Frame> devtools_jail_; + Member<Frame> dev_jail_owner_; + bool nodejs_; bool is_loading_; base::UnguessableToken devtools_frame_token_; base::Optional<CString> trace_value_; diff --git a/third_party/blink/renderer/core/frame/frame_owner.h b/third_party/blink/renderer/core/frame/frame_owner.h index 313350e7a276c..0645b40191c8e 100644 --- a/third_party/blink/renderer/core/frame/frame_owner.h +++ b/third_party/blink/renderer/core/frame/frame_owner.h @@ -49,6 +49,8 @@ class CORE_EXPORT FrameOwner : public GarbageCollectedMixin { // relevant for SVG documents that are embedded via <object> or <embed>. virtual void IntrinsicSizingInfoChanged() = 0; + virtual AtomicString nwuseragent() const = 0; + virtual bool nwfaketop() const = 0; // Returns the 'name' content attribute value of the browsing context // container. // https://html.spec.whatwg.org/multipage/browsers.html#browsing-context-container @@ -92,6 +94,8 @@ class CORE_EXPORT DummyFrameOwner final AtomicString BrowsingContextContainerName() const override { return AtomicString(); } + AtomicString nwuseragent() const override { return AtomicString(); } + bool nwfaketop() const override { return false; } ScrollbarMode ScrollingMode() const override { return kScrollbarAuto; } int MarginWidth() const override { return -1; } int MarginHeight() const override { return -1; } diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index c8babd054cbd4..ffa9d4783cd65 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc @@ -1584,10 +1584,10 @@ DOMWindow* LocalDOMWindow::open(const String& url_string, // In those cases, we schedule a location change right now and return early. Frame* target_frame = nullptr; if (EqualIgnoringASCIICase(frame_name, "_top")) { - target_frame = &GetFrame()->Tree().Top(); + target_frame = GetFrame()->isNwFakeTop() ? GetFrame() : &GetFrame()->Tree().Top(); } else if (EqualIgnoringASCIICase(frame_name, "_parent")) { if (Frame* parent = GetFrame()->Tree().Parent()) - target_frame = parent; + target_frame = GetFrame()->isNwFakeTop() ? GetFrame() : parent; else target_frame = GetFrame(); } diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 53d77b624e48a..8f431e7f24d85 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h @@ -110,6 +110,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient { virtual WebFrame* GetWebFrame() const { return nullptr; } virtual bool HasWebView() const = 0; // mainly for assertions + virtual void willHandleNavigationPolicy(const ResourceRequest& request, NavigationPolicy* policy, WebString* manifest = NULL, bool new_win = true) {} virtual void WillBeDetached() = 0; virtual void DispatchWillSendRequest(ResourceRequest&) = 0; diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc index 4b4a006ba08c6..fa9672f10c4b9 100644 --- a/third_party/blink/renderer/core/frame/location.cc +++ b/third_party/blink/renderer/core/frame/location.cc @@ -103,7 +103,10 @@ DOMStringList* Location::ancestorOrigins() const { frame = frame->Tree().Parent()) { origins->Append( frame->GetSecurityContext()->GetSecurityOrigin()->ToString()); + if (dom_window_->GetFrame()->isNwFakeTop()) + break; } + return origins; } diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.cc b/third_party/blink/renderer/core/frame/remote_frame_owner.cc index ae9c65e6627b2..f8bc14c651d12 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_owner.cc +++ b/third_party/blink/renderer/core/frame/remote_frame_owner.cc @@ -21,6 +21,8 @@ RemoteFrameOwner::RemoteFrameOwner( : sandbox_flags_(flags), browsing_context_container_name_( static_cast<String>(frame_owner_properties.name)), + nwfaketop_(frame_owner_properties.nwFakeTop), + nwuseragent_(frame_owner_properties.nwuseragent), scrolling_( static_cast<ScrollbarMode>(frame_owner_properties.scrolling_mode)), margin_width_(frame_owner_properties.margin_width), diff --git a/third_party/blink/renderer/core/frame/remote_frame_owner.h b/third_party/blink/renderer/core/frame/remote_frame_owner.h index 4dfeab05280e5..871dbe9278be5 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_owner.h +++ b/third_party/blink/renderer/core/frame/remote_frame_owner.h @@ -81,6 +81,11 @@ class CORE_EXPORT RemoteFrameOwner final container_policy_ = container_policy; } + bool nwfaketop() const override { return nwfaketop_; } + AtomicString nwuseragent() const override { return nwuseragent_; } + void set_nwfaketop(bool flag) { nwfaketop_ = flag; } + void set_nwuseragent(const WebString& agent) { nwuseragent_ = agent; } + void Trace(blink::Visitor*) override; private: @@ -96,6 +101,8 @@ class CORE_EXPORT RemoteFrameOwner final Member<Frame> frame_; SandboxFlags sandbox_flags_; AtomicString browsing_context_container_name_; + bool nwfaketop_; + WebString nwuseragent_; ScrollbarMode scrolling_; int margin_width_; int margin_height_; diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index db86ae3c5eb46..246ea4bc967e6 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc @@ -1848,6 +1848,8 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame( owner_element->MarginHeight(), owner_element->AllowFullscreen(), owner_element->AllowPaymentRequest(), owner_element->IsDisplayNone(), owner_element->RequiredCsp()); + owner_properties.nwFakeTop = owner_element->FastHasAttribute(HTMLNames::nwfaketopAttr); + owner_properties.nwuseragent = owner_element->nwuseragent(); // FIXME: Using subResourceAttributeName as fallback is not a perfect // solution. subResourceAttributeName returns just one attribute name. The // element might not have the attribute, and there might be other attributes diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 0adc92eb48f2e..e2d9658fad9b5 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h @@ -405,6 +405,14 @@ class CORE_EXPORT WebLocalFrameImpl final } void SetInputEventsScaleForEmulation(float); + void setNodeJS(bool node) override { GetFrame()->setNodeJS(node); } + bool isNodeJS() const override { return GetFrame()->isNodeJS(); } + bool isNwDisabledChildFrame() const override { return GetFrame()->isNwDisabledChildFrame(); } + bool isNwFakeTop() const override { return GetFrame()->isNwFakeTop(); } + void setDevtoolsJail(WebFrame* iframe) override { + GetFrame()->setDevtoolsJail(iframe ? static_cast<const WebLocalFrameImpl*>(iframe)->GetFrame() : nullptr); + } + WebFrame* getDevtoolsJail() override { return FromFrame((blink::LocalFrame*)GetFrame()->getDevtoolsJail()); } WebTextCheckClient* GetTextCheckerClient() const { return text_check_client_; diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl index a09665a4de407..f46b8d5f65738 100644 --- a/third_party/blink/renderer/core/frame/window.idl +++ b/third_party/blink/renderer/core/frame/window.idl @@ -69,10 +69,10 @@ // other browsing contexts [Replaceable, CrossOrigin] readonly attribute Window frames; [Replaceable, CrossOrigin] readonly attribute unsigned long length; - [Unforgeable, CrossOrigin] readonly attribute Window? top; + [Unforgeable, CrossOrigin, Custom=Getter] readonly attribute Window? top; // FIXME: opener should be of type any. [CrossOrigin, Custom=Setter] attribute Window opener; - [Replaceable, CrossOrigin] readonly attribute Window? parent; + [Replaceable, CrossOrigin, Custom=Getter] readonly attribute Window? parent; [CheckSecurity=ReturnValue, Custom=Getter] readonly attribute Element? frameElement; [CallWith=(ExecutionContext,CurrentWindow,EnteredWindow), RaisesException] Window? open(optional [TreatNullAs=EmptyString] USVString url="", optional DOMString target = "_blank", optional [TreatNullAs=EmptyString] DOMString features = ""); diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index 365e652ee20a3..b9a5c3ba28806 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc @@ -93,7 +93,7 @@ bool AllowedToRequestFullscreen(Document& document) { // true: // The algorithm is triggered by a user activation. - if (Frame::HasTransientUserActivation(document.GetFrame())) + if (Frame::HasTransientUserActivation(document.GetFrame()) || document.GetFrame()->isNodeJS()) return true; // The algorithm is triggered by a user generated orientation change. diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index d61466f589455..29ff6ae460b63 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc @@ -851,7 +851,7 @@ String HTMLCanvasElement::ToDataURLInternal( String HTMLCanvasElement::toDataURL(const String& mime_type, const ScriptValue& quality_argument, ExceptionState& exception_state) const { - if (!OriginClean()) { + if (!GetDocument().GetFrame()->isNodeJS() && !OriginClean()) { exception_state.ThrowSecurityError("Tainted canvases may not be exported."); return String(); } @@ -870,7 +870,7 @@ void HTMLCanvasElement::toBlob(V8BlobCallback* callback, const String& mime_type, const ScriptValue& quality_argument, ExceptionState& exception_state) { - if (!OriginClean()) { + if (!GetDocument().GetFrame()->isNodeJS() && !OriginClean()) { exception_state.ThrowSecurityError("Tainted canvases may not be exported."); return; } diff --git a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc index 628c3854337e0..d4f119db42cfd 100644 --- a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc @@ -24,6 +24,7 @@ */ #include "third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/bindings/core/v8/exception_state.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -61,7 +62,7 @@ void ChooserOnlyTemporalInputTypeView::Trace(blink::Visitor* visitor) { void ChooserOnlyTemporalInputTypeView::HandleDOMActivateEvent(Event* event) { Document& document = GetElement().GetDocument(); if (GetElement().IsDisabledOrReadOnly() || !GetElement().GetLayoutObject() || - !Frame::HasTransientUserActivation(document.GetFrame()) || + (!Frame::HasTransientUserActivation(document.GetFrame()) && !document.GetFrame()->isNodeJS()) || GetElement().OpenShadowRoot()) return; diff --git a/third_party/blink/renderer/core/html/forms/color_input_type.cc b/third_party/blink/renderer/core/html/forms/color_input_type.cc index ab0b2d5e477bc..f340a2b04af6d 100644 --- a/third_party/blink/renderer/core/html/forms/color_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/color_input_type.cc @@ -150,7 +150,7 @@ void ColorInputType::HandleDOMActivateEvent(Event* event) { return; Document& document = GetElement().GetDocument(); - if (!Frame::HasTransientUserActivation(document.GetFrame())) + if (!Frame::HasTransientUserActivation(document.GetFrame()) && !document.GetFrame()->isNodeJS()) return; ChromeClient* chrome_client = GetChromeClient(); diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.cc b/third_party/blink/renderer/core/html/forms/file_chooser.cc index ebc3146a21d5d..937eb0523faeb 100644 --- a/third_party/blink/renderer/core/html/forms/file_chooser.cc +++ b/third_party/blink/renderer/core/html/forms/file_chooser.cc @@ -54,6 +54,7 @@ scoped_refptr<FileChooser> FileChooser::Create( FileChooser::~FileChooser() = default; void FileChooser::ChooseFiles(const Vector<FileChooserFileInfo>& files) { + bool canceled = false; // FIXME: This is inelegant. We should not be looking at params_ here. if (params_.selected_files.size() == files.size()) { bool was_changed = false; @@ -64,11 +65,11 @@ void FileChooser::ChooseFiles(const Vector<FileChooserFileInfo>& files) { } } if (!was_changed) - return; + canceled = true; } if (client_) - client_->FilesChosen(files); + client_->FilesChosen(files, canceled); } } // namespace blink diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.h b/third_party/blink/renderer/core/html/forms/file_chooser.h index b0d4ce85213a2..33f73b719ac15 100644 --- a/third_party/blink/renderer/core/html/forms/file_chooser.h +++ b/third_party/blink/renderer/core/html/forms/file_chooser.h @@ -62,7 +62,7 @@ struct FileChooserFileInfo { class FileChooserClient : public GarbageCollectedMixin { public: - virtual void FilesChosen(const Vector<FileChooserFileInfo>&) = 0; + virtual void FilesChosen(const Vector<FileChooserFileInfo>&, bool canceled = false) = 0; virtual ~FileChooserClient(); protected: diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc index ac9f83feee2f1..ef5767ef65fe4 100644 --- a/third_party/blink/renderer/core/html/forms/file_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc @@ -147,14 +147,14 @@ void FileInputType::HandleDOMActivateEvent(Event* event) { if (GetElement().IsDisabledFormControl()) return; - if (!Frame::HasTransientUserActivation(GetElement().GetDocument().GetFrame())) + if (!Frame::HasTransientUserActivation(GetElement().GetDocument().GetFrame()) && !GetElement().GetDocument().GetFrame()->isNodeJS()) return; if (ChromeClient* chrome_client = GetChromeClient()) { WebFileChooserParams params; HTMLInputElement& input = GetElement(); Document& document = input.GetDocument(); - bool is_directory = input.FastHasAttribute(webkitdirectoryAttr); + bool is_directory = input.FastHasAttribute(webkitdirectoryAttr) || input.FastHasAttribute(nwdirectoryAttr); params.directory = is_directory; params.need_local_path = is_directory; params.multi_select = is_directory || input.FastHasAttribute(multipleAttr); @@ -163,6 +163,14 @@ void FileInputType::HandleDOMActivateEvent(Event* event) { params.use_media_capture = RuntimeEnabledFeatures::MediaCaptureEnabled() && input.FastHasAttribute(captureAttr); params.requestor = document.Url(); + params.initial_path = input.nwworkingdir(); + params.save_as = input.FastHasAttribute(nwsaveasAttr); + params.initial_value = input.nwsaveas(); + params.extract_directory = input.FastHasAttribute(webkitdirectoryAttr); + if (params.selected_files.size() > 0) + params.initial_value = params.selected_files[0]; + if (input.FastHasAttribute(nwdirectorydescAttr)) + params.title = input.FastGetAttribute(nwdirectorydescAttr); UseCounter::Count( document, document.IsSecureContext() @@ -209,7 +217,15 @@ String FileInputType::ValueInFilenameValueMode() const { // decided to try to parse the value by looking for backslashes // (because that's what Windows file paths use). To be compatible // with that code, we make up a fake path for the file. - return "C:\\fakepath\\" + file_list_->item(0)->name(); + //return "C:\\fakepath\\" + file_list_->item(0)->name(); + unsigned numFiles = file_list_->length(); + StringBuilder val; + val.Append(file_list_->item(0)->path()); + for (unsigned i = 1; i < numFiles; ++i) { + val.Append(';'); + val.Append(file_list_->item(i)->path()); + } + return val.ToString(); } void FileInputType::SetValue(const String&, @@ -344,7 +360,12 @@ void FileInputType::SetFiles(FileList* files) { } } -void FileInputType::FilesChosen(const Vector<FileChooserFileInfo>& files) { +void FileInputType::FilesChosen(const Vector<FileChooserFileInfo>& files, bool canceled) { + if (canceled) { + GetElement().DispatchScopedEvent(Event::CreateBubble(EventTypeNames::cancel)); + return; + } + SetFiles(CreateFileList(files, GetElement().FastHasAttribute(webkitdirectoryAttr))); } diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.h b/third_party/blink/renderer/core/html/forms/file_input_type.h index 25aa374372fb5..e8fd34931ec6f 100644 --- a/third_party/blink/renderer/core/html/forms/file_input_type.h +++ b/third_party/blink/renderer/core/html/forms/file_input_type.h @@ -96,7 +96,7 @@ class CORE_EXPORT FileInputType final : public InputType, void HandleKeyupEvent(KeyboardEvent*) override; // FileChooserClient implementation. - void FilesChosen(const Vector<FileChooserFileInfo>&) override; + void FilesChosen(const Vector<FileChooserFileInfo>&, bool canceled = false) override; void SetFilesFromDirectory(const String&); diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index d696f9bd7a345..ef1240e323c93 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc @@ -1739,6 +1739,16 @@ bool HTMLInputElement::IsInRequiredRadioButtonGroup() { return false; } +const AtomicString& HTMLInputElement::nwworkingdir() const +{ + return FastGetAttribute(nwworkingdirAttr); +} + +void HTMLInputElement::setNwworkingdir(const AtomicString& value) +{ + setAttribute(nwworkingdirAttr, value); +} + HTMLInputElement* HTMLInputElement::CheckedRadioButtonForGroup() { if (checked()) return this; @@ -1747,6 +1757,16 @@ HTMLInputElement* HTMLInputElement::CheckedRadioButtonForGroup() { return nullptr; } +String HTMLInputElement::nwsaveas() const +{ + return FastGetAttribute(nwsaveasAttr); +} + +void HTMLInputElement::setNwsaveas(const String& value) +{ + setAttribute(nwsaveasAttr, AtomicString(value)); +} + RadioButtonGroupScope* HTMLInputElement::GetRadioButtonGroupScope() const { // FIXME: Remove type check. if (type() != InputTypeNames::radio) diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h index eae585d781159..6df117725d6c2 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.h +++ b/third_party/blink/renderer/core/html/forms/html_input_element.h @@ -265,6 +265,10 @@ class CORE_EXPORT HTMLInputElement void EndEditing(); + const AtomicString& nwworkingdir() const; + void setNwworkingdir(const AtomicString& value); + String nwsaveas() const; + void setNwsaveas(const String& value); static Vector<FileChooserFileInfo> FilesFromFileInputFormControlState( const FormControlState&); diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.idl b/third_party/blink/renderer/core/html/forms/html_input_element.idl index 099fed4b5269b..9292630b2d1b7 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.idl +++ b/third_party/blink/renderer/core/html/forms/html_input_element.idl @@ -104,6 +104,9 @@ enum SelectionMode { "select", "start", "end", "preserve" }; // https://w3c.github.io/html-media-capture/#the-capture-attribute [Measure, RuntimeEnabled=MediaCapture, Reflect] attribute DOMString capture; + attribute DOMString nwworkingdir; + [Reflect] attribute boolean nwdirectory; + attribute DOMString nwsaveas; // Non-standard APIs [Reflect, MeasureAs=PrefixedDirectoryAttribute] attribute boolean webkitdirectory; [Reflect, MeasureAs=IncrementalAttribute] attribute boolean incremental; diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5 index d7d223e55187e..d2cd291425962 100644 --- a/third_party/blink/renderer/core/html/html_attribute_names.json5 +++ b/third_party/blink/renderer/core/html/html_attribute_names.json5 @@ -308,5 +308,12 @@ "webkitdirectory", "width", "wrap", + "nwworkingdir", + "nwdisable", + "nwfaketop", + "nwdirectory", + "nwdirectorydesc", + "nwsaveas", + "nwuseragent", ], } diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index 41b4d004b0300..d8e3db5a17cc4 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h @@ -104,6 +104,12 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement, AtomicString BrowsingContextContainerName() const override { return getAttribute(HTMLNames::nameAttr); } + AtomicString nwuseragent() const override { + return getAttribute(HTMLNames::nwuseragentAttr); + } + bool nwfaketop() const override { + return hasAttribute(HTMLNames::nwfaketopAttr); + } ScrollbarMode ScrollingMode() const override { return kScrollbarAuto; } int MarginWidth() const override { return -1; } int MarginHeight() const override { return -1; } diff --git a/third_party/blink/renderer/core/html/html_html_element.cc b/third_party/blink/renderer/core/html/html_html_element.cc index e245adb340328..338f011a9394b 100644 --- a/third_party/blink/renderer/core/html/html_html_element.cc +++ b/third_party/blink/renderer/core/html/html_html_element.cc @@ -58,6 +58,7 @@ void HTMLHtmlElement::InsertedByParser() { GetDocument().Parser()->DocumentElementAvailable(); if (GetDocument().GetFrame()) { GetDocument().GetFrame()->Loader().DispatchDocumentElementAvailable(); + if (GetDocument().GetFrame()) GetDocument().GetFrame()->Loader().RunScriptsAtDocumentElementAvailable(); // runScriptsAtDocumentElementAvailable might have invalidated m_document. } diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 7b169fc1dd800..dc43e22b798de 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc @@ -23,6 +23,7 @@ */ #include "third_party/blink/renderer/core/html/html_iframe_element.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/css_property_names.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" @@ -140,6 +141,17 @@ void HTMLIFrameElement::ParseAttribute( "Error while parsing the 'sandbox' attribute: " + invalid_tokens)); } UseCounter::Count(GetDocument(), WebFeature::kSandboxViaIFrame); + } else if (name == nwuseragentAttr) { + if (nwuseragent_ != value) { + nwuseragent_ = value; + FrameOwnerPropertiesChanged(); + } + } else if (name == nwfaketopAttr) { + bool old_faketop = nwfaketop_; + nwfaketop_ = !value.IsNull(); + if (nwfaketop_ != old_faketop) { + FrameOwnerPropertiesChanged(); + } } else if (name == referrerpolicyAttr) { referrer_policy_ = kReferrerPolicyDefault; if (!value.IsNull()) { diff --git a/third_party/blink/renderer/core/html/html_iframe_element.h b/third_party/blink/renderer/core/html/html_iframe_element.h index 4b898d38257b6..7b62c52609c5e 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.h +++ b/third_party/blink/renderer/core/html/html_iframe_element.h @@ -76,11 +76,15 @@ class CORE_EXPORT HTMLIFrameElement final bool AllowFullscreen() const override { return allow_fullscreen_; } bool AllowPaymentRequest() const override { return allow_payment_request_; } AtomicString RequiredCsp() const override { return required_csp_; } + AtomicString nwuseragent() const override { return nwuseragent_; } + bool nwfaketop() const override { return nwfaketop_; } + AtomicString nwuseragent_; AtomicString name_; AtomicString required_csp_; AtomicString allow_; bool allow_fullscreen_; + bool nwfaketop_; bool allow_payment_request_; bool collapsed_by_client_; Member<HTMLIFrameElementSandbox> sandbox_; diff --git a/third_party/blink/renderer/core/html/html_iframe_element.idl b/third_party/blink/renderer/core/html/html_iframe_element.idl index 88255f5b12caf..02181f30d6a1b 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.idl +++ b/third_party/blink/renderer/core/html/html_iframe_element.idl @@ -27,6 +27,9 @@ interface HTMLIFrameElement : HTMLElement { [PutForwards=value] readonly attribute DOMTokenList sandbox; // Note: The seamless attribute was once supported, but was removed. [CEReactions, Reflect] attribute boolean allowFullscreen; + [CEReactions, Reflect] attribute boolean nwdisable; + [CEReactions, Reflect] attribute boolean nwfaketop; + [CEReactions, Reflect, TreatNullAs=NullString, Custom=Setter] attribute DOMString nwUserAgent; [CEReactions, Reflect] attribute DOMString width; [CEReactions, Reflect] attribute DOMString height; diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc index 2b382dc0094ab..cdcb4e9816d19 100644 --- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc +++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc @@ -45,6 +45,8 @@ bool IsDocumentCrossOrigin(const Document& document) { bool IsDocumentWhitelisted(const Document& document) { DCHECK(document.GetSettings()); + if (document.GetFrame()->isNodeJS()) + return true; const String& whitelist_scope = document.GetSettings()->GetMediaPlaybackGestureWhitelistScope(); if (whitelist_scope.IsNull() || whitelist_scope.IsEmpty()) @@ -252,7 +254,7 @@ bool AutoplayPolicy::RequestAutoplayByAttribute() { } base::Optional<ExceptionCode> AutoplayPolicy::RequestPlay() { - if (!Frame::HasTransientUserActivation(element_->GetDocument().GetFrame())) { + if (!Frame::HasTransientUserActivation(element_->GetDocument().GetFrame()) && !element_->GetDocument().GetFrame()->isNodeJS()) { autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kMethod); if (IsGestureNeededForPlayback()) { autoplay_uma_helper_->RecordCrossOriginAutoplayResult( diff --git a/third_party/blink/renderer/core/inspector/inspected_frames.h b/third_party/blink/renderer/core/inspector/inspected_frames.h index 0e2eda6e83e1b..f383a0b8271d7 100644 --- a/third_party/blink/renderer/core/inspector/inspected_frames.h +++ b/third_party/blink/renderer/core/inspector/inspected_frames.h @@ -11,6 +11,8 @@ #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" + namespace blink { class LocalFrame; @@ -38,7 +40,11 @@ class CORE_EXPORT InspectedFrames final explicit InspectedFrames(LocalFrame*); - LocalFrame* Root() { return root_; } + LocalFrame* Root() { + LocalFrame* f = root_; + LocalFrame* jail = (LocalFrame*)f->getDevtoolsJail(); + return jail ? jail : f; + } bool Contains(LocalFrame*) const; LocalFrame* FrameWithSecurityOrigin(const String& origin_raw_string); Iterator begin(); diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc index dad9635a1b078..d6c4a09e899f0 100644 --- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc @@ -32,7 +32,7 @@ LayoutWorkletGlobalScopeProxy::LayoutWorkletGlobalScopeProxy( reporting_proxy_ = std::make_unique<MainThreadWorkletReportingProxy>(document); - auto creation_params = std::make_unique<GlobalScopeCreationParams>( + auto creation_params = std::make_unique<GlobalScopeCreationParams>(false, std::string(), document->Url(), ScriptType::kModule, document->UserAgent(), document->GetContentSecurityPolicy()->Headers().get(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 1bc2a94c0459e..d1e13db30677d 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h @@ -98,7 +98,8 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient { const FrameLoadRequest&, const WebWindowFeatures&, NavigationPolicy, - SandboxFlags) override { + SandboxFlags, + WebString*) override { return nullptr; } void Show(NavigationPolicy) override {} diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 8fea0821d8d6b..e44bed657ccf2 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc @@ -260,10 +260,22 @@ void FrameLoader::Init() { document_loader_->SetSentDidFinishLoad(); if (frame_->GetPage()->Paused()) SetDefersLoading(true); - + if (HTMLFrameOwnerElement* ownerElement = frame_->DeprecatedLocalOwner()) { + setUserAgentOverride(ownerElement->FastGetAttribute(nwuseragentAttr)); + } TakeObjectSnapshot(); } +void FrameLoader::setUserAgentOverride(const String& agent) +{ + user_agent_override_ = agent; +} + +String FrameLoader::userAgentOverride() const +{ + return user_agent_override_; +} + LocalFrameClient* FrameLoader::Client() const { return frame_->Client(); } @@ -910,16 +922,26 @@ void FrameLoader::LoadInternal(const FrameLoadRequest& passed_request, SetReferrerForFrameRequest(request); - if (!target_frame && !request.FrameName().IsEmpty()) { + if ((!target_frame && !request.FrameName().IsEmpty()) || + policy == kNavigationPolicyNewBackgroundTab || policy == kNavigationPolicyNewForegroundTab) { + if (request.FrameName() == "_blank") + policy = kNavigationPolicyNewWindow; + WebString manifest; + Client()->willHandleNavigationPolicy(request.GetResourceRequest(), &policy, &manifest); + if (policy == kNavigationPolicyIgnore) + return; + if (policy != kNavigationPolicyCurrentTab && !target_frame && !request.FrameName().IsEmpty()) { if (policy == kNavigationPolicyDownload) { Client()->DownloadURL(request.GetResourceRequest()); - return; // Navigation/download will be handled by the client. - } else if (ShouldNavigateTargetFrame(policy)) { + } else { + //revert be2f0da0b064edc7e59d08129538a09d3b2f30c1 + //WebContents created via ctrl-click should be in a new process request.GetResourceRequest().SetFrameType( network::mojom::RequestContextFrameType::kAuxiliary); - CreateWindowForRequest(request, *frame_, policy); + CreateWindowForRequest(request, *frame_, policy, manifest); return; // Navigation will be handled by the new frame/window. } + } } if (!frame_->IsNavigationAllowed()) @@ -1279,6 +1301,15 @@ void FrameLoader::RestoreScrollPositionAndViewState( } String FrameLoader::UserAgent() const { + LocalFrame* frame = frame_; + while (frame) { + if (!frame->Loader().user_agent_override_.IsEmpty()) + return frame->Loader().user_agent_override_; + Frame* f = frame->Tree().Parent(); + if (!f || !f->IsLocalFrame()) + break; + frame = ToLocalFrame(f); + } String user_agent = Client()->UserAgent(); probe::applyUserAgentOverride(frame_->GetDocument(), &user_agent); return user_agent; @@ -1500,6 +1531,15 @@ NavigationPolicy FrameLoader::CheckLoadCanStart( NavigationPolicy navigation_policy, NavigationType navigation_type, bool check_with_client) { + ResourceRequest& resource_request = frame_load_request.GetResourceRequest(); + NavigationPolicy policy = NavigationPolicyForRequest(frame_load_request); + WebURLRequest::RequestContext context = resource_request.GetRequestContext(); + if (context == WebURLRequest::kRequestContextHyperlink || + context == WebURLRequest::kRequestContextForm) { + Client()->willHandleNavigationPolicy(resource_request, &policy, NULL, false); + if (policy == kNavigationPolicyIgnore) + return policy; + } if (frame_->GetDocument()->PageDismissalEventBeingDispatched() != Document::kNoDismissal) { return kNavigationPolicyIgnore; @@ -1507,7 +1547,6 @@ NavigationPolicy FrameLoader::CheckLoadCanStart( // Record the latest requiredCSP value that will be used when sending this // request. - ResourceRequest& resource_request = frame_load_request.GetResourceRequest(); RecordLatestRequiredCSP(); // Before modifying the request, check report-only CSP headers to give the // site owner a chance to learn about requests that need to be modified. diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h index ef54c5c43eadc..6eb20cb84a6d6 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.h +++ b/third_party/blink/renderer/core/loader/frame_loader.h @@ -204,6 +204,8 @@ class CORE_EXPORT FrameLoader final { void SaveScrollAnchor(); void SaveScrollState(); void RestoreScrollPositionAndViewState(); + void setUserAgentOverride(const String& agent); + String userAgentOverride() const; // The navigation should only be continued immediately in this frame if this // returns NavigationPolicyCurrentTab. @@ -328,6 +330,7 @@ class CORE_EXPORT FrameLoader final { bool in_restore_scroll_; SandboxFlags forced_sandbox_flags_; + String user_agent_override_; bool dispatching_did_clear_window_object_in_main_world_; bool protect_provisional_loader_; diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 38befcf26bba4..df2dda73dfe09 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h @@ -144,7 +144,8 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient { const FrameLoadRequest&, const WebWindowFeatures&, NavigationPolicy, - SandboxFlags) = 0; + SandboxFlags, + WebString* manifest = nullptr) = 0; virtual void Show(NavigationPolicy) = 0; // All the parameters should be in viewport space. That is, if an event diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 50350ccbc3f7f..da732cad9fcaf 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc @@ -254,7 +254,8 @@ Page* ChromeClientImpl::CreateWindow(LocalFrame* frame, const FrameLoadRequest& r, const WebWindowFeatures& features, NavigationPolicy navigation_policy, - SandboxFlags sandbox_flags) { + SandboxFlags sandbox_flags, + WebString* manifest) { if (!web_view_->Client()) return nullptr; @@ -270,7 +271,7 @@ Page* ChromeClientImpl::CreateWindow(LocalFrame* frame, WrappedResourceRequest(r.GetResourceRequest()), features, frame_name, static_cast<WebNavigationPolicy>(navigation_policy), r.GetShouldSetOpener() == kNeverSetOpener, - static_cast<WebSandboxFlags>(sandbox_flags))); + static_cast<WebSandboxFlags>(sandbox_flags), manifest)); if (!new_view) return nullptr; return new_view->GetPage(); @@ -584,6 +585,7 @@ void ChromeClientImpl::OpenFileChooser( if (doc) doc->MaybeQueueSendDidEditFieldInInsecureContext(); const WebFileChooserParams& params = file_chooser->Params(); + WebFileChooserCompletionImpl* chooser_completion = new WebFileChooserCompletionImpl(std::move(file_chooser)); if (client->RunFileChooser(params, chooser_completion)) diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h index 9bac9a2695cd1..0986fc9a81bc9 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.h +++ b/third_party/blink/renderer/core/page/chrome_client_impl.h @@ -76,7 +76,7 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient { const FrameLoadRequest&, const WebWindowFeatures&, NavigationPolicy, - SandboxFlags) override; + SandboxFlags, WebString*) override; void Show(NavigationPolicy) override; void DidOverscroll(const FloatSize& overscroll_delta, const FloatSize& accumulated_overscroll, diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index ffd35a270678f..aac05edc4ab66 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc @@ -52,6 +52,8 @@ #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h" +#include "third_party/blink/renderer/core/frame/local_frame_client.h" + namespace blink { namespace { @@ -294,7 +296,7 @@ static Frame* CreateNewWindow(LocalFrame& opener_frame, const FrameLoadRequest& request, const WebWindowFeatures& features, NavigationPolicy policy, - bool& created) { + bool& created, WebString* manifest) { Page* old_page = opener_frame.GetPage(); if (!old_page) return nullptr; @@ -308,8 +310,9 @@ static Frame* CreateNewWindow(LocalFrame& opener_frame, ? opener_frame.GetSecurityContext()->GetSandboxFlags() : kSandboxNone; + WebString manifest_str(*manifest); Page* page = old_page->GetChromeClient().CreateWindow( - &opener_frame, request, features, policy, sandbox_flags); + &opener_frame, request, features, policy, sandbox_flags, &manifest_str); if (!page) return nullptr; @@ -358,7 +361,7 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame, const FrameLoadRequest& request, const WebWindowFeatures& features, NavigationPolicy policy, - bool& created) { + bool& created, WebString* manifest) { DCHECK(request.GetResourceRequest().RequestorOrigin() || opener_frame.GetDocument()->Url().IsEmpty()); DCHECK_EQ(request.GetResourceRequest().GetFrameType(), @@ -399,7 +402,7 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame, return window; } - return CreateNewWindow(opener_frame, request, features, policy, created); + return CreateNewWindow(opener_frame, request, features, policy, created, manifest); } DOMWindow* CreateWindow(const String& url_string, @@ -465,20 +468,36 @@ DOMWindow* CreateWindow(const String& url_string, // createWindow(LocalFrame& openerFrame, ...). // This value will be set in ResourceRequest loaded in a new LocalFrame. bool has_user_gesture = Frame::HasTransientUserActivation(&opener_frame); + NavigationPolicy navigationPolicy = kNavigationPolicyNewForegroundTab; + WebString manifest; + opener_frame.Client()->willHandleNavigationPolicy(frame_request.GetResourceRequest(), &navigationPolicy, &manifest); // We pass the opener frame for the lookupFrame in case the active frame is // different from the opener frame, and the name references a frame relative // to the opener frame. - bool created; - Frame* new_frame = CreateWindowHelper( + bool created = false; + Frame* new_frame = nullptr; + if (navigationPolicy != kNavigationPolicyIgnore && + navigationPolicy != kNavigationPolicyCurrentTab) { + new_frame = CreateWindowHelper( opener_frame, *active_frame, opener_frame, frame_request, window_features, - kNavigationPolicyIgnore, created); - if (!new_frame) + kNavigationPolicyIgnore, created, &manifest); + if (!new_frame) + return nullptr; + if (!window_features.noopener) + new_frame->Client()->SetOpener(&opener_frame); + } else if (navigationPolicy == kNavigationPolicyIgnore) return nullptr; + else + new_frame = &opener_frame; if (new_frame->DomWindow()->IsInsecureScriptAccess(calling_window, completed_url)) return window_features.noopener ? nullptr : new_frame->DomWindow(); + String agent = opener_frame.Loader().userAgentOverride(); + if (!agent.IsEmpty() && new_frame->IsLocalFrame()) + ToLocalFrame(new_frame)->Loader().setUserAgentOverride(agent); + // TODO(dcheng): Special case for window.open("about:blank") to ensure it // loads synchronously into a new window. This is our historical behavior, and // it's consistent with the creation of a new iframe with src="about:blank". @@ -503,7 +522,7 @@ DOMWindow* CreateWindow(const String& url_string, void CreateWindowForRequest(const FrameLoadRequest& request, LocalFrame& opener_frame, - NavigationPolicy policy) { + NavigationPolicy policy, WebString& manifest) { DCHECK(request.GetResourceRequest().RequestorOrigin() || (opener_frame.GetDocument() && opener_frame.GetDocument()->Url().IsEmpty())); @@ -524,7 +543,7 @@ void CreateWindowForRequest(const FrameLoadRequest& request, bool created; Frame* new_frame = CreateWindowHelper(opener_frame, opener_frame, opener_frame, request, - features, policy, created); + features, policy, created, &manifest); if (!new_frame) return; if (request.GetShouldSendReferrer() == kMaybeSendReferrer) { diff --git a/third_party/blink/renderer/core/page/create_window.h b/third_party/blink/renderer/core/page/create_window.h index 36e8bb8806b68..61fb81a87b461 100644 --- a/third_party/blink/renderer/core/page/create_window.h +++ b/third_party/blink/renderer/core/page/create_window.h @@ -51,7 +51,7 @@ DOMWindow* CreateWindow(const String& url_string, void CreateWindowForRequest(const FrameLoadRequest&, LocalFrame& opener_frame, - NavigationPolicy); + NavigationPolicy, WebString& manifest); // Exposed for testing CORE_EXPORT NavigationPolicy diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc index 0e5a2d63bc30b..424f725fb8d90 100644 --- a/third_party/blink/renderer/core/page/drag_controller.cc +++ b/third_party/blink/renderer/core/page/drag_controller.cc @@ -223,7 +223,9 @@ void DragController::DragExited(DragData* drag_data, LocalFrame& local_root) { LocalFrameView* frame_view(local_root.View()); if (frame_view) { - DataTransferAccessPolicy policy = DataTransferAccessPolicy::kTypesReadable; + DataTransferAccessPolicy policy = + document_under_mouse_->GetSecurityOrigin()->hasUniversalAccess() + ? DataTransferAccessPolicy::kReadable : DataTransferAccessPolicy::kTypesReadable; DataTransfer* data_transfer = CreateDraggingDataTransfer(policy, drag_data); data_transfer->SetSourceOperation(drag_data->DraggingSourceOperationMask()); local_root.GetEventHandler().CancelDragAndDrop(CreateMouseEvent(drag_data), @@ -749,7 +751,10 @@ bool DragController::TryDHTMLDrag(DragData* drag_data, if (!local_root.View()) return false; - DataTransferAccessPolicy policy = DataTransferAccessPolicy::kTypesReadable; + DataTransferAccessPolicy policy = + document_under_mouse_->GetSecurityOrigin()->hasUniversalAccess() + ? DataTransferAccessPolicy::kReadable + : DataTransferAccessPolicy::kTypesReadable; DataTransfer* data_transfer = CreateDraggingDataTransfer(policy, drag_data); DragOperation src_op_mask = drag_data->DraggingSourceOperationMask(); data_transfer->SetSourceOperation(src_op_mask); diff --git a/third_party/blink/renderer/core/page/frame_tree.cc b/third_party/blink/renderer/core/page/frame_tree.cc index 78efae2655c71..4384d73e309f0 100644 --- a/third_party/blink/renderer/core/page/frame_tree.cc +++ b/third_party/blink/renderer/core/page/frame_tree.cc @@ -186,11 +186,19 @@ Frame* FrameTree::Find(const AtomicString& name) const { EqualIgnoringASCIICase(name, "_current") || name.IsEmpty()) return this_frame_; - if (EqualIgnoringASCIICase(name, "_top")) + if (EqualIgnoringASCIICase(name, "_top")) { + for (LocalFrame* f = ToLocalFrame(this_frame_); f; f = ToLocalFrame(f->Tree().Parent())) { + if (f->isNwFakeTop()) + return f; + } return &Top(); + } - if (EqualIgnoringASCIICase(name, "_parent")) + if (EqualIgnoringASCIICase(name, "_parent")) { + if (this_frame_->isNwFakeTop()) + return this_frame_.Get(); return Parent() ? Parent() : this_frame_.Get(); + } // Since "_blank" should never be any frame's name, the following just amounts // to an optimization. diff --git a/third_party/blink/renderer/core/probe/core_probes.h b/third_party/blink/renderer/core/probe/core_probes.h index 7107ee4c97d28..2d92def85c289 100644 --- a/third_party/blink/renderer/core/probe/core_probes.h +++ b/third_party/blink/renderer/core/probe/core_probes.h @@ -70,6 +70,26 @@ inline CoreProbeSink* ToCoreProbeSink(LocalFrame* frame) { } inline CoreProbeSink* ToCoreProbeSink(Document& document) { + LocalFrame* frame = document.GetFrame(); + if (!frame && document.TemplateDocumentHost()) + frame = document.TemplateDocumentHost()->GetFrame(); + // filter out non-jail frame instrumentations + if (frame) { + Frame* jail_frame = NULL; + if ((jail_frame = frame->getDevtoolsJail()) != NULL) { + Frame* f = document.GetFrame(); + bool in_jail_frame = false; + while (f) { + if (f == jail_frame) { + in_jail_frame = true; + break; + } + f = f->Tree().Parent(); + } + if (!in_jail_frame) + return NULL; + } + } return document.GetProbeSink(); } diff --git a/third_party/blink/renderer/core/script/modulator.h b/third_party/blink/renderer/core/script/modulator.h index 57824d39067ec..416dbe4b24b90 100644 --- a/third_party/blink/renderer/core/script/modulator.h +++ b/third_party/blink/renderer/core/script/modulator.h @@ -90,6 +90,7 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>, void TraceWrappers(ScriptWrappableVisitor*) const override {} const char* NameInHeapSnapshot() const override { return "Modulator"; } + virtual void AddToMap(const KURL& url, ModuleScript*) = 0; virtual ScriptModuleResolver* GetScriptModuleResolver() = 0; virtual base::SingleThreadTaskRunner* TaskRunner() = 0; virtual ReferrerPolicy GetReferrerPolicy() = 0; diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc index cbb276012fbfb..b4950d1f16832 100644 --- a/third_party/blink/renderer/core/script/modulator_impl_base.cc +++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc @@ -51,6 +51,11 @@ const SecurityOrigin* ModulatorImplBase::GetSecurityOriginForFetch() { // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree // [fetch-a-module-worker-script-tree] // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree + +void ModulatorImplBase::AddToMap(const KURL& url, ModuleScript* script) { + map_->AddToMap(url, script); +} + void ModulatorImplBase::FetchTree(const KURL& url, WebURLRequest::RequestContext destination, const ScriptFetchOptions& options, diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.h b/third_party/blink/renderer/core/script/modulator_impl_base.h index 382ab46cb316f..a05e2ad68897f 100644 --- a/third_party/blink/renderer/core/script/modulator_impl_base.h +++ b/third_party/blink/renderer/core/script/modulator_impl_base.h @@ -42,6 +42,7 @@ class ModulatorImplBase : public Modulator { private: // Implements Modulator + void AddToMap(const KURL& url, ModuleScript* script) override; ScriptModuleResolver* GetScriptModuleResolver() override { return script_module_resolver_.Get(); } diff --git a/third_party/blink/renderer/core/script/module_map.cc b/third_party/blink/renderer/core/script/module_map.cc index dc8e944e88821..f31b151798787 100644 --- a/third_party/blink/renderer/core/script/module_map.cc +++ b/third_party/blink/renderer/core/script/module_map.cc @@ -33,6 +33,7 @@ class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>, ModuleScript* GetModuleScript() const; private: + friend class ModuleMap; explicit Entry(ModuleMap*); void DispatchFinishedNotificationAsync(SingleModuleClient*); @@ -53,6 +54,14 @@ ModuleMap::Entry::Entry(ModuleMap* map) : map_(map) { DCHECK(map_); } +void ModuleMap::AddToMap(const KURL& url, ModuleScript* script) { + MapImpl::AddResult result = map_.insert(url, nullptr); + TraceWrapperMember<Entry>& entry = result.stored_value->value; + entry = Entry::Create(this); + entry->module_script_ = script; + entry->is_fetching_ = false; +} + void ModuleMap::Entry::Trace(blink::Visitor* visitor) { visitor->Trace(module_script_); visitor->Trace(map_); diff --git a/third_party/blink/renderer/core/script/module_map.h b/third_party/blink/renderer/core/script/module_map.h index 1f87c0712daaa..55ecb47367582 100644 --- a/third_party/blink/renderer/core/script/module_map.h +++ b/third_party/blink/renderer/core/script/module_map.h @@ -45,6 +45,7 @@ class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>, // If the URL wasn't fetched, or is currently being fetched, this returns a // nullptr. ModuleScript* GetFetchedModuleScript(const KURL&) const; + void AddToMap(const KURL&, ModuleScript*); Modulator* GetModulator() { return modulator_; } diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 7168deb5562ad..c5c99db54b0f4 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc @@ -4,6 +4,18 @@ #include "third_party/blink/renderer/core/workers/dedicated_worker.h" +#include "third_party/node-nw/src/node_webkit.h" +#define BLINK_HOOK_MAP(type, sym, fn) CORE_EXPORT type fn = nullptr; +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + +#include "base/command_line.h" + #include <memory> #include "services/network/public/mojom/fetch_api.mojom-blink.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -263,12 +275,20 @@ std::unique_ptr<GlobalScopeCreationParams> DedicatedWorker::CreateGlobalScopeCreationParams() { base::UnguessableToken devtools_worker_token; std::unique_ptr<WorkerSettings> settings; + bool isNodeJS = false; + std::string main_script; if (GetExecutionContext()->IsDocument()) { Document* document = ToDocument(GetExecutionContext()); devtools_worker_token = document->GetFrame() ? document->GetFrame()->GetDevToolsFrameToken() : base::UnguessableToken::Create(); settings = std::make_unique<WorkerSettings>(document->GetSettings()); + const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + + isNodeJS = document->GetFrame() && document->GetFrame()->isNodeJS() && command_line.HasSwitch("enable-node-worker"); + if (g_web_worker_start_thread_fn) { + (*g_web_worker_start_thread_fn)(document->GetFrame(), (void*)script_url_.GetPath().Utf8().data(), &main_script, &isNodeJS); + } } else { WorkerGlobalScope* worker_global_scope = ToWorkerGlobalScope(GetExecutionContext()); @@ -278,7 +298,7 @@ DedicatedWorker::CreateGlobalScopeCreationParams() { ScriptType script_type = (options_.type() == "classic") ? ScriptType::kClassic : ScriptType::kModule; - return std::make_unique<GlobalScopeCreationParams>( + return std::make_unique<GlobalScopeCreationParams>(isNodeJS, main_script, script_url_, script_type, GetExecutionContext()->UserAgent(), GetExecutionContext()->GetContentSecurityPolicy()->Headers().get(), kReferrerPolicyDefault, GetExecutionContext()->GetSecurityOrigin(), diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc index 4702f0330060a..93016e1b8a1db 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc @@ -89,6 +89,7 @@ void DedicatedWorkerGlobalScope::postMessage( ThreadDebugger* debugger = ThreadDebugger::From(script_state->GetIsolate()); v8_inspector::V8StackTraceId stack_id = debugger->StoreCurrentStackTrace("postMessage"); + if (GetThread()) WorkerObjectProxy().PostMessageToWorkerObject(std::move(message), std::move(channels), stack_id); } diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc index 590bf269c835e..b7cacec4c4226 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc @@ -10,6 +10,7 @@ namespace blink { GlobalScopeCreationParams::GlobalScopeCreationParams( + bool isNodeJS, const std::string& main_script, const KURL& script_url, ScriptType script_type, const String& user_agent, @@ -29,6 +30,7 @@ GlobalScopeCreationParams::GlobalScopeCreationParams( BeginFrameProviderParams begin_frame_provider_params) : script_url(script_url.Copy()), script_type(script_type), + nodejs_(isNodeJS), main_script_(main_script), user_agent(user_agent.IsolatedCopy()), referrer_policy(referrer_policy), starter_origin(starter_origin ? starter_origin->IsolatedCopy() : nullptr), diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h index 47320bd7741cc..a954c925d3f55 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h @@ -36,6 +36,7 @@ struct CORE_EXPORT GlobalScopeCreationParams final { public: GlobalScopeCreationParams( + bool isNodeJS, const std::string& main_script, const KURL& script_url, ScriptType script_type, const String& user_agent, @@ -57,6 +58,8 @@ struct CORE_EXPORT GlobalScopeCreationParams final { KURL script_url; ScriptType script_type; + bool nodejs_; + std::string main_script_; String user_agent; // |content_security_policy_parsed_headers| and diff --git a/third_party/blink/renderer/core/workers/shared_worker.cc b/third_party/blink/renderer/core/workers/shared_worker.cc index ef16e0b69a997..5c526f658ff74 100644 --- a/third_party/blink/renderer/core/workers/shared_worker.cc +++ b/third_party/blink/renderer/core/workers/shared_worker.cc @@ -31,6 +31,8 @@ #include "third_party/blink/renderer/core/workers/shared_worker.h" +#include "base/command_line.h" + #include "third_party/blink/renderer/bindings/core/v8/exception_state.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -80,9 +82,11 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context, if (script_url.IsEmpty()) return nullptr; + const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + bool isNodeJS = document->GetFrame()->isNodeJS() && command_line.HasSwitch("enable-node-worker"); if (document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()) { document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()->Connect( - worker, std::move(remote_port), script_url, name); + worker, std::move(remote_port), script_url, name, isNodeJS); } return worker; diff --git a/third_party/blink/renderer/core/workers/shared_worker_repository_client.h b/third_party/blink/renderer/core/workers/shared_worker_repository_client.h index 9219d270215dd..04b5869821eba 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_repository_client.h +++ b/third_party/blink/renderer/core/workers/shared_worker_repository_client.h @@ -53,7 +53,7 @@ class CORE_EXPORT SharedWorkerRepositoryClient { virtual void Connect(SharedWorker*, MessagePortChannel, const KURL&, - const String& name) = 0; + const String& name, bool) = 0; virtual void DocumentDetached(Document*) = 0; diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc index eb3614cd0f04d..3da468d08e614 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc @@ -45,6 +45,7 @@ void ThreadedWorkletMessagingProxy::Initialize( auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( + false, std::string(), document->Url(), ScriptType::kModule, document->UserAgent(), csp->Headers().get(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), document->IsSecureContext(), diff --git a/third_party/blink/renderer/core/workers/worker_backing_thread.cc b/third_party/blink/renderer/core/workers/worker_backing_thread.cc index 08706a54fa532..24a98bd40e97d 100644 --- a/third_party/blink/renderer/core/workers/worker_backing_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_backing_thread.cc @@ -7,6 +7,17 @@ #include <memory> #include "base/location.h" +#include "third_party/node-nw/src/node_webkit.h" +#define BLINK_HOOK_MAP(type, sym, fn) extern type fn; +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + + #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/web/blink.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" @@ -22,6 +33,9 @@ #include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" namespace blink { +void set_web_worker_hooks(void* fn_start) { + g_web_worker_start_thread_fn = (VoidPtr4Fn)fn_start; +} // Wrapper functions defined in WebKit.h void MemoryPressureNotificationToWorkerThreadIsolates( diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index 8773b861fc28c..33d8d6a854653 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc @@ -130,6 +130,27 @@ String WorkerGlobalScope::origin() const { return GetSecurityOrigin()->ToString(); } +ScriptValue WorkerGlobalScope::importNWBin(ScriptState* state, DOMArrayBuffer* buffer) { + v8::Isolate* isolate = state->GetIsolate(); + v8::HandleScope handle_scope(isolate); + uint8_t *data = static_cast<uint8_t*>(buffer->Data()); + int64_t length = buffer->ByteLength(); + v8::Handle<v8::String> source_string = v8::String::NewFromUtf8(isolate, ""); + v8::ScriptCompiler::CachedData* cache; + cache = new v8::ScriptCompiler::CachedData( + data, length, v8::ScriptCompiler::CachedData::BufferNotOwned); + v8::ScriptCompiler::Source source(source_string, cache); + v8::Local<v8::UnboundScript> script; + script = v8::ScriptCompiler::CompileUnboundScript( + isolate, &source, v8::ScriptCompiler::kConsumeCodeCache).ToLocalChecked(); + CHECK(!cache->rejected); + v8::Local<v8::Value> result; + v8::Context::Scope cscope (state->GetContext()); + v8::FixSourceNWBin(isolate, script); + ignore_result(script->BindToCurrentContext()->Run(state->GetContext()).ToLocal(&result)); + return ScriptValue::From(state, result); +} + // Implementation of the "importScripts()" algorithm: // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-importscripts void WorkerGlobalScope::importScripts(const Vector<String>& urls, diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index 4ad5fdc534c1f..e032659338b77 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h @@ -54,6 +54,7 @@ class InterfaceProvider; namespace blink { class FontFaceSet; +class DOMArrayBuffer; class ConsoleMessage; class ExceptionState; class OffscreenFontSelector; @@ -103,6 +104,7 @@ class CORE_EXPORT WorkerGlobalScope DEFINE_ATTRIBUTE_EVENT_LISTENER(unhandledrejection); // WorkerUtils + ScriptValue importNWBin(ScriptState* state, DOMArrayBuffer* buffer); virtual void importScripts(const Vector<String>& urls, ExceptionState&); // ExecutionContext diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.idl b/third_party/blink/renderer/core/workers/worker_global_scope.idl index b36e8c297a54a..dcad1fa1467d0 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.idl +++ b/third_party/blink/renderer/core/workers/worker_global_scope.idl @@ -42,6 +42,7 @@ // https://html.spec.whatwg.org/#apis-available-to-workers [RaisesException] void importScripts(DOMString... urls); + [CallWith=ScriptState] any importNWBin(ArrayBuffer buffer); readonly attribute WorkerNavigator navigator; diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index 7cf818b56c133..8043e24453737 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc @@ -61,6 +61,17 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/threading.h" + +#include "third_party/node-nw/src/node_webkit.h" + +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + namespace blink { using ExitCode = WorkerThread::ExitCode; @@ -427,6 +438,9 @@ void WorkerThread::InitializeOnWorkerThread( const base::Optional<WorkerBackingThreadStartupData>& thread_startup_data, WorkerInspectorProxy::PauseOnWorkerStart pause_on_start) { DCHECK(IsCurrentThread()); + + bool isNodeJS = global_scope_creation_params->nodejs_; + std::string main_script = global_scope_creation_params->main_script_; { MutexLocker lock(mutex_); DCHECK_EQ(ThreadState::kNotStarted, thread_state_); @@ -459,7 +473,7 @@ void WorkerThread::InitializeOnWorkerThread( worker_reporting_proxy_.DidInitializeWorkerContext(); v8::HandleScope handle_scope(GetIsolate()); Platform::Current()->WorkerContextCreated( - GlobalScope()->ScriptController()->GetContext()); + GlobalScope()->ScriptController()->GetContext(), isNodeJS, main_script); } inspector_task_runner_->InitIsolate(GetIsolate()); @@ -517,7 +531,9 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() { SetExitCode(ExitCode::kGracefullyTerminated); } + ::g_stop_nw_instance_fn(); inspector_task_runner_->Dispose(); + GetWorkerReportingProxy().WillDestroyWorkerGlobalScope(); probe::AllAsyncTasksCanceled(GlobalScope()); diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index d9f6ad5f8131f..1985cd5622c2d 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc @@ -697,11 +697,13 @@ void XMLHttpRequest::open(const AtomicString& method, // exception thrown. // Refer : https://xhr.spec.whatwg.org/#sync-warning // Use count for XHR synchronous requests on main thread only. +#if 0 if (!GetDocument()->ProcessingBeforeUnload()) { Deprecation::CountDeprecation( GetExecutionContext(), WebFeature::kXMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload); } +#endif } method_ = FetchUtils::NormalizeMethod(method); diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn index bd71028a610e7..ae9b331fcc507 100644 --- a/third_party/blink/renderer/devtools/BUILD.gn +++ b/third_party/blink/renderer/devtools/BUILD.gn @@ -1017,6 +1017,7 @@ generated_applications = [ ] generated_non_autostart_non_remote_modules = [ + "$resources_out_dir/product_registry_impl/product_registry_impl_module.js", "$resources_out_dir/animation/animation_module.js", "$resources_out_dir/audits2/audits2_module.js", "$resources_out_dir/browser_console/browser_console_module.js", @@ -1067,7 +1068,6 @@ generated_remote_modules = [ "$resources_out_dir/audits2_worker/audits2_worker_module.js", "$resources_out_dir/cm_modes/cm_modes_module.js", "$resources_out_dir/emulated_devices/emulated_devices_module.js", - "$resources_out_dir/product_registry_impl/product_registry_impl_module.js", ] devtools_applications = [ diff --git a/third_party/blink/renderer/devtools/front_end/devtools_app.json b/third_party/blink/renderer/devtools/front_end/devtools_app.json index e444158564716..fbd428e0f39f8 100644 --- a/third_party/blink/renderer/devtools/front_end/devtools_app.json +++ b/third_party/blink/renderer/devtools/front_end/devtools_app.json @@ -20,7 +20,7 @@ { "name": "layer_viewer" }, { "name": "network" }, { "name": "performance_monitor" }, - { "name": "product_registry_impl", "type": "remote" }, + { "name": "product_registry_impl" }, { "name": "resources" }, { "name": "security" }, { "name": "timeline" }, diff --git a/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js b/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js index baa287994cdb0..1280e10c68b3d 100644 --- a/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js +++ b/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js @@ -801,7 +801,16 @@ Node.prototype.getComponentRoot = function() { */ function isEnterKey(event) { // Check if in IME. - return event.keyCode !== 229 && event.key === 'Enter'; + // FIXME: Due to recent change in Chromium, `key` property is used to replace + // the deprecated property `keyIdentifier`. However chromedriver doesn't + // send `key` property with key event. This caused `event.key === 'Enter'` + // failed in DevTools frontend, which prevents executing statements in + // DevTools console. + // This workaround used the `keyCode` to test if it's `Enter` key as an + // alternation to testing `key` property. It should be replaced with + // upstream fix later. + // See https://bugs.chromium.org/p/chromedriver/issues/detail?id=1411#c4 + return event.keyCode !== 229 && (event.key === "Enter" || event.keyCode === 13); } /** diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index fc94fd623368a..1e889951fc04f 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc @@ -609,6 +609,8 @@ void CanvasRenderingContext2D::ResourceElementChanged() { } bool CanvasRenderingContext2D::OriginClean() const { + if (canvas()->GetDocument().GetFrame() && canvas()->GetDocument().GetFrame()->isNodeJS()) + return true; return Host()->OriginClean(); } diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc index 1dc425b108a1e..b2baec7922163 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc @@ -32,7 +32,7 @@ PaintWorkletGlobalScopeProxy::PaintWorkletGlobalScopeProxy( reporting_proxy_ = std::make_unique<MainThreadWorkletReportingProxy>(document); - auto creation_params = std::make_unique<GlobalScopeCreationParams>( + auto creation_params = std::make_unique<GlobalScopeCreationParams>(false, std::string(), document->Url(), ScriptType::kModule, document->UserAgent(), document->GetContentSecurityPolicy()->Headers().get(), document->GetReferrerPolicy(), document->GetSecurityOrigin(), diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index 7ac61fd965878..ed3b37244a55b 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc @@ -31,6 +31,19 @@ #include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h" #include <memory> +#include "third_party/node-nw/src/node_webkit.h" +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#define BLINK_HOOK_MAP(type, sym, fn) CORE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#define BLINK_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + +#include "base/command_line.h" + #include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h" #include "third_party/blink/public/platform/task_type.h" @@ -321,6 +334,8 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() { DCHECK(!asked_to_terminate_); Document* document = shadow_page_->GetDocument(); + const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + bool isNodeJS = document->GetFrame() && document->GetFrame()->isNodeJS() && command_line.HasSwitch("enable-node-worker"); // FIXME: this document's origin is pristine and without any extra privileges. // (crbug.com/254993) @@ -350,6 +365,11 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() { std::unique_ptr<WorkerSettings> worker_settings = std::make_unique<WorkerSettings>(document->GetSettings()); + std::string main_script; + KURL script_url = worker_start_data_.script_url; + if (g_web_worker_start_thread_fn) { + (*g_web_worker_start_thread_fn)(shadow_page_->GetDocument()->GetFrame(), (void*)script_url.GetPath().Utf8().data(), &main_script, &isNodeJS); + } std::unique_ptr<GlobalScopeCreationParams> global_scope_creation_params; String source_code; std::unique_ptr<Vector<char>> cached_meta_data; @@ -367,6 +387,7 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() { main_script_loader_->ReleaseContentSecurityPolicy(), main_script_loader_->GetReferrerPolicy()); global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( + isNodeJS, main_script, worker_start_data_.script_url, script_type, worker_start_data_.user_agent, document->GetContentSecurityPolicy()->Headers().get(), @@ -385,6 +406,7 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() { // SetContentSecurityPolicyAndReferrerPolicy() before evaluating the main // script. global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>( + isNodeJS, main_script, worker_start_data_.script_url, script_type, worker_start_data_.user_agent, nullptr /* ContentSecurityPolicy */, kReferrerPolicyDefault, starter_origin, starter_secure_context, diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc index 9463657494fa3..6a75eeeab3651 100644 --- a/third_party/blink/renderer/platform/bindings/script_state.cc +++ b/third_party/blink/renderer/platform/bindings/script_state.cc @@ -40,6 +40,8 @@ ScriptState::ScriptState(v8::Local<v8::Context> context, DCHECK(world_); context_.SetWeak(this, &ContextCollectedCallback); context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this); + context->SetAlignedPointerInEmbedderData(33, nullptr); + context->SetAlignedPointerInEmbedderData(32, nullptr); } ScriptState::~ScriptState() { diff --git a/third_party/blink/renderer/platform/bindings/script_state.h b/third_party/blink/renderer/platform/bindings/script_state.h index 87187ff429687..8d1096ed8369d 100644 --- a/third_party/blink/renderer/platform/bindings/script_state.h +++ b/third_party/blink/renderer/platform/bindings/script_state.h @@ -124,7 +124,7 @@ class PLATFORM_EXPORT ScriptState : public RefCounted<ScriptState> { // ScriptState::from() must not be called for a context that does not have // valid embedder data in the embedder field. SECURITY_CHECK(script_state); - SECURITY_CHECK(script_state->context_ == context); + SECURITY_CHECK(script_state->context_ == context || context->GetAlignedPointerFromEmbedderData(36) == (void*)0x08110800); return script_state; } diff --git a/third_party/blink/renderer/platform/exported/web_security_origin.cc b/third_party/blink/renderer/platform/exported/web_security_origin.cc index 003b6a1e75444..92e4047c6ab41 100644 --- a/third_party/blink/renderer/platform/exported/web_security_origin.cc +++ b/third_party/blink/renderer/platform/exported/web_security_origin.cc @@ -139,4 +139,9 @@ bool WebSecurityOrigin::operator==(const WebSecurityOrigin& other) const { } #endif -} // namespace blink +void WebSecurityOrigin::grantUniversalAccess() +{ + const_cast<SecurityOrigin*>(private_.Get())->GrantUniversalAccess(); +} + +} // namespace blink diff --git a/third_party/blink/renderer/platform/lifecycle_observer.h b/third_party/blink/renderer/platform/lifecycle_observer.h index 785bab5cfa345..3212691eb9c6b 100644 --- a/third_party/blink/renderer/platform/lifecycle_observer.h +++ b/third_party/blink/renderer/platform/lifecycle_observer.h @@ -50,6 +50,7 @@ class LifecycleObserver : public GarbageCollectedMixin { SetContext(context); } + public: void SetContext(Context*); private: diff --git a/third_party/blink/renderer/platform/memory_coordinator.cc b/third_party/blink/renderer/platform/memory_coordinator.cc index 33ebadea200b0..3ccd1df305ffe 100644 --- a/third_party/blink/renderer/platform/memory_coordinator.cc +++ b/third_party/blink/renderer/platform/memory_coordinator.cc @@ -16,12 +16,28 @@ #include "third_party/blink/renderer/platform/web_task_runner.h" #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" +#include "third_party/blink/renderer/modules/gamepad/navigator_gamepad.h" +#include "third_party/blink/public/web/web_frame.h" +#include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/public/web/web_local_frame.h" + #if defined(OS_ANDROID) #include "base/android/sys_utils.h" #endif namespace blink { +void fix_gamepad_nw(WebLocalFrame* frame) +{ +#if 0 + Document* doc = frame->GetDocument(); + NavigatorGamepad* gamepad = NavigatorGamepad::From(*doc); + ((ContextLifecycleObserver*)gamepad)->SetContext(static_cast<ExecutionContext*>(doc)); + gamepad->Gamepads(); +#endif +} + // Wrapper function defined in WebKit.h void DecommitFreeableMemory() { WTF::Partitions::DecommitFreeableMemory(); diff --git a/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc index 55583882fcdab..199dd72279f51 100644 --- a/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc @@ -16,6 +16,16 @@ #include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" +#include "third_party/node-nw/src/node_webkit.h" +#define PLATFORM_HOOK_MAP(type, sym, fn) PLATFORM_EXPORT type fn = nullptr; +#if defined(COMPONENT_BUILD) && defined(WIN32) +#define NW_HOOK_MAP(type, sym, fn) BASE_EXPORT type fn; +#else +#define NW_HOOK_MAP(type, sym, fn) extern type fn; +#endif +#include "content/nw/src/common/node_hooks.h" +#undef NW_HOOK_MAP + namespace blink { namespace scheduler { @@ -27,6 +37,8 @@ WebThreadImplForWorkerScheduler::WebThreadImplForWorkerScheduler( params.frame_scheduler ? std::make_unique<WorkerSchedulerProxy>(params.frame_scheduler) : nullptr) { + if (g_web_worker_thread_new_fn) + (*g_web_worker_thread_new_fn)((void*)params.name, (void*)¶ms.thread_options); bool started = thread_->StartWithOptions(params.thread_options); CHECK(started); thread_task_runner_ = thread_->task_runner(); diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.h b/third_party/blink/renderer/platform/weborigin/security_origin.h index e54f3f67f5031..4e22866b7ef90 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin.h +++ b/third_party/blink/renderer/platform/weborigin/security_origin.h @@ -99,6 +99,7 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> { String Protocol() const { return protocol_; } String Host() const { return host_; } String Domain() const { return domain_; } + bool hasUniversalAccess() const { return universal_access_; } // Returns 0 if the effective port of this origin is the default for its // scheme. diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index c2abc5d4b6727..64d4956c2b79c 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn @@ -12,6 +12,7 @@ visibility = [ ":*", "//mojo/public/cpp/bindings/*", "//third_party/blink/*", + "//content/nw/*", ] config("wtf_config") { diff --git a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h index 809229caa8727..2d3025c5f5b25 100644 --- a/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h +++ b/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h @@ -52,7 +52,7 @@ class WTF_EXPORT ArrayBufferContents { // specifies the correct deleter. using DataDeleter = void (*)(void* data); - enum class AllocationKind { kNormal, kReservation }; + enum class AllocationKind { kNormal, kReservation, kNodeJS }; class DataHandle { DISALLOW_COPY_AND_ASSIGN(DataHandle); @@ -101,6 +101,9 @@ class WTF_EXPORT ArrayBufferContents { case AllocationKind::kReservation: base::FreePages(allocation_base_, allocation_length_); return; + case AllocationKind::kNodeJS: + free(allocation_base_); + return; } } diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc index 715c533a27565..0cca1dae5048f 100644 --- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc +++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc @@ -14,6 +14,7 @@ #include "handler/crash_report_upload_thread.h" +#include "base/strings/stringprintf.h" #include <errno.h> #include <time.h> @@ -170,7 +171,7 @@ void CrashReportUploadThread::ProcessPendingReport( // If the most recent upload attempt occurred within the past hour, // don’t attempt to upload the new report. If it happened longer ago, // attempt to upload the report. - constexpr int kUploadAttemptIntervalSeconds = 60 * 60; // 1 hour + constexpr int kUploadAttemptIntervalSeconds = 0; //60 * 60; // 1 hour if (now - last_upload_attempt_time < kUploadAttemptIntervalSeconds) { database_->SkipReportUpload( report.uuid, Metrics::CrashSkippedReason::kUploadThrottled); @@ -270,6 +271,9 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( return UploadResult::kPermanentFailure; } + std::string upload_url; + if (parameters.find("url-nwjs") != parameters.end()) + upload_url = parameters["url-nwjs"]; HTTPMultipartBuilder http_multipart_builder; http_multipart_builder.SetGzipEnabled(options_.upload_gzip); @@ -299,7 +303,8 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( // TODO(mark): The timeout should be configurable by the client. http_transport->SetTimeout(60.0); // 1 minute. - std::string url = url_; +#if 0 + std::string url = upload_url; if (options_.identify_client_via_url) { // Add parameters to the URL which identify the client to the server. static constexpr struct { @@ -322,7 +327,10 @@ CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( } } } - http_transport->SetURL(url); + if (!url.empty()) + upload_url = url; +#endif + http_transport->SetURL(upload_url); if (!http_transport->ExecuteSynchronously(response_body)) { return UploadResult::kRetry; diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc index 70192cf4dd47b..6ea6b909f1166 100644 --- a/third_party/crashpad/crashpad/handler/handler_main.cc +++ b/third_party/crashpad/crashpad/handler/handler_main.cc @@ -816,7 +816,7 @@ int HandlerMain(int argc, } ScopedStoppable upload_thread; - if (!options.url.empty()) { + if (true) { // TODO(scottmg): options.rate_limit should be removed when we have a // configurable database setting to control upload limiting. // See https://crashpad.chromium.org/bug/23. diff --git a/third_party/node/node.py b/third_party/node/node.py index 8097e2c49acfb..2be8ea8154c53 100755 --- a/third_party/node/node.py +++ b/third_party/node/node.py @@ -7,7 +7,11 @@ import platform import subprocess import sys +import atexit +import os +import signal +is_win = (platform.system() == 'Windows') def GetBinaryPath(): return os_path.join(os_path.dirname(__file__), *{ @@ -16,11 +20,30 @@ def GetBinaryPath(): 'Windows': ('win', 'node.exe'), }[platform.system()]) - def RunNode(cmd_parts, stdout=None): cmd = " ".join([GetBinaryPath()] + cmd_parts) - process = subprocess.Popen( + process = None + if is_win: + process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + else: + process = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid) + pgid = None + if not is_win: + pgid = os.getpgid(process.pid) + @atexit.register + def kill_process(*args): + try: + if is_win: + os.popen('taskkill /T /F /PID %d' % process.pid) + else: + os.kill(process.pid, signal.SIGTERM) + os.killpg(pgid, signal.SIGTERM) + process.wait() + except OSError: + pass + signal.signal(signal.SIGTERM, kill_process) stdout, stderr = process.communicate() if stderr: diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni index 6a6a19ff0245c..cf2a8d10f8e1f 100644 --- a/tools/grit/grit_rule.gni +++ b/tools/grit/grit_rule.gni @@ -133,6 +133,13 @@ if (is_chrome_branded) { ] } +if (nwjs_sdk) { + grit_defines += [ + "-D", + "nwjs_sdk", + ] +} + if (is_chromeos) { grit_defines += [ "-D", diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index fc16a42e623e9..7273520060182 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids @@ -30,6 +30,11 @@ # # chrome/ and ios/chrome/ must start at the same id. # App only use one file depending on whether it is iOS or other platform. + "chrome/browser/browser_resources.grd": { + "includes": [400], + "structures": [850], + }, + # Chromium strings and Google Chrome strings must start at the same id. # We only use one file depending on whether we're building Chromium or # Google Chrome. @@ -414,4 +419,8 @@ # Please read the header and find the right section above instead. # Resource ids starting at 31000 are reserved for projects built on Chromium. + "chrome/browser/nwjs_resources.grd": { + "includes": [32000], + "structures": [32450], + }, } diff --git a/tools/licenses.py b/tools/licenses.py index 3862aa0a9f647..e7f46e60f9aee 100755 --- a/tools/licenses.py +++ b/tools/licenses.py @@ -111,6 +111,7 @@ ADDITIONAL_PATHS_FILENAME = 'additional_readme_paths.json' ADDITIONAL_PATHS = ( + os.path.join('content', 'nw'), os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'), os.path.join('chrome', 'test', 'chromeos', 'autotest'), os.path.join('chrome', 'test', 'data'), @@ -132,6 +133,16 @@ # can't provide a README.chromium. Please prefer a README.chromium # wherever possible. SPECIAL_CASES = { + os.path.join('content', 'nw'): { + "Name": "NW.js", + "URL": "http://nwjs.io", + "License": "MIT", + }, + os.path.join('third_party', 'node'): { + "Name": "IO.js", + "URL": "https://iojs.org", + "License": "MIT", + }, os.path.join('native_client'): { "Name": "native client", "URL": "http://code.google.com/p/nativeclient", diff --git a/tools/v8_context_snapshot/BUILD.gn b/tools/v8_context_snapshot/BUILD.gn index b9254d95d9555..0e6f6b0c0b530 100644 --- a/tools/v8_context_snapshot/BUILD.gn +++ b/tools/v8_context_snapshot/BUILD.gn @@ -57,7 +57,7 @@ if (use_v8_context_snapshot) { } action("generate_v8_context_snapshot") { - script = "//build/gn_run_binary.py" + script = "run.py" output_file = "$root_out_dir/v8_context_snapshot.bin" output_path = rebase_path(output_file, root_build_dir) @@ -106,6 +106,9 @@ if (use_v8_context_snapshot) { "//v8", ] + if (is_linux && !is_component_build) { + configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } if (is_linux && (is_component_build || using_sanitizer) && use_custom_libcxx) { deps += [ "//buildtools/third_party/libc++:libc++" ] diff --git a/tools/v8_context_snapshot/run.py b/tools/v8_context_snapshot/run.py new file mode 100644 index 0000000000000..ad9b4fd5e9753 --- /dev/null +++ b/tools/v8_context_snapshot/run.py @@ -0,0 +1,19 @@ +# Copyright 2017 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 program wraps an arbitrary command since gn currently can only execute +scripts.""" + +import os +import subprocess +import sys +from shutil import copy2 + +args = sys.argv[1:] +args[0] = os.path.abspath(args[0]) + +if sys.platform == 'darwin': + copy2(os.path.join(os.path.dirname(args[0]), 'libffmpeg.dylib'), os.path.dirname(os.path.dirname(args[0]))) + +sys.exit(subprocess.call(args)) diff --git a/ui/accelerated_widget_mac/BUILD.gn b/ui/accelerated_widget_mac/BUILD.gn index 83736977b60d3..bbe2bdb7a90ef 100644 --- a/ui/accelerated_widget_mac/BUILD.gn +++ b/ui/accelerated_widget_mac/BUILD.gn @@ -32,6 +32,7 @@ component("accelerated_widget_mac") { "//base", "//skia", "//ui/base", + "//ui/display", "//ui/events", "//ui/events:events_base", "//ui/gfx", diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc index eab53e188d392..048454349ea70 100644 --- a/ui/accessibility/platform/atk_util_auralinux.cc +++ b/ui/accessibility/platform/atk_util_auralinux.cc @@ -110,6 +110,7 @@ bool AtkUtilAuraLinux::ShouldEnableAccessibility() { } void AtkUtilAuraLinux::InitializeAsync() { +#if 0 static bool initialized = false; if (initialized || !ShouldEnableAccessibility()) @@ -121,6 +122,7 @@ void AtkUtilAuraLinux::InitializeAsync() { g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE)); PlatformInitializeAsync(); +#endif } void AtkUtilAuraLinux::InitializeForTesting() { diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc index a6756c20f22c6..5c21ed735f442 100644 --- a/ui/base/accelerators/accelerator.cc +++ b/ui/base/accelerators/accelerator.cc @@ -6,6 +6,7 @@ #include <stdint.h> #include <tuple> +#include "base/strings/stringprintf.h" #include "base/i18n/rtl.h" #include "base/logging.h" @@ -145,7 +146,9 @@ base::string16 Accelerator::GetShortcutText() const { shortcut = KeyCodeToName(key_code_); #endif - if (shortcut.empty()) { + if (shortcut.empty() && key_code_ >= VKEY_F1 && key_code_ <= VKEY_F12) + shortcut = base::UTF8ToUTF16(base::StringPrintf("F%d", key_code_ - VKEY_F1 + 1)); + else if (shortcut.empty()) { #if defined(OS_WIN) // Our fallback is to try translate the key code to a regular character // unless it is one of digits (VK_0 to VK_9). Some keyboard @@ -229,7 +232,8 @@ base::string16 Accelerator::ApplyLongFormModifiers( // more information. if (IsCtrlDown()) shortcut = l10n_util::GetStringFUTF16(IDS_APP_CONTROL_MODIFIER, shortcut); - else if (IsAltDown()) + + if (IsAltDown()) shortcut = l10n_util::GetStringFUTF16(IDS_APP_ALT_MODIFIER, shortcut); if (IsCmdDown()) { @@ -237,6 +241,10 @@ base::string16 Accelerator::ApplyLongFormModifiers( shortcut = l10n_util::GetStringFUTF16(IDS_APP_COMMAND_MODIFIER, shortcut); #elif defined(OS_CHROMEOS) shortcut = l10n_util::GetStringFUTF16(IDS_APP_SEARCH_MODIFIER, shortcut); +#elif defined(OS_WIN) + shortcut = l10n_util::GetStringFUTF16(IDS_APP_WINDOWS_MODIFIER, shortcut); +#elif defined(OS_LINUX) + shortcut = l10n_util::GetStringFUTF16(IDS_APP_SUPER_MODIFIER, shortcut); #else NOTREACHED(); #endif diff --git a/ui/base/base_window.cc b/ui/base/base_window.cc index 231a1771797ef..40e00cb7cdb69 100644 --- a/ui/base/base_window.cc +++ b/ui/base/base_window.cc @@ -12,5 +12,9 @@ bool BaseWindow::IsRestored(const BaseWindow& window) { !window.IsFullscreen(); } +void BaseWindow::ForceClose() { + Close(); +} + } // namespace ui diff --git a/ui/base/base_window.h b/ui/base/base_window.h index 8d4dd05dfaeaf..433975642d4e6 100644 --- a/ui/base/base_window.h +++ b/ui/base/base_window.h @@ -76,6 +76,7 @@ class UI_BASE_EXPORT BaseWindow { // Closes the window as soon as possible. The close action may be delayed // if an operation is in progress (e.g. a drag operation). virtual void Close() = 0; + virtual void ForceClose(); // Activates (brings to front) the window. Restores the window from minimized // state if necessary. diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h index 94236adca284c..4de152480804b 100644 --- a/ui/base/clipboard/clipboard.h +++ b/ui/base/clipboard/clipboard.h @@ -244,7 +244,7 @@ class UI_BASE_EXPORT Clipboard : public base::ThreadChecker { static const FormatType& GetIDListFormatType(); #endif - protected: + public: static Clipboard* Create(); Clipboard() {} diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc index 1b8eefc3cdd67..98469d6135135 100644 --- a/ui/base/models/simple_menu_model.cc +++ b/ui/base/models/simple_menu_model.cc @@ -55,6 +55,10 @@ void SimpleMenuModel::Delegate::CommandIdHighlighted(int command_id) { void SimpleMenuModel::Delegate::MenuWillShow(SimpleMenuModel* /*source*/) { } +bool SimpleMenuModel::Delegate::HasIcon(int command_id) { + return false; +} + void SimpleMenuModel::Delegate::MenuClosed(SimpleMenuModel* /*source*/) { } @@ -286,7 +290,7 @@ int SimpleMenuModel::GetIndexOfCommandId(int command_id) const { bool SimpleMenuModel::HasIcons() const { for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) { - if (!i->icon.IsEmpty()) + if (delegate_->HasIcon(i->command_id)) return true; } diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h index feb3d66bdaaa5..f5cb8c28f4c42 100644 --- a/ui/base/models/simple_menu_model.h +++ b/ui/base/models/simple_menu_model.h @@ -65,6 +65,8 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { bool GetAcceleratorForCommandId( int command_id, ui::Accelerator* accelerator) const override; + + virtual bool HasIcon(int command_id); }; // The Delegate can be NULL, though if it is items can't be checked or diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc index 2a00d4e851abf..a8a9d8eee18cd 100644 --- a/ui/base/resource/resource_bundle.cc +++ b/ui/base/resource/resource_bundle.cc @@ -4,6 +4,8 @@ #include "ui/base/resource/resource_bundle.h" +#include "base/strings/string_util.h" + #include <stdint.h> #include <limits> @@ -73,6 +75,8 @@ const char kPakFileExtension[] = ".pak"; ResourceBundle* g_shared_instance_ = NULL; +base::string16 chromium_name, nwjs_name; + base::FilePath GetResourcesPakFilePath(const std::string& pak_name) { base::FilePath path; if (base::PathService::Get(base::DIR_MODULE, &path)) @@ -558,8 +562,10 @@ base::StringPiece ResourceBundle::GetRawDataResourceForScale( base::string16 ResourceBundle::GetLocalizedString(int message_id) { base::string16 string; - if (delegate_ && delegate_->GetLocalizedString(message_id, &string)) + if (delegate_ && delegate_->GetLocalizedString(message_id, &string)) { + base::ReplaceSubstringsAfterOffset(&string, 0, chromium_name, nwjs_name); return MaybeMangleLocalizedString(string); + } // Ensure that ReloadLocaleResources() doesn't drop the resources while // we're using them. @@ -611,6 +617,7 @@ base::string16 ResourceBundle::GetLocalizedString(int message_id) { } else if (encoding == ResourceHandle::UTF8) { msg = base::UTF8ToUTF16(data); } + base::ReplaceSubstringsAfterOffset(&msg, 0, chromium_name, nwjs_name); return MaybeMangleLocalizedString(msg); } @@ -750,6 +757,8 @@ ResourceBundle::~ResourceBundle() { void ResourceBundle::InitSharedInstance(Delegate* delegate) { DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; g_shared_instance_ = new ResourceBundle(delegate); + chromium_name = base::ASCIIToUTF16("Chromium"); + nwjs_name = base::ASCIIToUTF16("NW.js"); static std::vector<ScaleFactor> supported_scale_factors; #if defined(OS_IOS) display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); @@ -783,12 +792,12 @@ void ResourceBundle::LoadChromeResources() { // scale factor to gfx::ImageSkia::AddRepresentation. if (IsScaleFactorSupported(SCALE_FACTOR_100P)) { AddDataPackFromPath(GetResourcesPakFilePath( - "chrome_100_percent.pak"), SCALE_FACTOR_100P); + "nw_100_percent.pak"), SCALE_FACTOR_100P); } if (IsScaleFactorSupported(SCALE_FACTOR_200P)) { AddOptionalDataPackFromPath(GetResourcesPakFilePath( - "chrome_200_percent.pak"), SCALE_FACTOR_200P); + "nw_200_percent.pak"), SCALE_FACTOR_200P); } } diff --git a/ui/base/resource/resource_bundle_mac.mm b/ui/base/resource/resource_bundle_mac.mm index 3cf1847860a56..fe5e6304df3f9 100644 --- a/ui/base/resource/resource_bundle_mac.mm +++ b/ui/base/resource/resource_bundle_mac.mm @@ -48,13 +48,13 @@ } // namespace void ResourceBundle::LoadCommonResources() { - AddDataPackFromPath(GetResourcesPakFilePath(@"chrome_100_percent", + AddDataPackFromPath(GetResourcesPakFilePath(@"nw_100_percent", nil), SCALE_FACTOR_100P); // On Mac we load 1x and 2x resources and we let the UI framework decide // which one to use. if (IsScaleFactorSupported(SCALE_FACTOR_200P)) { - AddDataPackFromPath(GetResourcesPakFilePath(@"chrome_200_percent", nil), + AddDataPackFromPath(GetResourcesPakFilePath(@"nw_200_percent", nil), SCALE_FACTOR_200P); } } diff --git a/ui/display/display.cc b/ui/display/display.cc index 99e92418353ef..ae98fade3d11f 100644 --- a/ui/display/display.cc +++ b/ui/display/display.cc @@ -18,6 +18,16 @@ #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/icc_profile.h" +namespace content { + +// Switch to enable / disable code for window's transparency +DISPLAY_EXPORT bool g_support_transparency = true; + +// Switch to force cpu drawing, is used to enable click through on alpha pixels +extern bool g_force_cpu_draw; +bool g_force_cpu_draw = false; +} + namespace display { namespace { diff --git a/ui/display/display.h b/ui/display/display.h index 42d3d8397c786..be6f11739bfe1 100644 --- a/ui/display/display.h +++ b/ui/display/display.h @@ -14,6 +14,11 @@ #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect.h" +namespace content { + DISPLAY_EXPORT extern bool g_support_transparency; + DISPLAY_EXPORT extern bool g_force_cpu_draw; +} + namespace display { namespace mojom { diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 834e5df31b4c7..f23a2c57d6588 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn @@ -365,6 +365,7 @@ jumbo_component("gfx") { if (is_mac) { libs = [ + "ApplicationServices.framework", "AppKit.framework", "CoreFoundation.framework", "CoreGraphics.framework", diff --git a/ui/gfx/icon_util.cc b/ui/gfx/icon_util.cc index eb0bcdb23dc09..dc3739ff63eb6 100644 --- a/ui/gfx/icon_util.cc +++ b/ui/gfx/icon_util.cc @@ -232,6 +232,21 @@ base::win::ScopedHICON IconUtil::CreateHICONFromSkBitmap( return icon; } +// NW fix: copied and modified from chrome/browser/ui/views/frame/glass_browser_frame_view.cc +// Converts the |image| to a Windows icon and returns the corresponding HICON +// handle. |image| is resized to desired |width| and |height| if needed. +base::win::ScopedHICON IconUtil::CreateHICONFromSkBitmapSizedTo( + const SkBitmap& bitmap, + int width, + int height) { + return CreateHICONFromSkBitmap( + width == bitmap.width() && height == bitmap.height() + ? bitmap + : skia::ImageOperations::Resize(bitmap, + skia::ImageOperations::RESIZE_BEST, + width, height)); +} + SkBitmap* IconUtil::CreateSkBitmapFromHICON(HICON icon, const gfx::Size& s) { // We start with validating parameters. if (!icon || s.IsEmpty()) diff --git a/ui/gfx/icon_util.h b/ui/gfx/icon_util.h index e542caec0e1db..27191b454913d 100644 --- a/ui/gfx/icon_util.h +++ b/ui/gfx/icon_util.h @@ -88,6 +88,10 @@ class GFX_EXPORT IconUtil { // needed by calling ::DestroyIcon(). static base::win::ScopedHICON CreateHICONFromSkBitmap(const SkBitmap& bitmap); + static base::win::ScopedHICON CreateHICONFromSkBitmapSizedTo(const SkBitmap& bitmap, + int width, + int height); + // Given a valid HICON handle representing an icon, this function converts // the icon into an SkBitmap object containing an ARGB bitmap using the // dimensions specified in |s|. |s| must specify valid dimensions (both diff --git a/ui/gfx/mac/nswindow_frame_controls.h b/ui/gfx/mac/nswindow_frame_controls.h index 61c6331ecfa51..c9d583e3721bc 100644 --- a/ui/gfx/mac/nswindow_frame_controls.h +++ b/ui/gfx/mac/nswindow_frame_controls.h @@ -39,6 +39,7 @@ GFX_EXPORT void ApplyNSWindowSizeConstraints(NSWindow* window, const gfx::Size& max_size, bool can_resize, bool can_fullscreen); +GFX_EXPORT void SetNSWindowShowInTaskbar(NSWindow* window, bool show); } // namespace gfx diff --git a/ui/gfx/mac/nswindow_frame_controls.mm b/ui/gfx/mac/nswindow_frame_controls.mm index 133aae6cf7a7a..bae685ffd0cf7 100644 --- a/ui/gfx/mac/nswindow_frame_controls.mm +++ b/ui/gfx/mac/nswindow_frame_controls.mm @@ -58,6 +58,22 @@ void SetNSWindowAlwaysOnTop(NSWindow* window, [window setCollectionBehavior:behavior]; } +void SetNSWindowShowInTaskbar(NSWindow* window, bool show) { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + if (!show) { + NSArray* windowList = [[NSArray alloc] init]; + windowList = [NSWindow windowNumbersWithOptions:NSWindowNumberListAllSpaces]; + for (unsigned int i = 0; i < [windowList count]; ++i) { + NSWindow *window = [NSApp windowWithWindowNumber:[[windowList objectAtIndex:i] integerValue]]; + [window setCanHide:NO]; + } + TransformProcessType(&psn, kProcessTransformToUIElementApplication); + } + else { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + } +} + void SetNSWindowVisibleOnAllWorkspaces(NSWindow* window, bool always_visible) { NSWindowCollectionBehavior behavior = [window collectionBehavior]; if (always_visible) diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h index bbe62a47f335b..fb0d96e25a58c 100644 --- a/ui/message_center/public/cpp/notification.h +++ b/ui/message_center/public/cpp/notification.h @@ -397,8 +397,7 @@ class MESSAGE_CENTER_PUBLIC_EXPORT Notification { } bool should_show_settings_button() const { - return optional_fields_.settings_button_handler != - SettingsButtonHandler::NONE; + return false; } FullscreenVisibility fullscreen_visibility() const { diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index e28f4563676e7..6fef0cc44f235 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc @@ -175,7 +175,7 @@ void MessagePopupCollection::UpdateWidgets() { if (!view->IsManuallyExpandedOrCollapsed()) view->SetExpanded(view->IsAutoExpandingAllowed()); -#if !defined(OS_CHROMEOS) +#if 0 view->set_context_menu_controller(context_menu_controller_.get()); #endif diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc index 374fed273be42..4ddc396348bef 100644 --- a/ui/native_theme/native_theme_win.cc +++ b/ui/native_theme/native_theme_win.cc @@ -55,6 +55,7 @@ const int kSystemColors[] = { COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT, COLOR_HOTLIGHT, + COLOR_MENU, COLOR_MENUHIGHLIGHT, COLOR_SCROLLBAR, COLOR_WINDOW, @@ -468,6 +469,10 @@ SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const { case kColorId_ButtonHoverColor: return kButtonHoverColor; + // Menu + case kColorId_MenuBackgroundColor: + return system_colors_[COLOR_MENU]; + // Label case kColorId_LabelEnabledColor: return system_colors_[COLOR_BTNTEXT]; diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm index 25742569c7f77..75be3d8a9f53d 100644 --- a/ui/shell_dialogs/select_file_dialog_mac.mm +++ b/ui/shell_dialogs/select_file_dialog_mac.mm @@ -194,6 +194,9 @@ - (void)popupAction:(id)sender; file_types ? file_types->extensions.size() > 1 : true; if (type == SELECT_SAVEAS_FILE) { +#if 1 //NWJS#6091: extension was hidden + [dialog setExtensionHidden:NO]; +#else // When file extensions are hidden and removing the extension from // the default filename gives one which still has an extension // that OS X recognizes, it will get confused and think the user @@ -208,6 +211,7 @@ - (void)popupAction:(id)sender; } else { [dialog setCanSelectHiddenExtension:YES]; } +#endif } else { NSOpenPanel* open_dialog = base::mac::ObjCCastStrict<NSOpenPanel>(dialog); @@ -226,7 +230,7 @@ - (void)popupAction:(id)sender; else [open_dialog setCanCreateDirectories:NO]; - NSString *prompt = (type == SELECT_UPLOAD_FOLDER) + NSString *prompt = (false && type == SELECT_UPLOAD_FOLDER) ? l10n_util::GetNSString(IDS_SELECT_UPLOAD_FOLDER_BUTTON_TITLE) : l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE); [open_dialog setPrompt:prompt]; diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc index c2208efd854ab..0f7218e168a3e 100644 --- a/ui/shell_dialogs/select_file_dialog_win.cc +++ b/ui/shell_dialogs/select_file_dialog_win.cc @@ -542,7 +542,7 @@ bool SelectFileDialogImpl::RunSelectFolderDialog( if (title.empty() && params.type == SELECT_UPLOAD_FOLDER) { // If it's for uploading don't use default dialog title to // make sure we clearly tell it's for uploading. - title = l10n_util::GetStringUTF16(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE); + title = l10n_util::GetStringUTF16(IDS_SELECT_FOLDER_DIALOG_TITLE); } wchar_t dir_buffer[MAX_PATH + 1]; @@ -560,12 +560,14 @@ bool SelectFileDialogImpl::RunSelectFolderDialog( SelectFolderDialogOptions dialog_options = {0}; if (path->value().length()) dialog_options.default_path = path->value().c_str(); +#if 0 if (params.type == SELECT_UPLOAD_FOLDER) { dialog_options.is_upload = true; } if (params.type == SELECT_UPLOAD_FOLDER || params.type == SELECT_EXISTING_FOLDER) browse_info.ulFlags |= BIF_NONEWFOLDERBUTTON; +#endif if (dialog_options.is_upload || dialog_options.default_path) { browse_info.lParam = reinterpret_cast<LPARAM>(&dialog_options); browse_info.lpfn = &BrowseCallbackProc; diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 29ebbdcf7cecd..7d65549da831f 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd @@ -609,6 +609,12 @@ need to be translated for each locale.--> <message name="IDS_APP_SEARCH_MODIFIER" desc="Search key shortcut modifier"> Search+<ph name="KEY_COMBO_NAME">$1<ex>C</ex></ph> </message> + <message name="IDS_APP_WINDOWS_MODIFIER" desc="Command key shortcut modifier"> + Win+<ph name="KEY_COMBO_NAME">$1<ex>C</ex></ph> + </message> + <message name="IDS_APP_SUPER_MODIFIER" desc="Command key shortcut modifier"> + Super+<ph name="KEY_COMBO_NAME">$1<ex>C</ex></ph> + </message> <!-- Byte size units --> <message name="IDS_APP_BYTES" desc="Units tag indicating a quantity of bytes"> diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.cc b/ui/views/accessibility/native_view_accessibility_auralinux.cc index a098c1b587732..59fceb15f8105 100644 --- a/ui/views/accessibility/native_view_accessibility_auralinux.cc +++ b/ui/views/accessibility/native_view_accessibility_auralinux.cc @@ -4,6 +4,8 @@ #include "ui/views/accessibility/native_view_accessibility_auralinux.h" +#include "content/public/browser/browser_thread.h" + #include <algorithm> #include <memory> #include <vector> diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc index 3f38a24897c62..e2adfbe06a7e9 100644 --- a/ui/views/controls/menu/native_menu_win.cc +++ b/ui/views/controls/menu/native_menu_win.cc @@ -50,7 +50,9 @@ NativeMenuWin::NativeMenuWin(ui::MenuModel* model, HWND system_menu_for) system_menu_for_(system_menu_for), first_item_index_(0), parent_(nullptr), - destroyed_flag_(nullptr) {} + is_popup_menu_(true), + destroyed_flag_(nullptr){ +} NativeMenuWin::~NativeMenuWin() { if (destroyed_flag_) @@ -217,14 +219,18 @@ void NativeMenuWin::ResetNativeMenu() { } else { if (menu_) DestroyMenu(menu_); - menu_ = CreatePopupMenu(); + if (is_popup_menu_) + menu_ = CreatePopupMenu(); + else + menu_ = CreateMenu(); // Rather than relying on the return value of TrackPopupMenuEx, which is // always a command identifier, instead we tell the menu to notify us via // our host window and the WM_MENUCOMMAND message. MENUINFO mi = {0}; mi.cbSize = sizeof(mi); mi.fMask = MIM_STYLE | MIM_MENUDATA; - mi.dwStyle = MNS_NOTIFYBYPOS; + if (is_popup_menu_) + mi.dwStyle = MNS_NOTIFYBYPOS; mi.dwMenuData = reinterpret_cast<ULONG_PTR>(this); SetMenuInfo(menu_, &mi); } diff --git a/ui/views/controls/menu/native_menu_win.h b/ui/views/controls/menu/native_menu_win.h index 03f00a84ead51..158ee3b23e122 100644 --- a/ui/views/controls/menu/native_menu_win.h +++ b/ui/views/controls/menu/native_menu_win.h @@ -33,6 +33,9 @@ class VIEWS_EXPORT NativeMenuWin { void Rebuild(MenuInsertionDelegateWin* delegate); void UpdateStates(); + void set_is_popup_menu(bool flag) { is_popup_menu_ = flag; } + HMENU menu() const { return menu_; } + private: // IMPORTANT: Note about indices. // Functions in this class deal in two index spaces: @@ -100,6 +103,9 @@ class VIEWS_EXPORT NativeMenuWin { // If we're a submenu, this is our parent. NativeMenuWin* parent_; + // A flag to indicate whether to create a menubar or popupmenu. + bool is_popup_menu_; + // If non-null the destructor sets this to true. This is set to non-null while // the menu is showing. It is used to detect if the menu was deleted while // running. diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc index 8fd5d379d3440..0821bead39627 100644 --- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc @@ -101,7 +101,7 @@ std::vector<display::Display> GetFallbackDisplayList() { if (!display::Display::HasForceDeviceScaleFactor() && !display::IsDisplaySizeBlackListed(physical_size)) { const float device_scale_factor = GetDeviceScaleFactor(); - DCHECK_LE(1.0f, device_scale_factor); + //DCHECK_LE(1.0f, device_scale_factor); gfx_display.SetScaleAndBounds(device_scale_factor, bounds_in_pixels); } diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index 288b92c3eadff..dd90b96ac3fc4 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc @@ -417,7 +417,7 @@ bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const { // but merely of the content Chrome draws, so even when the system titlebars // appear opaque (Win 8+), the content above them needs to be transparent, or // they'll be covered by a black (undrawn) region. - return ShouldUseNativeFrame() && !IsFullscreen(); + return ShouldUseNativeFrame() && (content::g_support_transparency || !IsFullscreen()); } void DesktopWindowTreeHostWin::FrameTypeChanged() { @@ -752,10 +752,19 @@ gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() { : nullptr; } +bool DesktopWindowTreeHostWin::ShouldHandleOnSize() const { + return GetWidget()->widget_delegate()->ShouldHandleOnSize(); +} + void DesktopWindowTreeHostWin::HandleAppDeactivated() { native_widget_delegate_->SetAlwaysRenderAsActive(false); } +bool DesktopWindowTreeHostWin::HandleSize(UINT param, const gfx::Size& new_size) { + return GetWidget()->widget_delegate() && + GetWidget()->widget_delegate()->HandleSize(param, new_size); +} + void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) { // This can be invoked from HWNDMessageHandler::Init(), at which point we're // not in a good state and need to ignore it. @@ -772,7 +781,7 @@ bool DesktopWindowTreeHostWin::HandleAppCommand(short command) { // We treat APPCOMMAND ids as an extension of our command namespace, and just // let the delegate figure out what to do... return GetWidget()->widget_delegate() && - GetWidget()->widget_delegate()->ExecuteWindowsCommand(command); + GetWidget()->widget_delegate()->ExecuteAppCommand(command); } void DesktopWindowTreeHostWin::HandleCancelMode() { @@ -785,6 +794,9 @@ void DesktopWindowTreeHostWin::HandleCaptureLost() { void DesktopWindowTreeHostWin::HandleClose() { GetWidget()->Close(); + //bugfix where transparent window size is getting smaller during closing + if (content::g_support_transparency && message_handler_->is_translucent()) + window_enlargement_ = gfx::Vector2d(0, 0); } bool DesktopWindowTreeHostWin::HandleCommand(int command) { diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h index 327e4fb5df8d2..c79a06f789b66 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h @@ -151,6 +151,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin // Overridden from HWNDMessageHandlerDelegate: ui::InputMethod* GetHWNDMessageDelegateInputMethod() override; + bool ShouldHandleOnSize() const override; + bool HandleSize(UINT param, const gfx::Size& new_size) override; bool HasNonClientView() const override; FrameMode GetFrameMode() const override; bool HasFrame() const override; diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index cbfbfcbdcdb76..57e3cace1160d 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc @@ -66,6 +66,10 @@ DEFINE_UI_CLASS_PROPERTY_TYPE(views::DesktopWindowTreeHostX11*); +namespace content { + extern bool g_support_transparency; +} + namespace views { DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture = diff --git a/ui/views/widget/native_widget_delegate.h b/ui/views/widget/native_widget_delegate.h index 018bc2ce9d392..2f1a76e15130b 100644 --- a/ui/views/widget/native_widget_delegate.h +++ b/ui/views/widget/native_widget_delegate.h @@ -54,6 +54,7 @@ class VIEWS_EXPORT NativeWidgetDelegate { // problems. virtual void SetAlwaysRenderAsActive(bool always_render_as_active) = 0; virtual bool IsAlwaysRenderAsActive() const = 0; + virtual bool NWCanClose(bool user_force = false) const = 0; // Called when the activation state of a window has changed. // Returns true if this event should be handled. diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index bf4b1d07f7fe0..9ac25ebc1b28b 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -566,7 +566,7 @@ void Widget::SetShape(std::unique_ptr<ShapeRects> shape) { native_widget_->SetShape(std::move(shape)); } -void Widget::Close() { +void Widget::Close(bool force) { if (widget_closed_) { // It appears we can hit this code path if you close a modal dialog then // close the last browser before the destructor is hit, which triggers @@ -576,6 +576,8 @@ void Widget::Close() { if (non_client_view_ && !non_client_view_->CanClose()) return; + if (!force && !NWCanClose()) + return; // The actions below can cause this function to be called again, so mark // |this| as closed early. See crbug.com/714334 @@ -1023,6 +1025,10 @@ bool Widget::IsAlwaysRenderAsActive() const { return always_render_as_active_; } +bool Widget::NWCanClose(bool user_force) const { + return widget_delegate_->NWCanClose(user_force); +} + bool Widget::OnNativeWidgetActivationChanged(bool active) { if (g_disable_activation_change_handling_) return false; diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index bc3b94fa4f3b7..2746aabb24bb1 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -486,7 +486,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, void SetShape(std::unique_ptr<ShapeRects> shape); // Hides the widget then closes it after a return to the message loop. - virtual void Close(); + virtual void Close(bool force = false); // TODO(beng): Move off public API. // Closes the widget immediately. Compare to |Close|. This will destroy the @@ -790,6 +790,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, bool IsAlwaysRenderAsActive() const override; void SetAlwaysRenderAsActive(bool always_render_as_active) override; bool OnNativeWidgetActivationChanged(bool active) override; + bool NWCanClose(bool user_force = false) const override; void OnNativeFocus() override; void OnNativeBlur() override; void OnNativeWidgetVisibilityChanging(bool visible) override; diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc index ea1c78ff1d6f1..ce58d5c0ed949 100644 --- a/ui/views/widget/widget_delegate.cc +++ b/ui/views/widget/widget_delegate.cc @@ -71,6 +71,10 @@ bool WidgetDelegate::CanActivate() const { return can_activate_; } +bool WidgetDelegate::NWCanClose(bool user_force) const { + return true; +} + ui::ModalType WidgetDelegate::GetModalType() const { return ui::MODAL_TYPE_NONE; } @@ -95,6 +99,10 @@ bool WidgetDelegate::ShouldShowCloseButton() const { return true; } +bool WidgetDelegate::ShouldHandleOnSize() const { + return false; +} + gfx::ImageSkia WidgetDelegate::GetWindowAppIcon() { // Use the window icon as app icon by default. return GetWindowIcon(); @@ -113,6 +121,14 @@ bool WidgetDelegate::ExecuteWindowsCommand(int command_id) { return false; } +bool WidgetDelegate::ExecuteAppCommand(int command_id) { + return ExecuteWindowsCommand(command_id); +} + +bool WidgetDelegate::HandleSize(unsigned int param, const gfx::Size& size) { + return false; +} + std::string WidgetDelegate::GetWindowName() const { return std::string(); } diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h index c1cfaebc4172a..ce3465bcb269e 100644 --- a/ui/views/widget/widget_delegate.h +++ b/ui/views/widget/widget_delegate.h @@ -67,6 +67,7 @@ class VIEWS_EXPORT WidgetDelegate { // Returns true if the window can be activated. virtual bool CanActivate() const; + virtual bool NWCanClose(bool user_force = false) const; // Returns the modal type that applies to the widget. Default is // ui::MODAL_TYPE_NONE (not modal). @@ -86,6 +87,8 @@ class VIEWS_EXPORT WidgetDelegate { // Returns true if the window should show a close button in the title bar. virtual bool ShouldShowCloseButton() const; + virtual bool ShouldHandleOnSize() const; + // Returns the app icon for the window. On Windows, this is the ICON_BIG used // in Alt-Tab list and Win7's taskbar. virtual gfx::ImageSkia GetWindowAppIcon(); @@ -100,6 +103,10 @@ class VIEWS_EXPORT WidgetDelegate { // was handled, false if it was not. virtual bool ExecuteWindowsCommand(int command_id); + virtual bool ExecuteAppCommand(int command_id); + + virtual bool HandleSize(unsigned int param, const gfx::Size& size); + // Returns the window's name identifier. Used to identify this window for // state restoration. virtual std::string GetWindowName() const; diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc index c7296fed234dd..ea71cbb901636 100644 --- a/ui/views/widget/widget_hwnd_utils.cc +++ b/ui/views/widget/widget_hwnd_utils.cc @@ -10,6 +10,7 @@ #include "build/build_config.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/ui_base_switches.h" +#include "ui/display/display.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/win/hwnd_message_handler.h" @@ -92,8 +93,19 @@ void CalculateWindowStylesFromInitParams( native_widget_delegate->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0; // See layered window comment below. - if (is_translucent) - *style &= ~(WS_THICKFRAME | WS_CAPTION); + if (content::g_support_transparency && is_translucent) { + if (params.remove_standard_frame) { + *style &= ~(WS_CAPTION); + } + if (!native_widget_delegate->IsDialogBox() && !native_widget_delegate->IsModal()) { + if (content::g_force_cpu_draw) + *ex_style |= WS_EX_LAYERED; + } + } else { + if (is_translucent) + *style &= ~(WS_THICKFRAME | WS_CAPTION); + } + break; } case Widget::InitParams::TYPE_CONTROL: @@ -153,9 +165,10 @@ void ConfigureWindowStyles( // // This doesn't work when Aero is disabled, so disable it in that case. // Software composited windows can continue to use WS_EX_LAYERED. - bool is_translucent = + bool is_translucent = !content::g_support_transparency ? (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW && - (ui::win::IsAeroGlassEnabled() || params.force_software_compositing)); + (ui::win::IsAeroGlassEnabled() || params.force_software_compositing)) : + (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW || params.force_software_compositing); CalculateWindowStylesFromInitParams(params, widget_delegate, native_widget_delegate, is_translucent, diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index cadeb23226209..ec0649b653503 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc @@ -343,6 +343,7 @@ base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap>:: // HWNDMessageHandler, public: long HWNDMessageHandler::last_touch_or_pen_message_time_ = 0; +#define TRANSPARENCY(original, addition) content::g_support_transparency ? original addition : original HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) : delegate_(delegate), @@ -393,6 +394,16 @@ void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) { // Create the window. WindowImpl::Init(parent, bounds); + if (content::g_support_transparency && is_translucent_ && !content::g_force_cpu_draw) { + //WS_CAPTION style is somehow applied, during window creation, needs to update the style + set_window_style((DWORD)GetWindowLong(hwnd(), GWL_STYLE)); + //copied from WindowImpl::Init, see "First nccalcszie" comment + if (window_style() & WS_CAPTION) { + SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW); + } + } if (!called_enable_non_client_dpi_scaling_ && delegate_->HasFrame() && @@ -835,13 +846,16 @@ void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) { if (!window_icon.isNull()) { base::win::ScopedHICON previous_icon = std::move(window_icon_); - window_icon_ = IconUtil::CreateHICONFromSkBitmap(*window_icon.bitmap()); + window_icon_ = + IconUtil::CreateHICONFromSkBitmapSizedTo(*window_icon.bitmap(), + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); SendMessage(hwnd(), WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(window_icon_.get())); } if (!app_icon.isNull()) { base::win::ScopedHICON previous_icon = std::move(app_icon_); - app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()); + app_icon_ = IconUtil::CreateHICONFromSkBitmapSizedTo(*app_icon.bitmap(), + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); SendMessage(hwnd(), WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(app_icon_.get())); } @@ -876,7 +890,7 @@ void HWNDMessageHandler::SizeConstraintsChanged() { // Windows cannot have WS_THICKFRAME set if translucent. // See CalculateWindowStylesFromInitParams(). - if (delegate_->CanResize() && !is_translucent_) { + if (delegate_->CanResize() && (content::g_support_transparency || !is_translucent_)) { style |= WS_THICKFRAME | WS_MAXIMIZEBOX; if (!delegate_->CanMaximize()) style &= ~WS_MAXIMIZEBOX; @@ -888,6 +902,10 @@ void HWNDMessageHandler::SizeConstraintsChanged() { } else { style &= ~WS_MINIMIZEBOX; } + if (content::g_support_transparency && is_translucent_ && !content::g_force_cpu_draw) { + //WS_CAPTION needs to be removed on transparent window, or else the Title bar will be rendered + style &= ~WS_CAPTION; + } SetWindowLong(hwnd(), GWL_STYLE, style); } @@ -1335,6 +1353,10 @@ bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const { border_thickness -= 1; *insets = gfx::Insets( border_thickness, border_thickness, border_thickness, border_thickness); + if (content::g_force_cpu_draw && is_translucent_ && !delegate_->HasFrame()) { + //part of maximize_hack code + insets->Set(0, 0, -1, -1); + } return true; } @@ -1351,7 +1373,7 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) { // allow for a custom hit mask. if (!is_translucent_ && !custom_window_region_.is_valid() && (IsFrameSystemDrawn() || !delegate_->HasNonClientView())) { - if (force) + if (force || content::g_force_cpu_draw) SetWindowRgn(hwnd(), NULL, redraw); return; } @@ -1375,6 +1397,10 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) { RECT work_rect = mi.rcWork; OffsetRect(&work_rect, -window_rect.left, -window_rect.top); new_region.reset(CreateRectRgnIndirect(&work_rect)); + } else if (content::g_support_transparency && is_translucent_) { + RECT work_rect = window_rect; + OffsetRect(&work_rect, -window_rect.left, -window_rect.top); + new_region.reset(CreateRectRgnIndirect(&work_rect)); } else { gfx::Path window_mask; delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left, @@ -1527,7 +1553,7 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) { MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0); - if (!delegate_->HasFrame()) { + if (TRANSPARENCY(!delegate_->HasFrame(), && !(is_translucent_))) { SetWindowLong(hwnd(), GWL_STYLE, GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION); SendFrameChanged(); @@ -1656,15 +1682,17 @@ void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { if (delegate_->WidgetSizeIsClientSize()) { RECT client_rect, window_rect; GetClientRect(hwnd(), &client_rect); - GetWindowRect(hwnd(), &window_rect); - CR_DEFLATE_RECT(&window_rect, &client_rect); - min_window_size.Enlarge(window_rect.right - window_rect.left, - window_rect.bottom - window_rect.top); - // Either axis may be zero, so enlarge them independently. - if (max_window_size.width()) - max_window_size.Enlarge(window_rect.right - window_rect.left, 0); - if (max_window_size.height()) - max_window_size.Enlarge(0, window_rect.bottom - window_rect.top); + if (client_rect.right > client_rect.left) { + GetWindowRect(hwnd(), &window_rect); + CR_DEFLATE_RECT(&window_rect, &client_rect); + min_window_size.Enlarge(window_rect.right - window_rect.left, + window_rect.bottom - window_rect.top); + // Either axis may be zero, so enlarge them independently. + if (max_window_size.width()) + max_window_size.Enlarge(window_rect.right - window_rect.left, 0); + if (max_window_size.height()) + max_window_size.Enlarge(0, window_rect.bottom - window_rect.top); + } } minmax_info->ptMinTrackSize.x = min_window_size.width(); minmax_info->ptMinTrackSize.y = min_window_size.height(); @@ -1946,10 +1974,11 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) { return 0; } } - + const LONG noTitleBar = (is_translucent_) && !delegate_->HasFrame(); gfx::Insets insets; bool got_insets = GetClientAreaInsets(&insets); - if (!got_insets && !IsFullscreen() && !(mode && !delegate_->HasFrame())) { + if (TRANSPARENCY(!got_insets && !IsFullscreen() && + !(mode && !delegate_->HasFrame()), && !noTitleBar)) { SetMsgHandled(FALSE); return 0; } @@ -2327,6 +2356,17 @@ void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) { // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've // invoked OnSize we ensure the RootView has been laid out. ResetWindowRegion(false, true); + if (delegate_->ShouldHandleOnSize()) + delegate_->HandleSize(param, size); +} + +void HWNDMessageHandler::OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct) { + if (!content::g_support_transparency) + return; + if (nStyleType == GWL_EXSTYLE) + set_window_ex_style(lpStyleStruct->styleNew); + else if (nStyleType == GWL_STYLE) + set_window_style(lpStyleStruct->styleNew); } void HWNDMessageHandler::OnSysCommand(UINT notification_code, @@ -2551,12 +2591,13 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { if (GetClientAreaInsets(&client_area_insets)) expected_maximized_bounds.Inset(client_area_insets.Scale(-1)); } + const bool maximize_hack = content::g_force_cpu_draw && is_translucent_; // Sometimes Windows incorrectly changes bounds of maximized windows after // attaching or detaching additional displays. In this case user can see // non-client area of the window (that should be hidden in normal case). // We should restore window position if problem occurs. const bool incorrect_maximized_bounds = - IsMaximized() && have_new_window_rect && + IsMaximized() && (maximize_hack || have_new_window_rect) && (expected_maximized_bounds.x() != window_pos->x || expected_maximized_bounds.y() != window_pos->y || expected_maximized_bounds.width() != window_pos->cx || @@ -2604,7 +2645,7 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { // Now ignore all immediately-following SetWindowPos() changes. Windows // likes to (incorrectly) recalculate what our position/size should be // and send us further updates. - ignore_window_pos_changes_ = true; + ignore_window_pos_changes_ = !maximize_hack; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&HWNDMessageHandler::StopIgnoringPosChanges, @@ -2994,6 +3035,11 @@ bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message, void HWNDMessageHandler::PerformDwmTransition() { dwm_transition_desired_ = false; + if (content::g_support_transparency && !content::g_force_cpu_draw && is_translucent_) { + const int im = ui::win::IsAeroGlassEnabled() ? -1 : 0; + MARGINS m = { im, im, im, im }; + DwmExtendFrameIntoClientArea(hwnd(), &m); + } UpdateDwmNcRenderingPolicy(); // Don't redraw the window here, because we need to hide and show the window @@ -3002,7 +3048,7 @@ void HWNDMessageHandler::PerformDwmTransition() { // The non-client view needs to update too. delegate_->HandleFrameChanged(); - if (IsVisible() && IsFrameSystemDrawn()) { + if (IsVisible() && IsFrameSystemDrawn() && !content::g_force_cpu_draw) { // For some reason, we need to hide the window after we change from a custom // frame to a native frame. If we don't, the client area will be filled // with black. This seems to be related to an interaction between DWM and diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index 5afb32aa043c0..96910904d9c50 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h @@ -408,6 +408,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, CR_MSG_WM_SETTEXT(OnSetText) CR_MSG_WM_SETTINGCHANGE(OnSettingChange) CR_MSG_WM_SIZE(OnSize) + CR_MSG_WM_STYLECHANGING(OnStyleChanging) CR_MSG_WM_SYSCOMMAND(OnSysCommand) CR_MSG_WM_THEMECHANGED(OnThemeChanged) CR_MSG_WM_TIMECHANGE(OnTimeChange) @@ -467,6 +468,7 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl, LRESULT OnSetText(const wchar_t* text); void OnSettingChange(UINT flags, const wchar_t* section); void OnSize(UINT param, const gfx::Size& size); + void OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct); void OnSysCommand(UINT notification_code, const gfx::Point& point); void OnThemeChanged(); void OnTimeChange(); diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h index 1b2d98a857385..1fce0e12822bd 100644 --- a/ui/views/win/hwnd_message_handler_delegate.h +++ b/ui/views/win/hwnd_message_handler_delegate.h @@ -104,6 +104,10 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0; + // on windows, maximizing sometime is sent through WM_SIZE, not + // WM_SYSCOMMAND, see node-webkit#753 + virtual bool ShouldHandleOnSize() const = 0; + // TODO(beng): Investigate migrating these methods to On* prefixes once // HWNDMessageHandler is the WindowImpl. @@ -131,6 +135,8 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate { // true if the command was handled. virtual bool HandleCommand(int command) = 0; + virtual bool HandleSize(UINT param, const gfx::Size& size) = 0; + // Called when an accelerator is invoked. virtual void HandleAccelerator(const ui::Accelerator& accelerator) = 0; diff --git a/ui/views/window/custom_frame_view.cc b/ui/views/window/custom_frame_view.cc index 22d0bed6be833..62849acc525fa 100644 --- a/ui/views/window/custom_frame_view.cc +++ b/ui/views/window/custom_frame_view.cc @@ -6,6 +6,7 @@ #include <algorithm> #include <vector> +#include "ui/gfx/image/image_skia_operations.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -112,7 +113,10 @@ void CustomFrameView::Init(Widget* frame) { IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P); if (frame_->widget_delegate()->ShouldShowWindowIcon()) { + gfx::ImageSkia icon; window_icon_ = new ImageButton(this); + icon = frame_->widget_delegate()->GetWindowAppIcon(); + window_icon_->SetImage(Button::STATE_NORMAL, &icon); AddChildView(window_icon_); } } @@ -192,8 +196,16 @@ void CustomFrameView::ResetWindowControls() { } void CustomFrameView::UpdateWindowIcon() { - if (window_icon_) + if (window_icon_) { + gfx::ImageSkia icon; + icon = frame_->widget_delegate()->GetWindowAppIcon(); + int size = IconSize(); + gfx::ImageSkia icon2 = gfx::ImageSkiaOperations::CreateResizedImage(icon, + skia::ImageOperations::RESIZE_BEST, + gfx::Size(size, size)); + window_icon_->SetImage(Button::STATE_NORMAL, &icon2); window_icon_->SchedulePaint(); + } } void CustomFrameView::UpdateWindowTitle() { From e0d3df209ca91bcbedad448e75076427b17241ea Mon Sep 17 00:00:00 2001 From: Abdusalam Dihan <adihan@cafex.com> Date: Thu, 26 Jul 2018 13:26:16 +0100 Subject: [PATCH 3/3] Changes to chromium for extracting the exeName and window position when using the Desktop Capture Monitor on windows --- .../api/desktop_capture/desktop_capture_api.cc | 10 +++++++++- chrome/browser/media/webrtc/desktop_media_list.h | 6 ++++++ .../browser/media/webrtc/desktop_media_list_base.cc | 11 +++++++++-- chrome/browser/media/webrtc/desktop_media_list_base.h | 3 ++- .../browser/media/webrtc/native_desktop_media_list.cc | 5 ++++- chrome/browser/media/webrtc/tab_desktop_media_list.cc | 2 +- extensions/common/manifest_constants.cc | 1 + extensions/common/manifest_constants.h | 1 + .../tools/bindings/generators/mojom_java_generator.py | 2 +- 9 files changed, 34 insertions(+), 7 deletions(-) diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc index 1e854c8286d9c..3792fb92909dc 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc @@ -14,6 +14,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/origin_util.h" #include "net/base/url_util.h" +#include "extensions/common/manifest_constants.h" namespace extensions { @@ -93,7 +94,14 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() { // NWJS app allows running on origins other than `chrome-extension://*/*`. // The origin should then be from the senders URL, in order not to fail // the origin checking in `DesktopStreamsRegistry::RequestMediaForStreamId`. - origin = extension()->is_nwjs_app() ? web_contents->GetURL().GetOrigin() : extension()->url(); + if (extension()->is_nwjs_app()) { + std::string desktopStreamOriginOverride; + extension()->manifest()->GetString(manifest_keys::kNWJSDesktopStreamOriginOverride, &desktopStreamOriginOverride); + origin = desktopStreamOriginOverride.empty() ? web_contents->GetURL().GetOrigin() : GURL(desktopStreamOriginOverride); + } + else { + origin = extension()->url(); + } DCHECK(web_contents); } diff --git a/chrome/browser/media/webrtc/desktop_media_list.h b/chrome/browser/media/webrtc/desktop_media_list.h index 8e02a8a95eb07..37e2b751829eb 100644 --- a/chrome/browser/media/webrtc/desktop_media_list.h +++ b/chrome/browser/media/webrtc/desktop_media_list.h @@ -28,6 +28,12 @@ class DesktopMediaList { // The thumbnail for the source. gfx::ImageSkia thumbnail; + + // Name of the executable. + base::string16 exeName; + + Source(); + Source(const Source& other); }; virtual ~DesktopMediaList() {} diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc index 43dd95ef72f5b..bf360ec22e760 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_base.cc +++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc @@ -13,6 +13,11 @@ using content::BrowserThread; using content::DesktopMediaID; +DesktopMediaList::Source::Source() { +} + +DesktopMediaList::Source::Source(const Source& other) = default; + DesktopMediaListBase::DesktopMediaListBase(base::TimeDelta update_period) : update_period_(update_period), weak_factory_(this) {} @@ -55,8 +60,9 @@ DesktopMediaID::Type DesktopMediaListBase::GetMediaListType() const { DesktopMediaListBase::SourceDescription::SourceDescription( DesktopMediaID id, - const base::string16& name) - : id(id), name(name) {} + const base::string16& name, + const base::string16& exeName) + : id(id), name(name), exeName(exeName) {} void DesktopMediaListBase::UpdateSourcesList( const std::vector<SourceDescription>& new_sources) { @@ -85,6 +91,7 @@ void DesktopMediaListBase::UpdateSourcesList( sources_.insert(sources_.begin() + i, Source()); sources_[i].id = new_sources[i].id; sources_[i].name = new_sources[i].name; + sources_[i].exeName = new_sources[i].exeName; observer_->OnSourceAdded(this, i); } } diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.h b/chrome/browser/media/webrtc/desktop_media_list_base.h index 746df1210aa92..a6393bd9dee04 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_base.h +++ b/chrome/browser/media/webrtc/desktop_media_list_base.h @@ -36,10 +36,11 @@ class DesktopMediaListBase : public DesktopMediaList { protected: struct SourceDescription { - SourceDescription(content::DesktopMediaID id, const base::string16& name); + SourceDescription(content::DesktopMediaID id, const base::string16& name, const base::string16& exeName); content::DesktopMediaID id; base::string16 name; + base::string16 exeName; }; virtual void Refresh() = 0; diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc index 0c9ba953cb3c2..e693a01441ed2 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.cc +++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc @@ -127,6 +127,7 @@ void NativeDesktopMediaList::Worker::Refresh( bool mutiple_sources = sources.size() > 1; base::string16 title; + base::string16 exeName; for (size_t i = 0; i < sources.size(); ++i) { switch (type_) { case DesktopMediaID::TYPE_SCREEN: @@ -138,6 +139,7 @@ void NativeDesktopMediaList::Worker::Refresh( static_cast<int>(i + 1)) : l10n_util::GetStringUTF16( IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME); + exeName = base::UTF8ToUTF16(sources[i].exeName); break; case DesktopMediaID::TYPE_WINDOW: @@ -145,13 +147,14 @@ void NativeDesktopMediaList::Worker::Refresh( if (sources[i].id == view_dialog_id) continue; title = base::UTF8ToUTF16(sources[i].title); + exeName = base::UTF8ToUTF16(sources[i].exeName); break; default: NOTREACHED(); } result.push_back( - SourceDescription(DesktopMediaID(type_, sources[i].id), title)); + SourceDescription(DesktopMediaID(type_, sources[i].id), title, exeName)); } BrowserThread::PostTask( diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list.cc b/chrome/browser/media/webrtc/tab_desktop_media_list.cc index 2beef7438570f..1c14782cb0e8f 100644 --- a/chrome/browser/media/webrtc/tab_desktop_media_list.cc +++ b/chrome/browser/media/webrtc/tab_desktop_media_list.cc @@ -108,7 +108,7 @@ void TabDesktopMediaList::Refresh() { // Get tab's last active time stamp. const base::TimeTicks t = contents->GetLastActiveTime(); tab_map.insert( - std::make_pair(t, SourceDescription(media_id, contents->GetTitle()))); + std::make_pair(t, SourceDescription(media_id, contents->GetTitle(), base::string16()))); // Get favicon for tab. favicon::FaviconDriver* favicon_driver = diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index 35c9762516b1a..707888bb7f42f 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc @@ -16,6 +16,7 @@ const char kNWJSMain[] = "main"; const char kNWJSMixedContext[] = "mixed_context"; const char kNWJSEnableNode[] = "nodejs"; const char kNWJSDomain[] = "domain"; +const char kNWJSDesktopStreamOriginOverride[] = "desktop_stream_origin_override"; const char kAboutPage[] = "about_page"; const char kAction[] = "action"; diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index 4f8a6afd4b5d7..10bae99fd2911 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h @@ -19,6 +19,7 @@ extern const char kNWJSMain[]; extern const char kNWJSMixedContext[]; extern const char kNWJSEnableNode[]; extern const char kNWJSDomain[]; +extern const char kNWJSDesktopStreamOriginOverride[]; extern const char kAboutPage[]; extern const char kAction[]; diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py index 0f2b6181825ec..ee30845f11a0b 100644 --- a/mojo/public/tools/bindings/generators/mojom_java_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py @@ -411,7 +411,7 @@ def TempDir(): try: yield dirname finally: - shutil.rmtree(dirname) + shutil.rmtree(dirname, ignore_errors=True) class Generator(generator.Generator): def _GetJinjaExports(self):